Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@traptitech/traq-markdown-it

Package Overview
Dependencies
Maintainers
2
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@traptitech/traq-markdown-it - npm Package Compare versions

Comparing version 2.2.7 to 2.3.0

dist/default/language_subset.d.ts

2

dist/highlight.d.ts

@@ -1,1 +0,1 @@

export declare const createHighlightFunc: (preClass: string, withCaption?: boolean) => (code: string, lang: string) => string;
export declare const createHighlightFunc: (preClass: string, withCaption?: boolean, useSubsetForAuto?: boolean) => (code: string, lang: string) => string;

@@ -9,10 +9,16 @@ /// <reference types="../src/types/markdown-it-mark" />

import { Store } from './Store';
import { EmbeddingsExtractedMessage } from './embeddingExtractor';
export { Store } from './Store';
export { Embedding, EmbeddingFile, EmbeddingMessage, EmbeddingsExtractedMessage } from './embeddingExtractor';
export declare type MarkdownRenderResult = EmbeddingsExtractedMessage & {
renderedText: string;
};
export default class {
readonly md: MarkdownIt;
constructor(store: Store, whitelist?: string[]);
readonly embeddingRegExp: RegExp;
constructor(store: Store, whitelist: string[] | undefined, embeddingOrigin: string);
setPlugin(store: Store, whitelist: string[]): void;
setRendererRule(): void;
render(text: string): string;
renderInline(text: string): string;
render(text: string): MarkdownRenderResult;
renderInline(text: string): MarkdownRenderResult;
}

@@ -19,0 +25,0 @@ export { createHighlightFunc } from './highlight';

@@ -472,4 +472,6 @@ 'use strict';

var defaultSubset = ['actionscript', 'awk', 'bash', 'basic', 'bnf', 'brainfuck', 'csharp', 'h', 'cpp', 'cmake', 'coq', 'css', 'clojure', 'coffeescript', 'crystal', 'd', 'dart', 'delphi', 'diff', 'django', 'dockerfile', 'elixir', 'elm', 'fsharp', 'fortran', 'go', 'gradle', 'groovy', 'xml', 'http', 'haml', 'handlebars', 'haxe', 'ini', 'json', 'java', 'javascript', 'kotlin', 'tex', 'less', 'lisp', 'livescript', 'lua', 'makefile', 'markdown', 'mathematica', 'matlab', 'moonscript', 'nginx', 'nimrod', 'ocaml', 'objectivec', 'glsl', 'php', 'perl', 'plaintext', 'pgsql', 'powershell', 'processing', 'prolog', 'protobuf', 'python', 'k', 'r', 'ruby', 'scss', 'sql', 'scheme', 'shell', 'stylus', 'swift', 'twig', 'typescript', 'vbnet', 'vbscript', 'verilog', 'vim', 'x86asm', 'xquery', 'yaml', 'zephir'];
const noHighlightRe = /^(no-?highlight|plain|text)$/i;
const createHighlightFunc = (preClass, withCaption = true) => (code, lang) => {
const createHighlightFunc = (preClass, withCaption = true, useSubsetForAuto = true) => (code, lang) => {
let langName, langCaption;

@@ -494,3 +496,3 @@ let citeTag = '';

} else {
const result = hljs.highlightAuto(code);
const result = hljs.highlightAuto(code, useSubsetForAuto ? defaultSubset : undefined);
return `<pre class="${preClass}">${citeTag}<code class="lang-${result.language}">${result.value}</code></pre>`;

@@ -502,2 +504,122 @@ }

const createEmbeddingRegexp = embeddingOrigin => RegExp(`${embeddingOrigin}/(files|messages)/([\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12})(\\s*)`, 'g');
/**
* markdownから埋め込みURLを抽出する
*
* @param regexp
* マッチに使う正規表現。グループは順に
*
* - 種別
* - UUID
* - 削除されるスペース
*
* であることを期待する
*/
const embeddingExtractor = (rawMessage, regexp) => {
const embeddings = [];
const knownIdSet = new Set();
const matches = rawMessage.matchAll(regexp);
/** 連続したマッチの開始インデックス */
let sequenceStartIndex = 0;
/** スペースを含んだ、連続したマッチ全体の終了インデックス */
let sequenceEndIndex = 0;
for (const match of matches) {
var _match$index, _match$0$length, _match$, _match$3$length, _match$2, _match$3, _match$4;
const matchIndex = (_match$index = match.index) !== null && _match$index !== void 0 ? _match$index : 0;
const matchLength = (_match$0$length = (_match$ = match[0]) === null || _match$ === void 0 ? void 0 : _match$.length) !== null && _match$0$length !== void 0 ? _match$0$length : 0;
const spaceLength = (_match$3$length = (_match$2 = match[3]) === null || _match$2 === void 0 ? void 0 : _match$2.length) !== null && _match$3$length !== void 0 ? _match$3$length : 0;
const type = (_match$3 = match[1]) !== null && _match$3 !== void 0 ? _match$3 : '';
const id = (_match$4 = match[2]) !== null && _match$4 !== void 0 ? _match$4 : '';
const startIndex = matchIndex;
const endIndex = matchIndex + matchLength - spaceLength;
if (!knownIdSet.has(id)) {
if (type === 'files') {
embeddings.push({
type: 'file',
id,
startIndex,
endIndex
});
}
if (type === 'messages') {
embeddings.push({
type: 'message',
id,
startIndex,
endIndex
});
}
knownIdSet.add(id);
}
if (startIndex !== sequenceEndIndex) {
// 連続したマッチではなかった
sequenceStartIndex = startIndex;
}
sequenceEndIndex = matchIndex + matchLength;
}
const hasSequenceReachedEos = sequenceEndIndex === rawMessage.length;
return {
rawText: rawMessage,
text: hasSequenceReachedEos ? rawMessage.substring(0, sequenceStartIndex) : rawMessage,
embeddings
};
};
/**
* markdownから埋め込みURLを抽出してすべて置換する
*
* @param regexp
* マッチに使う正規表現。グループは順に
*
* - 種別
* - UUID
* - 削除されるスペース
*
* であることを期待する
*/
const embeddingReplacer = (rawMessage, regexp) => {
const {
text,
embeddings
} = embeddingExtractor(rawMessage, regexp);
let newText = text; // 置換で文字数がずれるのでずれた数を保持する
let placeDiff = 0;
for (const embedding of embeddings) {
// 末尾のものは抽出で消えているので置換しない
if (text.length <= embedding.startIndex) break;
let replaced;
if (embedding.type === 'file') {
replaced = '[[添付ファイル]]';
} else if (embedding.type === 'message') {
replaced = '[[添付メッセージ]]';
} else {
const invalid = embedding;
throw new Error(`embeddingReplacer unknown embedding type: ${invalid}`);
}
newText = newText.slice(0, placeDiff + embedding.startIndex) + replaced + newText.slice(placeDiff + embedding.endIndex);
placeDiff += replaced.length - (embedding.endIndex - embedding.startIndex);
}
return {
rawText: rawMessage,
text: newText,
embeddings
};
};
const defaultLabels = ['success', 'info', 'warning', 'danger'];

@@ -518,3 +640,3 @@ const useContainer = (md, labels = defaultLabels) => {

class index {
constructor(store, whitelist = defaultWhitelist) {
constructor(store, whitelist = defaultWhitelist, embeddingOrigin) {
this.md = new MarkdownIt({

@@ -525,2 +647,3 @@ breaks: true,

});
this.embeddingRegExp = createEmbeddingRegexp(embeddingOrigin);
this.setRendererRule();

@@ -548,6 +671,3 @@ this.setPlugin(store, whitelist);

setRendererRule() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const blockState = this.md.block.State;
blockState.prototype.skipEmptyLines = function skipEmptyLines(from) {
this.md.block.State.prototype.skipEmptyLines = function skipEmptyLines(from) {
for (let max = this.lineMax; from < max; from++) {

@@ -566,7 +686,11 @@ if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {

render(text) {
return this.md.render(text, {});
const data = embeddingExtractor(text, this.embeddingRegExp);
return { ...data,
renderedText: this.md.render(data.text, {})
};
}
renderInline(text) {
const parsed = this.md.parseInline(text, {});
const data = embeddingReplacer(text, this.embeddingRegExp);
const parsed = this.md.parseInline(data.text, {});
const tokens = parsed[0].children || [];

@@ -591,3 +715,5 @@ const rendered = [];

return rendered.join('');
return { ...data,
renderedText: rendered.join('')
};
}

@@ -594,0 +720,0 @@

@@ -1,2 +0,2 @@

"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0}),require("core-js/modules/web.dom-collections.iterator");var t=e(require("markdown-it")),r=e(require("markdown-it-mark")),n=e(require("@traptitech/markdown-it-spoiler")),s=e(require("markdown-it-regexp"));require("core-js/modules/es.string.replace");var o=e(require("markdown-it-json")),i=e(require("@traptitech/markdown-it-katex")),a=e(require("katex")),u=e(require("markdown-it-link-attributes")),l=e(require("markdown-it-image-filter")),c=e(require("highlight.js")),p=e(require("markdown-it-container"));function h(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&g(e,t)}function f(e){return(f=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function g(e,t){return(g=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function d(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function m(e,t,r){return(m=d()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return r&&g(s,r.prototype),s}).apply(null,arguments)}function y(e){var t="function"==typeof Map?new Map:void 0;return(y=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return m(e,arguments,f(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),g(r,e)})(e)}function x(e,t){x=function(e,t){return new o(e,void 0,t)};var r=y(RegExp),n=RegExp.prototype,s=new WeakMap;function o(e,t,n){var o=r.call(this,e,t);return s.set(o,n||s.get(e)),o}function i(e,t){var r=s.get(t);return Object.keys(r).reduce((function(t,n){return t[n]=e[r[n]],t}),Object.create(null))}return h(o,r),o.prototype.exec=function(e){var t=n.exec.call(this,e);return t&&(t.groups=i(t,this)),t},o.prototype[Symbol.replace]=function(e,t){if("string"==typeof t){var r=s.get(this);return n[Symbol.replace].call(this,e,t.replace(/\$<([^>]+)>/g,(function(e,t){return"$"+r[t]})))}if("function"==typeof t){var o=this;return n[Symbol.replace].call(this,e,(function(){var e=[];return e.push.apply(e,arguments),"object"!=typeof e[e.length-1]&&e.push(i(e,o)),t.apply(this,e)}))}return n[Symbol.replace].call(this,e,t)},x.apply(this,arguments)}const k=/[&<>"]/g,_=new Map([["&","&amp;"],["<","&lt;"],[">","&gt;"],['"',"&quot;"]]),v=e=>_.get(e),w=e=>k.test(e)?e.replace(k,v):e;let b,$="";const q=new Set(["rotate","rotate-inv","wiggle","parrot","zoom","inversion","turn","turn-v","happa","pyon","flashy","pull","atsumori","stretch","stretch-v","conga","conga-inv","marquee","marquee-inv","rainbow"]),j=new Set(["ex-large","large","small"]),F=new Map([["marquee","conga"],["marquee-inv","conga-inv"]]),M=(e,t,r,n,s)=>{const o=w(r),i=w(n),a=w(t),u=s.filter(e=>j.has(e)),l=s.filter(e=>q.has(e));if(u.length+l.length<s.length)return e;if(l.length>5)return e;const c=l.map(e=>F.has(e)?F.get(e):e),p=u[u.length-1]||"";return((e,t,r)=>t.map((e,t)=>`<span class="emoji-effect ${e}${0===t&&r?" "+r:""}">`).join("")+e+"</span>".repeat(t.length))(`<i class="emoji s24 message-emoji ${p}" title=":${o}:" style="${i};">:${a}:</i>`,c,p)},O=(e,t,r,n,s)=>M(e,t,r,`background-image: url(${n})`,s),P=/[a-zA-Z0-9+_-]{1,32}/,S=x(/(hsl\([0-9]+,[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[0-9]+(?:\.[0-9]+)?%,[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[0-9]+(?:\.[0-9]+)?%\))(.*)/,{color:1,effects:2}),R=x(/0x([0-9A-Fa-f]{6})(.*)/,{color:1,effects:2}),A=e=>{const{inner:t}={inner:e[1]},r=R.exec(t);if(r)return(e=>{const{color:t,effects:r}=e.groups;return M(`:${e[0]}:`,"0x"+t,"0x"+t,"background-color: #"+t,""===r?[]:r.split(".").slice(1))})(r);const n=S.exec(t);if(n)return(e=>{const{color:t,effects:r}=e.groups;return M(`:${e[0]}:`,t,t,"background-color: "+t,""===r?[]:r.split(".").slice(1))})(n);if(!P.exec(t))return e[0];const[s,...o]=t.split(".");if(s.startsWith("@")){const t=b.getUserByName(s.slice(1));return t?O(e[0],s,s,`${$}/api/v3/files/${t.iconFileId}`,o):e[0]}const i=b.getStampByName(s);return i?O(e[0],s,i.name,`${$}/api/v3/files/${i.fileId}`,o):e[0]},E=/:((?:@?[a-zA-Z0-9+_-]{1,32}|\w+\([^:<>"'=+!?]+\))[\w+-.]*):/;function C(e,t,r){b=t,r&&($=r),s(E,A)(e)}let I;const z=e=>{if(!(e=>"string"==typeof e.type&&"string"==typeof e.raw&&"string"==typeof e.id)(e))return!1;const{type:t,id:r}=e;return"user"===t||"channel"===t&&!!I.getChannel(r)||"group"===t||"file"===t||"message"===t},T=(e,t)=>{"user"!==t.type?"channel"===t.type&&I.getChannel(t.id)?((e,{type:t,id:r,raw:n})=>{const s=[];s.push(["href",`javascript:changeChannel('${I.getChannelPath(r)}')`]),s.push(["class","message-channel-link"]);let o=e.push("traq_extends_link_open","a",1);o.attrs=s,o.meta={type:t,data:n},o=e.push("text","",0),o.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):"group"!==t.type?"file"!==t.type?(e.push("traq_extends_plain_open","a",1),e.push("text","",0).content=t.raw,e.push("traq_extends_plain_close","a",-1)):((e,{type:t,id:r,raw:n})=>{let s=e.push("traq_extends_link_open","a",1);s.attrs=[["href","/api/v3/files/"+r],["download",r]],s.meta={type:t,data:r},s=e.push("text","",0),s.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):((e,{type:t,id:r,raw:n})=>{var s,o;const i=[],a=I.getUserGroup(r),u=I.getMe();i.push(["href",`javascript:openGroupModal('${r}')`]),null!==(s=null==a||null===(o=a.members)||void 0===o?void 0:o.some(e=>e.id===(null==u?void 0:u.id)))&&void 0!==s&&s?i.push(["class","message-group-link-highlight message-group-link"]):i.push(["class","message-group-link"]);let l=e.push("traq_extends_link_open","a",1);l.attrs=i,l.meta={type:t,data:r},l=e.push("text","",0),l.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):((e,{type:t,id:r,raw:n})=>{const s=[],o=I.getMe();s.push(["href",`javascript:openUserModal('${r}')`]),s.push(r===(null==o?void 0:o.id)?["class","message-user-link-highlight message-user-link"]:["class","message-user-link"]);let i=e.push("traq_extends_link_open","a",1);i.attrs=s,i.meta={type:t,data:r},i=e.push("text","",0),i.content=n,e.push("traq_extends_link_close","a",-1)})(e,t)};function U(e,t){I=t,o(z,T)(e)}const W=/^(no-?highlight|plain|text)$/i,B=(e,t=!0)=>(r,n)=>{let s,o,i="";if(t?([s,o]=n.split(":"),o&&(i=`<cite>${w(o)}</cite>`)):s=n,c.getLanguage(s)){const t=c.highlight(s,r);return`<pre class="${e}">${i}<code class="lang-${t.language}">${t.value}</code></pre>`}if(W.test(s))return`<pre class="${e}">${i}<code>${w(r)}</code></pre>`;{const t=c.highlightAuto(r);return`<pre class="${e}">${i}<code class="lang-${t.language}">${t.value}</code></pre>`}};var D=["libra.tokyotech.org","user-images.githubusercontent.com","git.trap.jp","wiki.trapti.tech","wiki.trap.jp","md.trapti.tech","md.trap.jp","trap.jp","traq-dev.tokyotech.org"];const G=["success","info","warning","danger"],H=r,L=n,N=C,Z=U,J=i;exports.createHighlightFunc=B,exports.default=class{constructor(e,r=D){this.md=new t({breaks:!0,linkify:!0,highlight:B("traq-code traq-lang")}),this.setRendererRule(),this.setPlugin(e,r)}setPlugin(e,t){this.md.use(r).use(n,!0).use(U,e).use(C,e).use(i,{katex:a,output:"html",strict:e=>"unicodeTextInMathMode"===e?"ignore":"warn",maxSize:100,blockClass:"is-scroll"}).use(u,{attrs:{target:"_blank",rel:"nofollow noopener noreferrer"}}).use(l(t,{httpsOnly:!0}))}setRendererRule(){this.md.block.State.prototype.skipEmptyLines=function(e){for(let t=this.lineMax;e<t&&!(this.bMarks[e]+this.tShift[e]<this.eMarks[e]);e++)this.push("hardbreak","br",0);return e}}render(e){return this.md.render(e,{})}renderInline(e){const t=this.md.parseInline(e,{})[0].children||[],r=[];for(const e of t)r.push("regexp-0"===e.type?A(e.meta.match):"spoiler_open"===e.type?'<span class="spoiler">':"spoiler_close"===e.type?"</span>":"softbreak"===e.type?" ":this.md.utils.escapeHtml(e.content));return r.join("")}},exports.jsonPlugin=Z,exports.katexPlugin=J,exports.markPlugin=H,exports.spoilerPlugin=L,exports.stampCssPlugin=(e,t)=>{s(/:([\w-_]+?)[:;]/,([e,r])=>t.includes(r)?`<i class="emoji s${e.endsWith(":")?32:16} e_${r.replace(/\+/g,"_-plus-_")}" title="${e}">${e}</i>`:e)(e)},exports.stampPlugin=N,exports.useContainer=(e,t=G)=>{t.forEach(t=>{e.use(p,t)})};
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0}),require("core-js/modules/web.dom-collections.iterator");var t=e(require("markdown-it")),r=e(require("markdown-it-mark")),n=e(require("@traptitech/markdown-it-spoiler")),s=e(require("markdown-it-regexp"));require("core-js/modules/es.string.replace");var i=e(require("markdown-it-json")),o=e(require("@traptitech/markdown-it-katex")),a=e(require("katex")),l=e(require("markdown-it-link-attributes")),u=e(require("markdown-it-image-filter")),c=e(require("highlight.js")),p=e(require("markdown-it-container"));function d(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&g(e,t)}function h(e){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function g(e,t){return(g=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function f(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function m(e,t,r){return(m=f()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return r&&g(s,r.prototype),s}).apply(null,arguments)}function x(e){var t="function"==typeof Map?new Map:void 0;return(x=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return m(e,arguments,h(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),g(r,e)})(e)}function y(e,t){y=function(e,t){return new i(e,void 0,t)};var r=x(RegExp),n=RegExp.prototype,s=new WeakMap;function i(e,t,n){var i=r.call(this,e,t);return s.set(i,n||s.get(e)),i}function o(e,t){var r=s.get(t);return Object.keys(r).reduce((function(t,n){return t[n]=e[r[n]],t}),Object.create(null))}return d(i,r),i.prototype.exec=function(e){var t=n.exec.call(this,e);return t&&(t.groups=o(t,this)),t},i.prototype[Symbol.replace]=function(e,t){if("string"==typeof t){var r=s.get(this);return n[Symbol.replace].call(this,e,t.replace(/\$<([^>]+)>/g,(function(e,t){return"$"+r[t]})))}if("function"==typeof t){var i=this;return n[Symbol.replace].call(this,e,(function(){var e=[];return e.push.apply(e,arguments),"object"!=typeof e[e.length-1]&&e.push(o(e,i)),t.apply(this,e)}))}return n[Symbol.replace].call(this,e,t)},y.apply(this,arguments)}const v=/[&<>"]/g,b=new Map([["&","&amp;"],["<","&lt;"],[">","&gt;"],['"',"&quot;"]]),k=e=>b.get(e),w=e=>v.test(e)?e.replace(v,k):e;let _,j="";const q=new Set(["rotate","rotate-inv","wiggle","parrot","zoom","inversion","turn","turn-v","happa","pyon","flashy","pull","atsumori","stretch","stretch-v","conga","conga-inv","marquee","marquee-inv","rainbow"]),$=new Set(["ex-large","large","small"]),R=new Map([["marquee","conga"],["marquee-inv","conga-inv"]]),F=(e,t,r,n,s)=>{const i=w(r),o=w(n),a=w(t),l=s.filter(e=>$.has(e)),u=s.filter(e=>q.has(e));if(l.length+u.length<s.length)return e;if(u.length>5)return e;const c=u.map(e=>R.has(e)?R.get(e):e),p=l[l.length-1]||"";return((e,t,r)=>t.map((e,t)=>`<span class="emoji-effect ${e}${0===t&&r?" "+r:""}">`).join("")+e+"</span>".repeat(t.length))(`<i class="emoji s24 message-emoji ${p}" title=":${i}:" style="${o};">:${a}:</i>`,c,p)},M=(e,t,r,n,s)=>F(e,t,r,`background-image: url(${n})`,s),O=/[a-zA-Z0-9+_-]{1,32}/,P=y(/(hsl\([0-9]+,[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[0-9]+(?:\.[0-9]+)?%,[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[0-9]+(?:\.[0-9]+)?%\))(.*)/,{color:1,effects:2}),S=y(/0x([0-9A-Fa-f]{6})(.*)/,{color:1,effects:2}),I=e=>{const{inner:t}={inner:e[1]},r=S.exec(t);if(r)return(e=>{const{color:t,effects:r}=e.groups;return F(`:${e[0]}:`,"0x"+t,"0x"+t,"background-color: #"+t,""===r?[]:r.split(".").slice(1))})(r);const n=P.exec(t);if(n)return(e=>{const{color:t,effects:r}=e.groups;return F(`:${e[0]}:`,t,t,"background-color: "+t,""===r?[]:r.split(".").slice(1))})(n);if(!O.exec(t))return e[0];const[s,...i]=t.split(".");if(s.startsWith("@")){const t=_.getUserByName(s.slice(1));return t?M(e[0],s,s,`${j}/api/v3/files/${t.iconFileId}`,i):e[0]}const o=_.getStampByName(s);return o?M(e[0],s,o.name,`${j}/api/v3/files/${o.fileId}`,i):e[0]},E=/:((?:@?[a-zA-Z0-9+_-]{1,32}|\w+\([^:<>"'=+!?]+\))[\w+-.]*):/;function A(e,t,r){_=t,r&&(j=r),s(E,I)(e)}let C;const T=e=>{if(!(e=>"string"==typeof e.type&&"string"==typeof e.raw&&"string"==typeof e.id)(e))return!1;const{type:t,id:r}=e;return"user"===t||"channel"===t&&!!C.getChannel(r)||"group"===t||"file"===t||"message"===t},z=(e,t)=>{"user"!==t.type?"channel"===t.type&&C.getChannel(t.id)?((e,{type:t,id:r,raw:n})=>{const s=[];s.push(["href",`javascript:changeChannel('${C.getChannelPath(r)}')`]),s.push(["class","message-channel-link"]);let i=e.push("traq_extends_link_open","a",1);i.attrs=s,i.meta={type:t,data:n},i=e.push("text","",0),i.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):"group"!==t.type?"file"!==t.type?(e.push("traq_extends_plain_open","a",1),e.push("text","",0).content=t.raw,e.push("traq_extends_plain_close","a",-1)):((e,{type:t,id:r,raw:n})=>{let s=e.push("traq_extends_link_open","a",1);s.attrs=[["href","/api/v3/files/"+r],["download",r]],s.meta={type:t,data:r},s=e.push("text","",0),s.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):((e,{type:t,id:r,raw:n})=>{var s,i;const o=[],a=C.getUserGroup(r),l=C.getMe();o.push(["href",`javascript:openGroupModal('${r}')`]),null!==(s=null==a||null===(i=a.members)||void 0===i?void 0:i.some(e=>e.id===(null==l?void 0:l.id)))&&void 0!==s&&s?o.push(["class","message-group-link-highlight message-group-link"]):o.push(["class","message-group-link"]);let u=e.push("traq_extends_link_open","a",1);u.attrs=o,u.meta={type:t,data:r},u=e.push("text","",0),u.content=n,e.push("traq_extends_link_close","a",-1)})(e,t):((e,{type:t,id:r,raw:n})=>{const s=[],i=C.getMe();s.push(["href",`javascript:openUserModal('${r}')`]),s.push(r===(null==i?void 0:i.id)?["class","message-user-link-highlight message-user-link"]:["class","message-user-link"]);let o=e.push("traq_extends_link_open","a",1);o.attrs=s,o.meta={type:t,data:r},o=e.push("text","",0),o.content=n,e.push("traq_extends_link_close","a",-1)})(e,t)};function U(e,t){C=t,i(T,z)(e)}var W=["actionscript","awk","bash","basic","bnf","brainfuck","csharp","h","cpp","cmake","coq","css","clojure","coffeescript","crystal","d","dart","delphi","diff","django","dockerfile","elixir","elm","fsharp","fortran","go","gradle","groovy","xml","http","haml","handlebars","haxe","ini","json","java","javascript","kotlin","tex","less","lisp","livescript","lua","makefile","markdown","mathematica","matlab","moonscript","nginx","nimrod","ocaml","objectivec","glsl","php","perl","plaintext","pgsql","powershell","processing","prolog","protobuf","python","k","r","ruby","scss","sql","scheme","shell","stylus","swift","twig","typescript","vbnet","vbscript","verilog","vim","x86asm","xquery","yaml","zephir"];const B=/^(no-?highlight|plain|text)$/i,D=(e,t=!0,r=!0)=>(n,s)=>{let i,o,a="";if(t?([i,o]=s.split(":"),o&&(a=`<cite>${w(o)}</cite>`)):i=s,c.getLanguage(i)){const t=c.highlight(i,n);return`<pre class="${e}">${a}<code class="lang-${t.language}">${t.value}</code></pre>`}if(B.test(i))return`<pre class="${e}">${a}<code>${w(n)}</code></pre>`;{const t=c.highlightAuto(n,r?W:void 0);return`<pre class="${e}">${a}<code class="lang-${t.language}">${t.value}</code></pre>`}};var G=["libra.tokyotech.org","user-images.githubusercontent.com","git.trap.jp","wiki.trapti.tech","wiki.trap.jp","md.trapti.tech","md.trap.jp","trap.jp","traq-dev.tokyotech.org"];const H=(e,t)=>{const r=[],n=new Set,s=e.matchAll(t);let i=0,o=0;for(const e of s){var a,l,u,c,p,d,h;const t=null!==(a=e.index)&&void 0!==a?a:0,s=null!==(l=null===(u=e[0])||void 0===u?void 0:u.length)&&void 0!==l?l:0,g=null!==(c=null===(p=e[3])||void 0===p?void 0:p.length)&&void 0!==c?c:0,f=null!==(d=e[1])&&void 0!==d?d:"",m=null!==(h=e[2])&&void 0!==h?h:"",x=t,y=t+s-g;n.has(m)||("files"===f&&r.push({type:"file",id:m,startIndex:x,endIndex:y}),"messages"===f&&r.push({type:"message",id:m,startIndex:x,endIndex:y}),n.add(m)),x!==o&&(i=x),o=t+s}return{rawText:e,text:o===e.length?e.substring(0,i):e,embeddings:r}},L=["success","info","warning","danger"],N=r,Z=n,J=A,K=U,Q=o;exports.createHighlightFunc=D,exports.default=class{constructor(e,r=G,n){this.md=new t({breaks:!0,linkify:!0,highlight:D("traq-code traq-lang")}),this.embeddingRegExp=(e=>RegExp(e+"/(files|messages)/([\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12})(\\s*)","g"))(n),this.setRendererRule(),this.setPlugin(e,r)}setPlugin(e,t){this.md.use(r).use(n,!0).use(U,e).use(A,e).use(o,{katex:a,output:"html",strict:e=>"unicodeTextInMathMode"===e?"ignore":"warn",maxSize:100,blockClass:"is-scroll"}).use(l,{attrs:{target:"_blank",rel:"nofollow noopener noreferrer"}}).use(u(t,{httpsOnly:!0}))}setRendererRule(){this.md.block.State.prototype.skipEmptyLines=function(e){for(let t=this.lineMax;e<t&&!(this.bMarks[e]+this.tShift[e]<this.eMarks[e]);e++)this.push("hardbreak","br",0);return e}}render(e){const t=H(e,this.embeddingRegExp);return{...t,renderedText:this.md.render(t.text,{})}}renderInline(e){const t=((e,t)=>{const{text:r,embeddings:n}=H(e,t);let s=r,i=0;for(const e of n){if(r.length<=e.startIndex)break;let t;if("file"===e.type)t="[[添付ファイル]]";else{if("message"!==e.type)throw new Error("embeddingReplacer unknown embedding type: "+e);t="[[添付メッセージ]]"}s=s.slice(0,i+e.startIndex)+t+s.slice(i+e.endIndex),i+=t.length-(e.endIndex-e.startIndex)}return{rawText:e,text:s,embeddings:n}})(e,this.embeddingRegExp),r=this.md.parseInline(t.text,{})[0].children||[],n=[];for(const e of r)n.push("regexp-0"===e.type?I(e.meta.match):"spoiler_open"===e.type?'<span class="spoiler">':"spoiler_close"===e.type?"</span>":"softbreak"===e.type?" ":this.md.utils.escapeHtml(e.content));return{...t,renderedText:n.join("")}}},exports.jsonPlugin=K,exports.katexPlugin=Q,exports.markPlugin=N,exports.spoilerPlugin=Z,exports.stampCssPlugin=(e,t)=>{s(/:([\w-_]+?)[:;]/,([e,r])=>t.includes(r)?`<i class="emoji s${e.endsWith(":")?32:16} e_${r.replace(/\+/g,"_-plus-_")}" title="${e}">${e}</i>`:e)(e)},exports.stampPlugin=J,exports.useContainer=(e,t=L)=>{t.forEach(t=>{e.use(p,t)})};
//# sourceMappingURL=traq-markdown-it.cjs.production.min.js.map

@@ -466,4 +466,6 @@ import 'core-js/modules/web.dom-collections.iterator';

var defaultSubset = ['actionscript', 'awk', 'bash', 'basic', 'bnf', 'brainfuck', 'csharp', 'h', 'cpp', 'cmake', 'coq', 'css', 'clojure', 'coffeescript', 'crystal', 'd', 'dart', 'delphi', 'diff', 'django', 'dockerfile', 'elixir', 'elm', 'fsharp', 'fortran', 'go', 'gradle', 'groovy', 'xml', 'http', 'haml', 'handlebars', 'haxe', 'ini', 'json', 'java', 'javascript', 'kotlin', 'tex', 'less', 'lisp', 'livescript', 'lua', 'makefile', 'markdown', 'mathematica', 'matlab', 'moonscript', 'nginx', 'nimrod', 'ocaml', 'objectivec', 'glsl', 'php', 'perl', 'plaintext', 'pgsql', 'powershell', 'processing', 'prolog', 'protobuf', 'python', 'k', 'r', 'ruby', 'scss', 'sql', 'scheme', 'shell', 'stylus', 'swift', 'twig', 'typescript', 'vbnet', 'vbscript', 'verilog', 'vim', 'x86asm', 'xquery', 'yaml', 'zephir'];
const noHighlightRe = /^(no-?highlight|plain|text)$/i;
const createHighlightFunc = (preClass, withCaption = true) => (code, lang) => {
const createHighlightFunc = (preClass, withCaption = true, useSubsetForAuto = true) => (code, lang) => {
let langName, langCaption;

@@ -488,3 +490,3 @@ let citeTag = '';

} else {
const result = hljs.highlightAuto(code);
const result = hljs.highlightAuto(code, useSubsetForAuto ? defaultSubset : undefined);
return `<pre class="${preClass}">${citeTag}<code class="lang-${result.language}">${result.value}</code></pre>`;

@@ -496,2 +498,122 @@ }

const createEmbeddingRegexp = embeddingOrigin => RegExp(`${embeddingOrigin}/(files|messages)/([\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12})(\\s*)`, 'g');
/**
* markdownから埋め込みURLを抽出する
*
* @param regexp
* マッチに使う正規表現。グループは順に
*
* - 種別
* - UUID
* - 削除されるスペース
*
* であることを期待する
*/
const embeddingExtractor = (rawMessage, regexp) => {
const embeddings = [];
const knownIdSet = new Set();
const matches = rawMessage.matchAll(regexp);
/** 連続したマッチの開始インデックス */
let sequenceStartIndex = 0;
/** スペースを含んだ、連続したマッチ全体の終了インデックス */
let sequenceEndIndex = 0;
for (const match of matches) {
var _match$index, _match$0$length, _match$, _match$3$length, _match$2, _match$3, _match$4;
const matchIndex = (_match$index = match.index) !== null && _match$index !== void 0 ? _match$index : 0;
const matchLength = (_match$0$length = (_match$ = match[0]) === null || _match$ === void 0 ? void 0 : _match$.length) !== null && _match$0$length !== void 0 ? _match$0$length : 0;
const spaceLength = (_match$3$length = (_match$2 = match[3]) === null || _match$2 === void 0 ? void 0 : _match$2.length) !== null && _match$3$length !== void 0 ? _match$3$length : 0;
const type = (_match$3 = match[1]) !== null && _match$3 !== void 0 ? _match$3 : '';
const id = (_match$4 = match[2]) !== null && _match$4 !== void 0 ? _match$4 : '';
const startIndex = matchIndex;
const endIndex = matchIndex + matchLength - spaceLength;
if (!knownIdSet.has(id)) {
if (type === 'files') {
embeddings.push({
type: 'file',
id,
startIndex,
endIndex
});
}
if (type === 'messages') {
embeddings.push({
type: 'message',
id,
startIndex,
endIndex
});
}
knownIdSet.add(id);
}
if (startIndex !== sequenceEndIndex) {
// 連続したマッチではなかった
sequenceStartIndex = startIndex;
}
sequenceEndIndex = matchIndex + matchLength;
}
const hasSequenceReachedEos = sequenceEndIndex === rawMessage.length;
return {
rawText: rawMessage,
text: hasSequenceReachedEos ? rawMessage.substring(0, sequenceStartIndex) : rawMessage,
embeddings
};
};
/**
* markdownから埋め込みURLを抽出してすべて置換する
*
* @param regexp
* マッチに使う正規表現。グループは順に
*
* - 種別
* - UUID
* - 削除されるスペース
*
* であることを期待する
*/
const embeddingReplacer = (rawMessage, regexp) => {
const {
text,
embeddings
} = embeddingExtractor(rawMessage, regexp);
let newText = text; // 置換で文字数がずれるのでずれた数を保持する
let placeDiff = 0;
for (const embedding of embeddings) {
// 末尾のものは抽出で消えているので置換しない
if (text.length <= embedding.startIndex) break;
let replaced;
if (embedding.type === 'file') {
replaced = '[[添付ファイル]]';
} else if (embedding.type === 'message') {
replaced = '[[添付メッセージ]]';
} else {
const invalid = embedding;
throw new Error(`embeddingReplacer unknown embedding type: ${invalid}`);
}
newText = newText.slice(0, placeDiff + embedding.startIndex) + replaced + newText.slice(placeDiff + embedding.endIndex);
placeDiff += replaced.length - (embedding.endIndex - embedding.startIndex);
}
return {
rawText: rawMessage,
text: newText,
embeddings
};
};
const defaultLabels = ['success', 'info', 'warning', 'danger'];

@@ -512,3 +634,3 @@ const useContainer = (md, labels = defaultLabels) => {

class index {
constructor(store, whitelist = defaultWhitelist) {
constructor(store, whitelist = defaultWhitelist, embeddingOrigin) {
this.md = new MarkdownIt({

@@ -519,2 +641,3 @@ breaks: true,

});
this.embeddingRegExp = createEmbeddingRegexp(embeddingOrigin);
this.setRendererRule();

@@ -542,6 +665,3 @@ this.setPlugin(store, whitelist);

setRendererRule() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const blockState = this.md.block.State;
blockState.prototype.skipEmptyLines = function skipEmptyLines(from) {
this.md.block.State.prototype.skipEmptyLines = function skipEmptyLines(from) {
for (let max = this.lineMax; from < max; from++) {

@@ -560,7 +680,11 @@ if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {

render(text) {
return this.md.render(text, {});
const data = embeddingExtractor(text, this.embeddingRegExp);
return { ...data,
renderedText: this.md.render(data.text, {})
};
}
renderInline(text) {
const parsed = this.md.parseInline(text, {});
const data = embeddingReplacer(text, this.embeddingRegExp);
const parsed = this.md.parseInline(data.text, {});
const tokens = parsed[0].children || [];

@@ -585,3 +709,5 @@ const rendered = [];

return rendered.join('');
return { ...data,
renderedText: rendered.join('')
};
}

@@ -588,0 +714,0 @@

{
"name": "@traptitech/traq-markdown-it",
"version": "2.2.7",
"version": "2.3.0",
"description": "Markdown parser for traQ.",

@@ -17,6 +17,6 @@ "main": "dist/index.js",

"start": "tsdx watch",
"build": "tsdx build && dart-sass ./src/css/index.sass ./dist/stamp.css",
"build": "tsdx build && dart-sass ./src/css/index.scss ./dist/index.css",
"test": "tsdx test",
"lint": "tsdx lint",
"prepare": "tsdx build && dart-sass ./src/css/index.sass ./dist/stamp.css"
"prepare": "tsdx build && dart-sass ./src/css/index.scss ./dist/index.css"
},

@@ -34,8 +34,8 @@ "repository": {

"dependencies": {
"@traptitech/markdown-it-katex": "^3.2.3",
"@traptitech/markdown-it-spoiler": "^1.1.3",
"@traptitech/markdown-it-katex": "^3.2.4",
"@traptitech/markdown-it-spoiler": "^1.1.4",
"core-js": "^3.6.5",
"highlight.js": "^10.0.2",
"highlight.js": "^10.0.3",
"katex": "^0.11.1",
"markdown-it": "^10.0.0",
"markdown-it": "^11.0.0",
"markdown-it-container": "^2.0.0",

@@ -50,10 +50,11 @@ "markdown-it-image-filter": "^1.1.0",

"@babel/preset-env": "^7.9.6",
"@traptitech/traq": "3.0.3-0",
"@traptitech/traq": "3.1.2-5",
"@types/highlightjs": "^9.12.0",
"@types/jest": "^25.2.3",
"@types/katex": "^0.11.0",
"@types/markdown-it": "10.0.1",
"@typescript-eslint/eslint-plugin": "^2.31.0",
"@typescript-eslint/parser": "^2.31.0",
"@typescript-eslint/eslint-plugin": "^3.0.0",
"@typescript-eslint/parser": "^3.0.0",
"dart-sass": "^1.25.0",
"eslint": "^6.8.0",
"eslint": "^7.0.0",
"eslint-config-prettier": "^6.11.0",

@@ -64,4 +65,4 @@ "eslint-plugin-prettier": "^3.1.3",

"tsdx": "^0.13.2",
"tslib": "^1.11.2",
"typescript": "^3.8.3"
"tslib": "^2.0.0",
"typescript": "^3.9.3"
},

@@ -68,0 +69,0 @@ "husky": {

import hljs from 'highlight.js'
import defaultSubset from './default/language_subset'
import { escapeHtml } from './util'

@@ -6,6 +7,7 @@

export const createHighlightFunc = (preClass: string, withCaption = true) => (
code: string,
lang: string
): string => {
export const createHighlightFunc = (
preClass: string,
withCaption = true,
useSubsetForAuto = true
) => (code: string, lang: string): string => {
let langName: string, langCaption: string

@@ -30,5 +32,8 @@ let citeTag = ''

} else {
const result = hljs.highlightAuto(code)
const result = hljs.highlightAuto(
code,
useSubsetForAuto ? defaultSubset : undefined
)
return `<pre class="${preClass}">${citeTag}<code class="lang-${result.language}">${result.value}</code></pre>`
}
}
/// <reference types="../src/types/markdown-it-mark" />
/* eslint-disable @typescript-eslint/camelcase */
import MarkdownIt from 'markdown-it'

@@ -16,4 +15,20 @@ import MarkdownItMark from 'markdown-it-mark'

import { Store } from './Store'
import {
createEmbeddingRegexp,
embeddingExtractor,
EmbeddingsExtractedMessage,
embeddingReplacer
} from './embeddingExtractor'
export { Store } from './Store'
export {
Embedding,
EmbeddingFile,
EmbeddingMessage,
EmbeddingsExtractedMessage
} from './embeddingExtractor'
export type MarkdownRenderResult = EmbeddingsExtractedMessage & {
renderedText: string
}
export default class {

@@ -25,4 +40,10 @@ readonly md = new MarkdownIt({

})
readonly embeddingRegExp: RegExp
constructor(store: Store, whitelist: string[] = defaultWhitelist) {
constructor(
store: Store,
whitelist: string[] = defaultWhitelist,
embeddingOrigin: string
) {
this.embeddingRegExp = createEmbeddingRegexp(embeddingOrigin)
this.setRendererRule()

@@ -56,5 +77,3 @@ this.setPlugin(store, whitelist)

setRendererRule(): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const blockState = this.md.block.State
blockState.prototype.skipEmptyLines = function skipEmptyLines(
this.md.block.State.prototype.skipEmptyLines = function skipEmptyLines(
from: number

@@ -72,8 +91,14 @@ ): number {

render(text: string): string {
return this.md.render(text, {})
render(text: string): MarkdownRenderResult {
const data = embeddingExtractor(text, this.embeddingRegExp)
return {
...data,
renderedText: this.md.render(data.text, {})
}
}
renderInline(text: string): string {
const parsed = this.md.parseInline(text, {})
renderInline(text: string): MarkdownRenderResult {
const data = embeddingReplacer(text, this.embeddingRegExp)
const parsed = this.md.parseInline(data.text, {})
const tokens = parsed[0].children || []

@@ -96,3 +121,7 @@ const rendered = []

}
return rendered.join('')
return {
...data,
renderedText: rendered.join('')
}
}

@@ -99,0 +128,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc