🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More
Socket
Book a DemoSign in
Socket

@mdit/plugin-embed

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mdit/plugin-embed - npm Package Compare versions

Comparing version
0.24.1
to
0.25.0
+2
dist/cdn.umd.js
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.mdItPluginEmbed={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=/\\{%/g,n=/%\\}/g,r=(e,t)=>{if(e.charCodeAt(t)!==123||e.charCodeAt(t+1)!==37)return!1;let n=t-1,r=0;for(;n>=0&&e.charCodeAt(n)===92;)r++,n--;return r%2!=1},i=(e,t)=>e.charCodeAt(t)===37&&e.charCodeAt(t+1)===125,a=e=>(a,o)=>{let s=a.md.utils.isSpace,c=a.pos,l=a.src.length;if(l-c<5||!r(a.src,c))return!1;let u=c+2;for(;u<l&&s(a.src.charCodeAt(u));)u++;let d=u,f=!1;for(;d+1<l;d++){if(r(a.src,d))return!1;if(i(a.src,d)){f=!0;break}}if(!f)return!1;let p=u+1;for(;p<d&&!s(a.src.charCodeAt(p));)p++;let m=a.src.slice(u,p);if(!e.has(m))return!1;if(!o){let e=a.push(`embed_inline`,`embed`,0),r=p<d?a.src.slice(p+1,d).trim().replaceAll(t,`{%`).replaceAll(n,`%}`):``;e.markup=`{% %}`,e.info=m,e.content=r}return a.pos=d+2,!0},o=e=>(a,o,s,c)=>{let l=a.md.utils.isSpace,u=a.bMarks[o]+a.tShift[o],d=a.eMarks[o],f=a.src;if(d-u<5||a.src.charCodeAt(u)!==123||a.src.charCodeAt(u+1)!==37)return!1;d=a.skipSpacesBack(d,u);let p=d-2;if(!i(f,p))return!1;let m=u+2;for(;m<p&&l(a.src.charCodeAt(m));)m++;let h=-1;for(let e=m;e+1<p;e++){if(r(a.src,e)||i(a.src,e))return!1;h===-1&&l(a.src.charCodeAt(e))&&(h=e)}let g=h===-1?a.src.slice(m,p).trimEnd():a.src.slice(m,h);if(!e.has(g)||h===-1&&e.get(g).allowInline)return!1;if(c)return!0;let _=h===-1?``:a.src.slice(h+1,p).trim().replaceAll(t,`{%`).replaceAll(n,`%}`),v=a.push(`embed_block`,`embed`,0);return v.block=!0,v.info=g,v.content=_,v.map=[o,o+1],v.markup=`{% %}`,a.line=o+1,!0};e.embed=(e,t)=>{if(typeof t!=`object`||!Array.isArray(t.config))throw TypeError(`[@mdit/plugin-embed]: config is required and must be an array.`);let n=e,r=n.__embedMap??=new Map,i=n.__inlineEmbedMap??=new Map;t.config.forEach(e=>{r.set(e.name,e),e.allowInline&&i.set(e.name,e)}),`embed_block`in e.renderer.rules||(e.block.ruler.before(`paragraph`,`embed_block`,o(r),{alt:[`paragraph`,`reference`,`blockquote`,`list`]}),e.renderer.rules.embed_block=(e,t)=>{let n=e[t];return r.get(n.info).setup(n.content,!1)}),i.size>0&&!(`embed_inline`in e.renderer.rules)&&(e.inline.ruler.before(`emphasis`,`embed_inline`,a(i)),e.renderer.rules.embed_inline=(e,t)=>{let n=e[t];return i.get(n.info).setup(n.content,!0)})}});
//# sourceMappingURL=cdn.umd.js.map
{"version":3,"file":"cdn.umd.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type MarkdownIt from \"markdown-it\";\nimport type { PluginWithOptions } from \"markdown-it\";\nimport type { RuleBlock } from \"markdown-it/lib/parser_block.mjs\";\nimport type { RuleInline } from \"markdown-it/lib/parser_inline.mjs\";\nimport type Token from \"markdown-it/lib/token.mjs\";\n\nimport type { EmbedConfig, MarkdownItEmbedOptions } from \"./options.js\";\n\nconst ESCAPED_OPENING_MARKER_REGEXP = /\\\\{%/g;\nconst ESCAPED_CLOSING_MARKER_REGEXP = /%\\\\}/g;\n\nconst checkInlineOpeningMarker = (src: string, current: number): boolean => {\n if (src.charCodeAt(current) !== 123 /* { */ || src.charCodeAt(current + 1) !== 37 /* % */)\n return false;\n\n // Check if the opening marker was escaped\n let pos = current - 1;\n let backslashCount = 0;\n\n while (pos >= 0 && src.charCodeAt(pos) === 92 /* \\ */) {\n backslashCount++;\n pos--;\n }\n\n // If opening {% is escaped (odd number of preceding backslashes), don't parse\n if (backslashCount % 2 === 1) return false;\n\n return true;\n};\n\nconst checkClosingMarker = (src: string, current: number): boolean =>\n src.charCodeAt(current) === 37 /* % */ && src.charCodeAt(current + 1) === 125; /* } */\n\n/*\n * Parse inline embed with bracket syntax: {%...%}\n */\nconst createInlineEmbedRule =\n (inlineEmbedMap: Map<string, EmbedConfig>): RuleInline =>\n (state, silent) => {\n const isSpace = state.md.utils.isSpace;\n const start = state.pos;\n const max = state.src.length;\n\n // minimum length check for inline embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (!checkInlineOpeningMarker(state.src, start)) return false;\n\n let contentStart = start + 2; // Move past the opening {% marker\n\n // skip spaces\n while (contentStart < max) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let contentEnd = contentStart;\n let found = false;\n\n for (; contentEnd + 1 < max; contentEnd++) {\n // must not include opening marker\n if (checkInlineOpeningMarker(state.src, contentEnd)) return false;\n\n if (checkClosingMarker(state.src, contentEnd)) {\n found = true;\n break;\n }\n }\n\n // No closing marker found\n if (!found) return false;\n\n // get first space\n let spacer = contentStart + 1;\n\n while (spacer < contentEnd) {\n if (isSpace(state.src.charCodeAt(spacer))) break;\n\n spacer++;\n }\n\n // Extract embed name\n const name = state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!inlineEmbedMap.has(name)) return false;\n\n if (!silent) {\n const token = state.push(\"embed_inline\", \"embed\", 0);\n const params =\n spacer < contentEnd\n ? state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\")\n : \"\";\n\n token.markup = \"{% %}\";\n token.info = name;\n token.content = params;\n }\n // Move past the closing %} marker\n state.pos = contentEnd + 2;\n\n return true;\n };\n\n/*\n * Parse block embed with syntax: {% ... %}\n */\nconst createBlockEmbedRule =\n (embedMap: Map<string, EmbedConfig>): RuleBlock =>\n (state, startLine, _, silent) => {\n const isSpace = state.md.utils.isSpace;\n const start = state.bMarks[startLine] + state.tShift[startLine];\n let max = state.eMarks[startLine];\n const src = state.src;\n\n // minimum length check for block embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (\n state.src.charCodeAt(start) !== 123 /* { */ ||\n state.src.charCodeAt(start + 1) !== 37 /* % */\n )\n return false;\n\n max = state.skipSpacesBack(max, start);\n\n const contentEnd = max - 2;\n\n if (!checkClosingMarker(src, contentEnd)) return false;\n\n let contentStart = start + 2;\n\n // skip spaces\n while (contentStart < contentEnd) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let spacer = -1;\n\n for (let pos = contentStart; pos + 1 < contentEnd; pos++) {\n // must not include unescaped opening marker or closing marker\n if (checkInlineOpeningMarker(state.src, pos)) return false;\n\n if (checkClosingMarker(state.src, pos)) return false;\n\n if (spacer !== -1) continue;\n\n if (isSpace(state.src.charCodeAt(pos))) spacer = pos;\n }\n\n // Extract content between {% and %}\n const name =\n spacer === -1\n ? state.src.slice(contentStart, contentEnd).trimEnd()\n : state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!embedMap.has(name)) return false;\n\n // Fallback to inline if it's an inline-allowed embed without params\n // oxlint-disable-next-line typescript/no-non-null-assertion\n if (spacer === -1 && embedMap.get(name)!.allowInline) return false;\n\n if (silent) return true;\n\n const params =\n spacer === -1\n ? \"\"\n : state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\");\n\n const token = state.push(\"embed_block\", \"embed\", 0);\n\n token.block = true;\n token.info = name;\n token.content = params;\n token.map = [startLine, startLine + 1];\n token.markup = \"{% %}\";\n\n // Advance to the next line\n state.line = startLine + 1;\n\n return true;\n };\n\nexport const embed: PluginWithOptions<MarkdownItEmbedOptions> = (md, options) => {\n if (typeof options !== \"object\" || !Array.isArray(options.config))\n throw new TypeError(\"[@mdit/plugin-embed]: config is required and must be an array.\");\n\n // Get existing maps or create new ones to support multiple plugin instances\n const mdWithMaps = md as MarkdownIt & {\n __embedMap?: Map<string, EmbedConfig>;\n __inlineEmbedMap?: Map<string, EmbedConfig>;\n };\n\n const embedMap = (mdWithMaps.__embedMap ??= new Map<string, EmbedConfig>());\n const inlineEmbedMap = (mdWithMaps.__inlineEmbedMap ??= new Map<string, EmbedConfig>());\n\n options.config.forEach((item) => {\n embedMap.set(item.name, item);\n // Inline embeds are only supported when allowInline is true\n if (item.allowInline) inlineEmbedMap.set(item.name, item);\n });\n\n // Only register rules if not already registered\n // check embed_block rules here\n if (!(\"embed_block\" in md.renderer.rules)) {\n // Register the block rule\n md.block.ruler.before(\"paragraph\", \"embed_block\", createBlockEmbedRule(embedMap), {\n alt: [\"paragraph\", \"reference\", \"blockquote\", \"list\"],\n });\n\n // Register the renderers\n md.renderer.rules.embed_block = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return embedMap.get(token.info)!.setup(token.content, false);\n };\n }\n\n // only register embed_inline rules if inline embeds are allowed\n if (inlineEmbedMap.size > 0 && !(\"embed_inline\" in md.renderer.rules)) {\n // Register the inline rule\n md.inline.ruler.before(\"emphasis\", \"embed_inline\", createInlineEmbedRule(inlineEmbedMap));\n\n md.renderer.rules.embed_inline = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return inlineEmbedMap.get(token.info)!.setup(token.content, true);\n };\n }\n};\n"],"mappings":"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"}
import { PluginWithOptions } from "markdown-it";
//#region src/options.d.ts
interface EmbedConfig {
/**
* Embed token name
*
* 嵌入令牌名称
*/
name: string;
/**
* Setup function to generate embed HTML
*
* 生成嵌入 HTML 的设置函数
*/
setup: (ref: string, isInline: boolean) => string;
/**
* Whether the embed can be used inline
*
* 是否允许在行内使用
*
* @default false
*/
allowInline?: boolean;
}
interface MarkdownItEmbedOptions {
/**
* Embed configurations
*
* 嵌入配置
*/
config?: EmbedConfig[];
}
//#endregion
//#region src/plugin.d.ts
declare const embed: PluginWithOptions<MarkdownItEmbedOptions>;
//#endregion
export { EmbedConfig, MarkdownItEmbedOptions, embed };
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/options.ts","../src/plugin.ts"],"mappings":";;;UAAiB,WAAA;;;AAAjB;;;EAME,IAAA;;;;;;EAOA,KAAA,GAAQ,GAAA,UAAa,QAAA;EASrB;AAGF;;;;;;EAHE,WAAA;AAAA;AAAA,UAGe,sBAAA;EC4KqB;;;;;EDtKpC,MAAA,GAAS,WAAA;AAAA;;;cCsKE,KAAA,EAAO,iBAAA,CAAkB,sBAAA"}
const e=/\\{%/g,t=/%\\}/g,n=(e,t)=>{if(e.charCodeAt(t)!==123||e.charCodeAt(t+1)!==37)return!1;let n=t-1,r=0;for(;n>=0&&e.charCodeAt(n)===92;)r++,n--;return r%2!=1},r=(e,t)=>e.charCodeAt(t)===37&&e.charCodeAt(t+1)===125,i=i=>(a,o)=>{let s=a.md.utils.isSpace,c=a.pos,l=a.src.length;if(l-c<5||!n(a.src,c))return!1;let u=c+2;for(;u<l&&s(a.src.charCodeAt(u));)u++;let d=u,f=!1;for(;d+1<l;d++){if(n(a.src,d))return!1;if(r(a.src,d)){f=!0;break}}if(!f)return!1;let p=u+1;for(;p<d&&!s(a.src.charCodeAt(p));)p++;let m=a.src.slice(u,p);if(!i.has(m))return!1;if(!o){let n=a.push(`embed_inline`,`embed`,0),r=p<d?a.src.slice(p+1,d).trim().replaceAll(e,`{%`).replaceAll(t,`%}`):``;n.markup=`{% %}`,n.info=m,n.content=r}return a.pos=d+2,!0},a=i=>(a,o,s,c)=>{let l=a.md.utils.isSpace,u=a.bMarks[o]+a.tShift[o],d=a.eMarks[o],f=a.src;if(d-u<5||a.src.charCodeAt(u)!==123||a.src.charCodeAt(u+1)!==37)return!1;d=a.skipSpacesBack(d,u);let p=d-2;if(!r(f,p))return!1;let m=u+2;for(;m<p&&l(a.src.charCodeAt(m));)m++;let h=-1;for(let e=m;e+1<p;e++){if(n(a.src,e)||r(a.src,e))return!1;h===-1&&l(a.src.charCodeAt(e))&&(h=e)}let g=h===-1?a.src.slice(m,p).trimEnd():a.src.slice(m,h);if(!i.has(g)||h===-1&&i.get(g).allowInline)return!1;if(c)return!0;let _=h===-1?``:a.src.slice(h+1,p).trim().replaceAll(e,`{%`).replaceAll(t,`%}`),v=a.push(`embed_block`,`embed`,0);return v.block=!0,v.info=g,v.content=_,v.map=[o,o+1],v.markup=`{% %}`,a.line=o+1,!0},o=(e,t)=>{if(typeof t!=`object`||!Array.isArray(t.config))throw TypeError(`[@mdit/plugin-embed]: config is required and must be an array.`);let n=e,r=n.__embedMap??=new Map,o=n.__inlineEmbedMap??=new Map;t.config.forEach(e=>{r.set(e.name,e),e.allowInline&&o.set(e.name,e)}),`embed_block`in e.renderer.rules||(e.block.ruler.before(`paragraph`,`embed_block`,a(r),{alt:[`paragraph`,`reference`,`blockquote`,`list`]}),e.renderer.rules.embed_block=(e,t)=>{let n=e[t];return r.get(n.info).setup(n.content,!1)}),o.size>0&&!(`embed_inline`in e.renderer.rules)&&(e.inline.ruler.before(`emphasis`,`embed_inline`,i(o)),e.renderer.rules.embed_inline=(e,t)=>{let n=e[t];return o.get(n.info).setup(n.content,!0)})};export{o as embed};
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type MarkdownIt from \"markdown-it\";\nimport type { PluginWithOptions } from \"markdown-it\";\nimport type { RuleBlock } from \"markdown-it/lib/parser_block.mjs\";\nimport type { RuleInline } from \"markdown-it/lib/parser_inline.mjs\";\nimport type Token from \"markdown-it/lib/token.mjs\";\n\nimport type { EmbedConfig, MarkdownItEmbedOptions } from \"./options.js\";\n\nconst ESCAPED_OPENING_MARKER_REGEXP = /\\\\{%/g;\nconst ESCAPED_CLOSING_MARKER_REGEXP = /%\\\\}/g;\n\nconst checkInlineOpeningMarker = (src: string, current: number): boolean => {\n if (src.charCodeAt(current) !== 123 /* { */ || src.charCodeAt(current + 1) !== 37 /* % */)\n return false;\n\n // Check if the opening marker was escaped\n let pos = current - 1;\n let backslashCount = 0;\n\n while (pos >= 0 && src.charCodeAt(pos) === 92 /* \\ */) {\n backslashCount++;\n pos--;\n }\n\n // If opening {% is escaped (odd number of preceding backslashes), don't parse\n if (backslashCount % 2 === 1) return false;\n\n return true;\n};\n\nconst checkClosingMarker = (src: string, current: number): boolean =>\n src.charCodeAt(current) === 37 /* % */ && src.charCodeAt(current + 1) === 125; /* } */\n\n/*\n * Parse inline embed with bracket syntax: {%...%}\n */\nconst createInlineEmbedRule =\n (inlineEmbedMap: Map<string, EmbedConfig>): RuleInline =>\n (state, silent) => {\n const isSpace = state.md.utils.isSpace;\n const start = state.pos;\n const max = state.src.length;\n\n // minimum length check for inline embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (!checkInlineOpeningMarker(state.src, start)) return false;\n\n let contentStart = start + 2; // Move past the opening {% marker\n\n // skip spaces\n while (contentStart < max) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let contentEnd = contentStart;\n let found = false;\n\n for (; contentEnd + 1 < max; contentEnd++) {\n // must not include opening marker\n if (checkInlineOpeningMarker(state.src, contentEnd)) return false;\n\n if (checkClosingMarker(state.src, contentEnd)) {\n found = true;\n break;\n }\n }\n\n // No closing marker found\n if (!found) return false;\n\n // get first space\n let spacer = contentStart + 1;\n\n while (spacer < contentEnd) {\n if (isSpace(state.src.charCodeAt(spacer))) break;\n\n spacer++;\n }\n\n // Extract embed name\n const name = state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!inlineEmbedMap.has(name)) return false;\n\n if (!silent) {\n const token = state.push(\"embed_inline\", \"embed\", 0);\n const params =\n spacer < contentEnd\n ? state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\")\n : \"\";\n\n token.markup = \"{% %}\";\n token.info = name;\n token.content = params;\n }\n // Move past the closing %} marker\n state.pos = contentEnd + 2;\n\n return true;\n };\n\n/*\n * Parse block embed with syntax: {% ... %}\n */\nconst createBlockEmbedRule =\n (embedMap: Map<string, EmbedConfig>): RuleBlock =>\n (state, startLine, _, silent) => {\n const isSpace = state.md.utils.isSpace;\n const start = state.bMarks[startLine] + state.tShift[startLine];\n let max = state.eMarks[startLine];\n const src = state.src;\n\n // minimum length check for block embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (\n state.src.charCodeAt(start) !== 123 /* { */ ||\n state.src.charCodeAt(start + 1) !== 37 /* % */\n )\n return false;\n\n max = state.skipSpacesBack(max, start);\n\n const contentEnd = max - 2;\n\n if (!checkClosingMarker(src, contentEnd)) return false;\n\n let contentStart = start + 2;\n\n // skip spaces\n while (contentStart < contentEnd) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let spacer = -1;\n\n for (let pos = contentStart; pos + 1 < contentEnd; pos++) {\n // must not include unescaped opening marker or closing marker\n if (checkInlineOpeningMarker(state.src, pos)) return false;\n\n if (checkClosingMarker(state.src, pos)) return false;\n\n if (spacer !== -1) continue;\n\n if (isSpace(state.src.charCodeAt(pos))) spacer = pos;\n }\n\n // Extract content between {% and %}\n const name =\n spacer === -1\n ? state.src.slice(contentStart, contentEnd).trimEnd()\n : state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!embedMap.has(name)) return false;\n\n // Fallback to inline if it's an inline-allowed embed without params\n // oxlint-disable-next-line typescript/no-non-null-assertion\n if (spacer === -1 && embedMap.get(name)!.allowInline) return false;\n\n if (silent) return true;\n\n const params =\n spacer === -1\n ? \"\"\n : state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\");\n\n const token = state.push(\"embed_block\", \"embed\", 0);\n\n token.block = true;\n token.info = name;\n token.content = params;\n token.map = [startLine, startLine + 1];\n token.markup = \"{% %}\";\n\n // Advance to the next line\n state.line = startLine + 1;\n\n return true;\n };\n\nexport const embed: PluginWithOptions<MarkdownItEmbedOptions> = (md, options) => {\n if (typeof options !== \"object\" || !Array.isArray(options.config))\n throw new TypeError(\"[@mdit/plugin-embed]: config is required and must be an array.\");\n\n // Get existing maps or create new ones to support multiple plugin instances\n const mdWithMaps = md as MarkdownIt & {\n __embedMap?: Map<string, EmbedConfig>;\n __inlineEmbedMap?: Map<string, EmbedConfig>;\n };\n\n const embedMap = (mdWithMaps.__embedMap ??= new Map<string, EmbedConfig>());\n const inlineEmbedMap = (mdWithMaps.__inlineEmbedMap ??= new Map<string, EmbedConfig>());\n\n options.config.forEach((item) => {\n embedMap.set(item.name, item);\n // Inline embeds are only supported when allowInline is true\n if (item.allowInline) inlineEmbedMap.set(item.name, item);\n });\n\n // Only register rules if not already registered\n // check embed_block rules here\n if (!(\"embed_block\" in md.renderer.rules)) {\n // Register the block rule\n md.block.ruler.before(\"paragraph\", \"embed_block\", createBlockEmbedRule(embedMap), {\n alt: [\"paragraph\", \"reference\", \"blockquote\", \"list\"],\n });\n\n // Register the renderers\n md.renderer.rules.embed_block = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return embedMap.get(token.info)!.setup(token.content, false);\n };\n }\n\n // only register embed_inline rules if inline embeds are allowed\n if (inlineEmbedMap.size > 0 && !(\"embed_inline\" in md.renderer.rules)) {\n // Register the inline rule\n md.inline.ruler.before(\"emphasis\", \"embed_inline\", createInlineEmbedRule(inlineEmbedMap));\n\n md.renderer.rules.embed_inline = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return inlineEmbedMap.get(token.info)!.setup(token.content, true);\n };\n }\n};\n"],"mappings":"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"}
+8
-8
{
"name": "@mdit/plugin-embed",
"version": "0.24.1",
"version": "0.25.0",
"description": "embed plugin for MarkdownIt",

@@ -26,11 +26,11 @@ "keywords": [

"files": [
"lib"
"dist"
],
"type": "module",
"browser": "./lib/browser.js",
"types": "./lib/index.d.ts",
"unpkg": "./dist/cdn.umd.js",
"jsdelivr": "./dist/cdn.umd.js",
"exports": {
".": {
"type": "./lib/index.d.ts",
"default": "./lib/index.js"
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},

@@ -54,8 +54,8 @@ "./package.json": "./package.json"

"engines": {
"node": ">= 18"
"node": ">= 20"
},
"scripts": {
"build": "tsdown --config-loader unrun",
"clean": "rimraf ./lib"
"clean": "rimraf ./dist"
}
}
function e(e){switch(e){case 9:case 32:return!0}return!1}const t=/\\{%/g,n=/%\\}/g,r=(e,t)=>{if(e.charCodeAt(t)!==123||e.charCodeAt(t+1)!==37)return!1;let n=t-1,r=0;for(;n>=0&&e.charCodeAt(n)===92;)r++,n--;return r%2!=1},i=(e,t)=>e.charCodeAt(t)===37&&e.charCodeAt(t+1)===125,a=a=>(o,s)=>{let c=o.pos,l=o.src.length;if(l-c<5||!r(o.src,c))return!1;let u=c+2;for(;u<l&&e(o.src.charCodeAt(u));)u++;let d=u,f=!1;for(;d+1<l;d++){if(r(o.src,d))return!1;if(i(o.src,d)){f=!0;break}}if(!f)return!1;let p=u+1;for(;p<d&&!e(o.src.charCodeAt(p));)p++;let m=o.src.slice(u,p);if(!a.has(m))return!1;if(!s){let e=o.push(`embed_inline`,`embed`,0),r=p?o.src.slice(p+1,d).trim().replaceAll(t,`{%`).replaceAll(n,`%}`):``;e.markup=`{% %}`,e.info=m,e.content=r}return o.pos=d+2,!0},o=a=>(o,s,c,l)=>{let u=o.bMarks[s]+o.tShift[s],d=o.eMarks[s],f=o.src;if(d-u<5||o.src.charCodeAt(u)!==123||o.src.charCodeAt(u+1)!==37)return!1;d=o.skipSpacesBack(d,u);let p=d-2;if(!i(f,p))return!1;let m=u+2;for(;m<p&&e(o.src.charCodeAt(m));)m++;let h=-1;for(let t=m;t+1<p;t++){if(r(o.src,t)||i(o.src,t))return!1;h===-1&&e(o.src.charCodeAt(t))&&(h=t)}let g=h===-1?o.src.slice(m,p+1).trimEnd():o.src.slice(m,h);if(!a.has(g))return!1;if(l)return!0;let _=h===-1?``:o.src.slice(h+1,p).trim().replaceAll(t,`{%`).replaceAll(n,`%}`),v=o.push(`embed_block`,`embed`,0);return v.block=!0,v.info=g,v.content=_,v.map=[s,s+1],v.markup=`{% %}`,o.line=s+1,!0},s=(e,t)=>{if(typeof t!=`object`||!Array.isArray(t.config))throw TypeError(`[@mdit/plugin-embed]: config is required and must be an array.`);let n=e,r=n.__embedMap??=new Map,i=n.__inlineEmbedMap??=new Map;t.config.forEach(e=>{r.set(e.name,e),e.allowInline&&i.set(e.name,e)}),`embed_block`in e.renderer.rules||(e.block.ruler.before(`paragraph`,`embed_block`,o(r),{alt:[`paragraph`,`reference`,`blockquote`,`list`]}),e.renderer.rules.embed_block=(e,t)=>{let n=e[t];return r.get(n.info).setup(n.content,!1)}),i.size>0&&!(`embed_inline`in e.renderer.rules)&&(e.inline.ruler.before(`emphasis`,`embed_inline`,a(i)),e.renderer.rules.embed_inline=(e,t)=>{let n=e[t];return i.get(n.info).setup(n.content,!0)})};export{s as embed};
//# sourceMappingURL=browser.js.map
{"version":3,"file":"browser.js","names":[],"sources":["../../../node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/lib/common/utils.mjs","../src/plugin.ts"],"sourcesContent":["// Utilities\n//\n\nimport * as mdurl from 'mdurl'\nimport * as ucmicro from 'uc.micro'\nimport { decodeHTML } from 'entities'\n\nfunction _class (obj) { return Object.prototype.toString.call(obj) }\n\nfunction isString (obj) { return _class(obj) === '[object String]' }\n\nconst _hasOwnProperty = Object.prototype.hasOwnProperty\n\nfunction has (object, key) {\n return _hasOwnProperty.call(object, key)\n}\n\n// Merge objects\n//\nfunction assign (obj /* from1, from2, from3, ... */) {\n const sources = Array.prototype.slice.call(arguments, 1)\n\n sources.forEach(function (source) {\n if (!source) { return }\n\n if (typeof source !== 'object') {\n throw new TypeError(source + 'must be object')\n }\n\n Object.keys(source).forEach(function (key) {\n obj[key] = source[key]\n })\n })\n\n return obj\n}\n\n// Remove element from array and put another array at those position.\n// Useful for some operations with tokens\nfunction arrayReplaceAt (src, pos, newElements) {\n return [].concat(src.slice(0, pos), newElements, src.slice(pos + 1))\n}\n\nfunction isValidEntityCode (c) {\n /* eslint no-bitwise:0 */\n // broken sequence\n if (c >= 0xD800 && c <= 0xDFFF) { return false }\n // never used\n if (c >= 0xFDD0 && c <= 0xFDEF) { return false }\n if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false }\n // control codes\n if (c >= 0x00 && c <= 0x08) { return false }\n if (c === 0x0B) { return false }\n if (c >= 0x0E && c <= 0x1F) { return false }\n if (c >= 0x7F && c <= 0x9F) { return false }\n // out of range\n if (c > 0x10FFFF) { return false }\n return true\n}\n\nfunction fromCodePoint (c) {\n /* eslint no-bitwise:0 */\n if (c > 0xffff) {\n c -= 0x10000\n const surrogate1 = 0xd800 + (c >> 10)\n const surrogate2 = 0xdc00 + (c & 0x3ff)\n\n return String.fromCharCode(surrogate1, surrogate2)\n }\n return String.fromCharCode(c)\n}\n\nconst UNESCAPE_MD_RE = /\\\\([!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{|}~])/g\nconst ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi\nconst UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi')\n\nconst DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i\n\nfunction replaceEntityPattern (match, name) {\n if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {\n const code = name[1].toLowerCase() === 'x'\n ? parseInt(name.slice(2), 16)\n : parseInt(name.slice(1), 10)\n\n if (isValidEntityCode(code)) {\n return fromCodePoint(code)\n }\n\n return match\n }\n\n const decoded = decodeHTML(match)\n if (decoded !== match) {\n return decoded\n }\n\n return match\n}\n\n/* function replaceEntities(str) {\n if (str.indexOf('&') < 0) { return str; }\n\n return str.replace(ENTITY_RE, replaceEntityPattern);\n} */\n\nfunction unescapeMd (str) {\n if (str.indexOf('\\\\') < 0) { return str }\n return str.replace(UNESCAPE_MD_RE, '$1')\n}\n\nfunction unescapeAll (str) {\n if (str.indexOf('\\\\') < 0 && str.indexOf('&') < 0) { return str }\n\n return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {\n if (escaped) { return escaped }\n return replaceEntityPattern(match, entity)\n })\n}\n\nconst HTML_ESCAPE_TEST_RE = /[&<>\"]/\nconst HTML_ESCAPE_REPLACE_RE = /[&<>\"]/g\nconst HTML_REPLACEMENTS = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;'\n}\n\nfunction replaceUnsafeChar (ch) {\n return HTML_REPLACEMENTS[ch]\n}\n\nfunction escapeHtml (str) {\n if (HTML_ESCAPE_TEST_RE.test(str)) {\n return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar)\n }\n return str\n}\n\nconst REGEXP_ESCAPE_RE = /[.?*+^$[\\]\\\\(){}|-]/g\n\nfunction escapeRE (str) {\n return str.replace(REGEXP_ESCAPE_RE, '\\\\$&')\n}\n\nfunction isSpace (code) {\n switch (code) {\n case 0x09:\n case 0x20:\n return true\n }\n return false\n}\n\n// Zs (unicode class) || [\\t\\f\\v\\r\\n]\nfunction isWhiteSpace (code) {\n if (code >= 0x2000 && code <= 0x200A) { return true }\n switch (code) {\n case 0x09: // \\t\n case 0x0A: // \\n\n case 0x0B: // \\v\n case 0x0C: // \\f\n case 0x0D: // \\r\n case 0x20:\n case 0xA0:\n case 0x1680:\n case 0x202F:\n case 0x205F:\n case 0x3000:\n return true\n }\n return false\n}\n\n/* eslint-disable max-len */\n\n// Currently without astral characters support.\nfunction isPunctChar (ch) {\n return ucmicro.P.test(ch) || ucmicro.S.test(ch)\n}\n\n// Markdown ASCII punctuation characters.\n//\n// !, \", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \\, ], ^, _, `, {, |, }, or ~\n// http://spec.commonmark.org/0.15/#ascii-punctuation-character\n//\n// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.\n//\nfunction isMdAsciiPunct (ch) {\n switch (ch) {\n case 0x21/* ! */:\n case 0x22/* \" */:\n case 0x23/* # */:\n case 0x24/* $ */:\n case 0x25/* % */:\n case 0x26/* & */:\n case 0x27/* ' */:\n case 0x28/* ( */:\n case 0x29/* ) */:\n case 0x2A/* * */:\n case 0x2B/* + */:\n case 0x2C/* , */:\n case 0x2D/* - */:\n case 0x2E/* . */:\n case 0x2F/* / */:\n case 0x3A/* : */:\n case 0x3B/* ; */:\n case 0x3C/* < */:\n case 0x3D/* = */:\n case 0x3E/* > */:\n case 0x3F/* ? */:\n case 0x40/* @ */:\n case 0x5B/* [ */:\n case 0x5C/* \\ */:\n case 0x5D/* ] */:\n case 0x5E/* ^ */:\n case 0x5F/* _ */:\n case 0x60/* ` */:\n case 0x7B/* { */:\n case 0x7C/* | */:\n case 0x7D/* } */:\n case 0x7E/* ~ */:\n return true\n default:\n return false\n }\n}\n\n// Hepler to unify [reference labels].\n//\nfunction normalizeReference (str) {\n // Trim and collapse whitespace\n //\n str = str.trim().replace(/\\s+/g, ' ')\n\n // In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug\n // fixed in v12 (couldn't find any details).\n //\n // So treat this one as a special case\n // (remove this when node v10 is no longer supported).\n //\n if ('ẞ'.toLowerCase() === 'Ṿ') {\n str = str.replace(/ẞ/g, 'ß')\n }\n\n // .toLowerCase().toUpperCase() should get rid of all differences\n // between letter variants.\n //\n // Simple .toLowerCase() doesn't normalize 125 code points correctly,\n // and .toUpperCase doesn't normalize 6 of them (list of exceptions:\n // İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently\n // uppercased versions).\n //\n // Here's an example showing how it happens. Lets take greek letter omega:\n // uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)\n //\n // Unicode entries:\n // 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;\n // 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398\n // 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398\n // 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;\n //\n // Case-insensitive comparison should treat all of them as equivalent.\n //\n // But .toLowerCase() doesn't change ϑ (it's already lowercase),\n // and .toUpperCase() doesn't change ϴ (already uppercase).\n //\n // Applying first lower then upper case normalizes any character:\n // '\\u0398\\u03f4\\u03b8\\u03d1'.toLowerCase().toUpperCase() === '\\u0398\\u0398\\u0398\\u0398'\n //\n // Note: this is equivalent to unicode case folding; unicode normalization\n // is a different step that is not required here.\n //\n // Final result should be uppercased, because it's later stored in an object\n // (this avoid a conflict with Object.prototype members,\n // most notably, `__proto__`)\n //\n return str.toLowerCase().toUpperCase()\n}\n\n// Re-export libraries commonly used in both markdown-it and its plugins,\n// so plugins won't have to depend on them explicitly, which reduces their\n// bundled size (e.g. a browser build).\n//\nconst lib = { mdurl, ucmicro }\n\nexport {\n lib,\n assign,\n isString,\n has,\n unescapeMd,\n unescapeAll,\n isValidEntityCode,\n fromCodePoint,\n escapeHtml,\n arrayReplaceAt,\n isSpace,\n isWhiteSpace,\n isMdAsciiPunct,\n isPunctChar,\n escapeRE,\n normalizeReference\n}\n","import type MarkdownIt from \"markdown-it\";\nimport type { PluginWithOptions } from \"markdown-it\";\nimport { isSpace } from \"markdown-it/lib/common/utils.mjs\";\nimport type { RuleBlock } from \"markdown-it/lib/parser_block.mjs\";\nimport type { RuleInline } from \"markdown-it/lib/parser_inline.mjs\";\nimport type Token from \"markdown-it/lib/token.mjs\";\n\nimport type { EmbedConfig, MarkdownItEmbedOptions } from \"./options.js\";\n\nconst ESCAPED_OPENING_MARKER_REGEXP = /\\\\{%/g;\nconst ESCAPED_CLOSING_MARKER_REGEXP = /%\\\\}/g;\n\nconst checkInlineOpeningMarker = (src: string, current: number): boolean => {\n if (src.charCodeAt(current) !== 123 /* { */ || src.charCodeAt(current + 1) !== 37 /* % */)\n return false;\n\n // Check if the opening marker was escaped\n let pos = current - 1;\n let backslashCount = 0;\n\n while (pos >= 0 && src.charCodeAt(pos) === 92 /* \\ */) {\n backslashCount++;\n pos--;\n }\n\n // If opening {% is escaped (odd number of preceding backslashes), don't parse\n if (backslashCount % 2 === 1) return false;\n\n return true;\n};\n\nconst checkClosingMarker = (src: string, current: number): boolean =>\n src.charCodeAt(current) === 37 /* % */ && src.charCodeAt(current + 1) === 125; /* } */\n\n/*\n * Parse inline embed with bracket syntax: {%...%}\n */\nconst getEmbedInline =\n (inlineEmbedMap: Map<string, EmbedConfig>): RuleInline =>\n (state, silent) => {\n const start = state.pos;\n const max = state.src.length;\n\n // minimum length check for inline embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (!checkInlineOpeningMarker(state.src, start)) return false;\n\n let contentStart = start + 2; // Move past the opening {% marker\n\n // skip spaces\n while (contentStart < max) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let contentEnd = contentStart;\n let found = false;\n\n for (; contentEnd + 1 < max; contentEnd++) {\n // must not include opening marker\n if (checkInlineOpeningMarker(state.src, contentEnd)) return false;\n\n if (checkClosingMarker(state.src, contentEnd)) {\n found = true;\n break;\n }\n }\n\n // No closing marker found\n if (!found) return false;\n\n // get first space\n let spacer = contentStart + 1;\n\n while (spacer < contentEnd) {\n if (isSpace(state.src.charCodeAt(spacer))) break;\n\n spacer++;\n }\n\n // Extract embed name\n const name = state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!inlineEmbedMap.has(name)) return false;\n\n if (!silent) {\n const token = state.push(\"embed_inline\", \"embed\", 0);\n const params = spacer\n ? state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\")\n : \"\";\n\n token.markup = \"{% %}\";\n token.info = name;\n token.content = params;\n }\n\n // Move past the closing %} marker\n state.pos = contentEnd + 2;\n\n return true;\n };\n\n/*\n * Parse block embed with syntax: {% ... %}\n */\nconst getEmbedBlock =\n (embedMap: Map<string, EmbedConfig>): RuleBlock =>\n (state, startLine, _, silent) => {\n const start = state.bMarks[startLine] + state.tShift[startLine];\n let max = state.eMarks[startLine];\n const src = state.src;\n\n // minimum length check for block embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (\n state.src.charCodeAt(start) !== 123 /* { */ ||\n state.src.charCodeAt(start + 1) !== 37 /* % */\n )\n return false;\n\n max = state.skipSpacesBack(max, start);\n\n const contentEnd = max - 2;\n\n if (!checkClosingMarker(src, contentEnd)) return false;\n\n let contentStart = start + 2;\n\n // skip spaces\n while (contentStart < contentEnd) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let spacer = -1;\n\n for (let pos = contentStart; pos + 1 < contentEnd; pos++) {\n // must not include unescaped opening marker or closing marker\n if (checkInlineOpeningMarker(state.src, pos)) return false;\n\n if (checkClosingMarker(state.src, pos)) return false;\n\n if (spacer !== -1) continue;\n\n if (isSpace(state.src.charCodeAt(pos))) spacer = pos;\n }\n\n // Extract content between {% and %}\n const name =\n spacer === -1\n ? state.src.slice(contentStart, contentEnd + 1).trimEnd()\n : state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!embedMap.has(name)) return false;\n\n if (silent) return true;\n\n const params =\n spacer === -1\n ? \"\"\n : state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\");\n\n const token = state.push(\"embed_block\", \"embed\", 0);\n\n token.block = true;\n token.info = name;\n token.content = params;\n token.map = [startLine, startLine + 1];\n token.markup = \"{% %}\";\n\n // Advance to the next line\n state.line = startLine + 1;\n\n return true;\n };\n\nexport const embed: PluginWithOptions<MarkdownItEmbedOptions> = (md, options) => {\n if (typeof options !== \"object\" || !Array.isArray(options.config))\n throw new TypeError(\"[@mdit/plugin-embed]: config is required and must be an array.\");\n\n // Get existing maps or create new ones to support multiple plugin instances\n const mdWithMaps = md as MarkdownIt & {\n // oxlint-disable-next-line typescript/naming-convention\n __embedMap?: Map<string, EmbedConfig>;\n // oxlint-disable-next-line typescript/naming-convention\n __inlineEmbedMap?: Map<string, EmbedConfig>;\n };\n\n const embedMap = (mdWithMaps.__embedMap ??= new Map<string, EmbedConfig>());\n const inlineEmbedMap = (mdWithMaps.__inlineEmbedMap ??= new Map<string, EmbedConfig>());\n\n options.config.forEach((item) => {\n embedMap.set(item.name, item);\n // Inline embeds are only supported when allowInline is true\n if (item.allowInline) inlineEmbedMap.set(item.name, item);\n });\n\n // Only register rules if not already registered\n // check embed_block rules here\n if (!(\"embed_block\" in md.renderer.rules)) {\n // Register the block rule\n md.block.ruler.before(\"paragraph\", \"embed_block\", getEmbedBlock(embedMap), {\n alt: [\"paragraph\", \"reference\", \"blockquote\", \"list\"],\n });\n\n // Register the renderers\n md.renderer.rules.embed_block = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return embedMap.get(token.info)!.setup(token.content, false);\n };\n }\n\n // only register embed_inline rules if inline embeds are allowed\n if (inlineEmbedMap.size > 0 && !(\"embed_inline\" in md.renderer.rules)) {\n // Register the inline rule\n md.inline.ruler.before(\"emphasis\", \"embed_inline\", getEmbedInline(inlineEmbedMap));\n\n md.renderer.rules.embed_inline = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return inlineEmbedMap.get(token.info)!.setup(token.content, true);\n };\n }\n};\n"],"x_google_ignoreList":[0],"mappings":"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"}
import { PluginWithOptions } from "markdown-it";
//#region src/options.d.ts
interface EmbedConfig {
/**
* Embed token name
*
* 嵌入令牌名称
*/
name: string;
/**
* Setup function to generate embed HTML
*
* 生成嵌入 HTML 的设置函数
*/
setup: (ref: string, isInline: boolean) => string;
/**
* Whether the embed can be used inline
*
* 是否允许在行内使用
*
* @default false
*/
allowInline?: boolean;
}
interface MarkdownItEmbedOptions {
/**
* Embed configurations
*
* 嵌入配置
*/
config?: EmbedConfig[];
}
//#endregion
//#region src/plugin.d.ts
declare const embed: PluginWithOptions<MarkdownItEmbedOptions>;
//#endregion
export { EmbedConfig, MarkdownItEmbedOptions, embed };
//# sourceMappingURL=index.d.ts.map
import{isSpace as e}from"markdown-it/lib/common/utils.mjs";const t=/\\{%/g,n=/%\\}/g,r=(e,t)=>{if(e.charCodeAt(t)!==123||e.charCodeAt(t+1)!==37)return!1;let n=t-1,r=0;for(;n>=0&&e.charCodeAt(n)===92;)r++,n--;return r%2!=1},i=(e,t)=>e.charCodeAt(t)===37&&e.charCodeAt(t+1)===125,a=a=>(o,s)=>{let c=o.pos,l=o.src.length;if(l-c<5||!r(o.src,c))return!1;let u=c+2;for(;u<l&&e(o.src.charCodeAt(u));)u++;let d=u,f=!1;for(;d+1<l;d++){if(r(o.src,d))return!1;if(i(o.src,d)){f=!0;break}}if(!f)return!1;let p=u+1;for(;p<d&&!e(o.src.charCodeAt(p));)p++;let m=o.src.slice(u,p);if(!a.has(m))return!1;if(!s){let e=o.push(`embed_inline`,`embed`,0),r=p?o.src.slice(p+1,d).trim().replaceAll(t,`{%`).replaceAll(n,`%}`):``;e.markup=`{% %}`,e.info=m,e.content=r}return o.pos=d+2,!0},o=a=>(o,s,c,l)=>{let u=o.bMarks[s]+o.tShift[s],d=o.eMarks[s],f=o.src;if(d-u<5||o.src.charCodeAt(u)!==123||o.src.charCodeAt(u+1)!==37)return!1;d=o.skipSpacesBack(d,u);let p=d-2;if(!i(f,p))return!1;let m=u+2;for(;m<p&&e(o.src.charCodeAt(m));)m++;let h=-1;for(let t=m;t+1<p;t++){if(r(o.src,t)||i(o.src,t))return!1;h===-1&&e(o.src.charCodeAt(t))&&(h=t)}let g=h===-1?o.src.slice(m,p+1).trimEnd():o.src.slice(m,h);if(!a.has(g))return!1;if(l)return!0;let _=h===-1?``:o.src.slice(h+1,p).trim().replaceAll(t,`{%`).replaceAll(n,`%}`),v=o.push(`embed_block`,`embed`,0);return v.block=!0,v.info=g,v.content=_,v.map=[s,s+1],v.markup=`{% %}`,o.line=s+1,!0},s=(e,t)=>{if(typeof t!=`object`||!Array.isArray(t.config))throw TypeError(`[@mdit/plugin-embed]: config is required and must be an array.`);let n=e,r=n.__embedMap??=new Map,i=n.__inlineEmbedMap??=new Map;t.config.forEach(e=>{r.set(e.name,e),e.allowInline&&i.set(e.name,e)}),`embed_block`in e.renderer.rules||(e.block.ruler.before(`paragraph`,`embed_block`,o(r),{alt:[`paragraph`,`reference`,`blockquote`,`list`]}),e.renderer.rules.embed_block=(e,t)=>{let n=e[t];return r.get(n.info).setup(n.content,!1)}),i.size>0&&!(`embed_inline`in e.renderer.rules)&&(e.inline.ruler.before(`emphasis`,`embed_inline`,a(i)),e.renderer.rules.embed_inline=(e,t)=>{let n=e[t];return i.get(n.info).setup(n.content,!0)})};export{s as embed};
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type MarkdownIt from \"markdown-it\";\nimport type { PluginWithOptions } from \"markdown-it\";\nimport { isSpace } from \"markdown-it/lib/common/utils.mjs\";\nimport type { RuleBlock } from \"markdown-it/lib/parser_block.mjs\";\nimport type { RuleInline } from \"markdown-it/lib/parser_inline.mjs\";\nimport type Token from \"markdown-it/lib/token.mjs\";\n\nimport type { EmbedConfig, MarkdownItEmbedOptions } from \"./options.js\";\n\nconst ESCAPED_OPENING_MARKER_REGEXP = /\\\\{%/g;\nconst ESCAPED_CLOSING_MARKER_REGEXP = /%\\\\}/g;\n\nconst checkInlineOpeningMarker = (src: string, current: number): boolean => {\n if (src.charCodeAt(current) !== 123 /* { */ || src.charCodeAt(current + 1) !== 37 /* % */)\n return false;\n\n // Check if the opening marker was escaped\n let pos = current - 1;\n let backslashCount = 0;\n\n while (pos >= 0 && src.charCodeAt(pos) === 92 /* \\ */) {\n backslashCount++;\n pos--;\n }\n\n // If opening {% is escaped (odd number of preceding backslashes), don't parse\n if (backslashCount % 2 === 1) return false;\n\n return true;\n};\n\nconst checkClosingMarker = (src: string, current: number): boolean =>\n src.charCodeAt(current) === 37 /* % */ && src.charCodeAt(current + 1) === 125; /* } */\n\n/*\n * Parse inline embed with bracket syntax: {%...%}\n */\nconst getEmbedInline =\n (inlineEmbedMap: Map<string, EmbedConfig>): RuleInline =>\n (state, silent) => {\n const start = state.pos;\n const max = state.src.length;\n\n // minimum length check for inline embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (!checkInlineOpeningMarker(state.src, start)) return false;\n\n let contentStart = start + 2; // Move past the opening {% marker\n\n // skip spaces\n while (contentStart < max) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let contentEnd = contentStart;\n let found = false;\n\n for (; contentEnd + 1 < max; contentEnd++) {\n // must not include opening marker\n if (checkInlineOpeningMarker(state.src, contentEnd)) return false;\n\n if (checkClosingMarker(state.src, contentEnd)) {\n found = true;\n break;\n }\n }\n\n // No closing marker found\n if (!found) return false;\n\n // get first space\n let spacer = contentStart + 1;\n\n while (spacer < contentEnd) {\n if (isSpace(state.src.charCodeAt(spacer))) break;\n\n spacer++;\n }\n\n // Extract embed name\n const name = state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!inlineEmbedMap.has(name)) return false;\n\n if (!silent) {\n const token = state.push(\"embed_inline\", \"embed\", 0);\n const params = spacer\n ? state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\")\n : \"\";\n\n token.markup = \"{% %}\";\n token.info = name;\n token.content = params;\n }\n\n // Move past the closing %} marker\n state.pos = contentEnd + 2;\n\n return true;\n };\n\n/*\n * Parse block embed with syntax: {% ... %}\n */\nconst getEmbedBlock =\n (embedMap: Map<string, EmbedConfig>): RuleBlock =>\n (state, startLine, _, silent) => {\n const start = state.bMarks[startLine] + state.tShift[startLine];\n let max = state.eMarks[startLine];\n const src = state.src;\n\n // minimum length check for block embed - at least 5 characters: {%x%}\n if (max - start < 5) return false;\n\n // check opening marker\n if (\n state.src.charCodeAt(start) !== 123 /* { */ ||\n state.src.charCodeAt(start + 1) !== 37 /* % */\n )\n return false;\n\n max = state.skipSpacesBack(max, start);\n\n const contentEnd = max - 2;\n\n if (!checkClosingMarker(src, contentEnd)) return false;\n\n let contentStart = start + 2;\n\n // skip spaces\n while (contentStart < contentEnd) {\n if (!isSpace(state.src.charCodeAt(contentStart))) break;\n\n contentStart++;\n }\n\n let spacer = -1;\n\n for (let pos = contentStart; pos + 1 < contentEnd; pos++) {\n // must not include unescaped opening marker or closing marker\n if (checkInlineOpeningMarker(state.src, pos)) return false;\n\n if (checkClosingMarker(state.src, pos)) return false;\n\n if (spacer !== -1) continue;\n\n if (isSpace(state.src.charCodeAt(pos))) spacer = pos;\n }\n\n // Extract content between {% and %}\n const name =\n spacer === -1\n ? state.src.slice(contentStart, contentEnd + 1).trimEnd()\n : state.src.slice(contentStart, spacer);\n\n // Check if embed name exists in the map\n if (!embedMap.has(name)) return false;\n\n if (silent) return true;\n\n const params =\n spacer === -1\n ? \"\"\n : state.src\n .slice(spacer + 1, contentEnd)\n .trim()\n .replaceAll(ESCAPED_OPENING_MARKER_REGEXP, \"{%\")\n .replaceAll(ESCAPED_CLOSING_MARKER_REGEXP, \"%}\");\n\n const token = state.push(\"embed_block\", \"embed\", 0);\n\n token.block = true;\n token.info = name;\n token.content = params;\n token.map = [startLine, startLine + 1];\n token.markup = \"{% %}\";\n\n // Advance to the next line\n state.line = startLine + 1;\n\n return true;\n };\n\nexport const embed: PluginWithOptions<MarkdownItEmbedOptions> = (md, options) => {\n if (typeof options !== \"object\" || !Array.isArray(options.config))\n throw new TypeError(\"[@mdit/plugin-embed]: config is required and must be an array.\");\n\n // Get existing maps or create new ones to support multiple plugin instances\n const mdWithMaps = md as MarkdownIt & {\n // oxlint-disable-next-line typescript/naming-convention\n __embedMap?: Map<string, EmbedConfig>;\n // oxlint-disable-next-line typescript/naming-convention\n __inlineEmbedMap?: Map<string, EmbedConfig>;\n };\n\n const embedMap = (mdWithMaps.__embedMap ??= new Map<string, EmbedConfig>());\n const inlineEmbedMap = (mdWithMaps.__inlineEmbedMap ??= new Map<string, EmbedConfig>());\n\n options.config.forEach((item) => {\n embedMap.set(item.name, item);\n // Inline embeds are only supported when allowInline is true\n if (item.allowInline) inlineEmbedMap.set(item.name, item);\n });\n\n // Only register rules if not already registered\n // check embed_block rules here\n if (!(\"embed_block\" in md.renderer.rules)) {\n // Register the block rule\n md.block.ruler.before(\"paragraph\", \"embed_block\", getEmbedBlock(embedMap), {\n alt: [\"paragraph\", \"reference\", \"blockquote\", \"list\"],\n });\n\n // Register the renderers\n md.renderer.rules.embed_block = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return embedMap.get(token.info)!.setup(token.content, false);\n };\n }\n\n // only register embed_inline rules if inline embeds are allowed\n if (inlineEmbedMap.size > 0 && !(\"embed_inline\" in md.renderer.rules)) {\n // Register the inline rule\n md.inline.ruler.before(\"emphasis\", \"embed_inline\", getEmbedInline(inlineEmbedMap));\n\n md.renderer.rules.embed_inline = (tokens: Token[], index: number): string => {\n const token = tokens[index];\n\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return inlineEmbedMap.get(token.info)!.setup(token.content, true);\n };\n }\n};\n"],"mappings":"2DASA,MAAM,EAAgC,QAChC,EAAgC,QAEhC,GAA4B,EAAa,IAA6B,CAC1E,GAAI,EAAI,WAAW,EAAQ,GAAK,KAAe,EAAI,WAAW,EAAU,EAAE,GAAK,GAC7E,MAAO,GAGT,IAAI,EAAM,EAAU,EAChB,EAAiB,EAErB,KAAO,GAAO,GAAK,EAAI,WAAW,EAAI,GAAK,IACzC,IACA,IAMF,OAFI,EAAiB,GAAM,GAKvB,GAAsB,EAAa,IACvC,EAAI,WAAW,EAAQ,GAAK,IAAc,EAAI,WAAW,EAAU,EAAE,GAAK,IAKtE,EACH,IACA,EAAO,IAAW,CACjB,IAAM,EAAQ,EAAM,IACd,EAAM,EAAM,IAAI,OAMtB,GAHI,EAAM,EAAQ,GAGd,CAAC,EAAyB,EAAM,IAAK,EAAM,CAAE,MAAO,GAExD,IAAI,EAAe,EAAQ,EAG3B,KAAO,EAAe,GACf,EAAQ,EAAM,IAAI,WAAW,EAAa,CAAC,EAEhD,IAGF,IAAI,EAAa,EACb,EAAQ,GAEZ,KAAO,EAAa,EAAI,EAAK,IAAc,CAEzC,GAAI,EAAyB,EAAM,IAAK,EAAW,CAAE,MAAO,GAE5D,GAAI,EAAmB,EAAM,IAAK,EAAW,CAAE,CAC7C,EAAQ,GACR,OAKJ,GAAI,CAAC,EAAO,MAAO,GAGnB,IAAI,EAAS,EAAe,EAE5B,KAAO,EAAS,GACV,GAAQ,EAAM,IAAI,WAAW,EAAO,CAAC,EAEzC,IAIF,IAAM,EAAO,EAAM,IAAI,MAAM,EAAc,EAAO,CAGlD,GAAI,CAAC,EAAe,IAAI,EAAK,CAAE,MAAO,GAEtC,GAAI,CAAC,EAAQ,CACX,IAAM,EAAQ,EAAM,KAAK,eAAgB,QAAS,EAAE,CAC9C,EAAS,EACX,EAAM,IACH,MAAM,EAAS,EAAG,EAAW,CAC7B,MAAM,CACN,WAAW,EAA+B,KAAK,CAC/C,WAAW,EAA+B,KAAK,CAClD,GAEJ,EAAM,OAAS,QACf,EAAM,KAAO,EACb,EAAM,QAAU,EAMlB,MAFA,GAAM,IAAM,EAAa,EAElB,IAML,EACH,IACA,EAAO,EAAW,EAAG,IAAW,CAC/B,IAAM,EAAQ,EAAM,OAAO,GAAa,EAAM,OAAO,GACjD,EAAM,EAAM,OAAO,GACjB,EAAM,EAAM,IAMlB,GAHI,EAAM,EAAQ,GAIhB,EAAM,IAAI,WAAW,EAAM,GAAK,KAChC,EAAM,IAAI,WAAW,EAAQ,EAAE,GAAK,GAEpC,MAAO,GAET,EAAM,EAAM,eAAe,EAAK,EAAM,CAEtC,IAAM,EAAa,EAAM,EAEzB,GAAI,CAAC,EAAmB,EAAK,EAAW,CAAE,MAAO,GAEjD,IAAI,EAAe,EAAQ,EAG3B,KAAO,EAAe,GACf,EAAQ,EAAM,IAAI,WAAW,EAAa,CAAC,EAEhD,IAGF,IAAI,EAAS,GAEb,IAAK,IAAI,EAAM,EAAc,EAAM,EAAI,EAAY,IAAO,CAIxD,GAFI,EAAyB,EAAM,IAAK,EAAI,EAExC,EAAmB,EAAM,IAAK,EAAI,CAAE,MAAO,GAE3C,IAAW,IAEX,EAAQ,EAAM,IAAI,WAAW,EAAI,CAAC,GAAE,EAAS,GAInD,IAAM,EACJ,IAAW,GACP,EAAM,IAAI,MAAM,EAAc,EAAa,EAAE,CAAC,SAAS,CACvD,EAAM,IAAI,MAAM,EAAc,EAAO,CAG3C,GAAI,CAAC,EAAS,IAAI,EAAK,CAAE,MAAO,GAEhC,GAAI,EAAQ,MAAO,GAEnB,IAAM,EACJ,IAAW,GACP,GACA,EAAM,IACH,MAAM,EAAS,EAAG,EAAW,CAC7B,MAAM,CACN,WAAW,EAA+B,KAAK,CAC/C,WAAW,EAA+B,KAAK,CAElD,EAAQ,EAAM,KAAK,cAAe,QAAS,EAAE,CAWnD,MATA,GAAM,MAAQ,GACd,EAAM,KAAO,EACb,EAAM,QAAU,EAChB,EAAM,IAAM,CAAC,EAAW,EAAY,EAAE,CACtC,EAAM,OAAS,QAGf,EAAM,KAAO,EAAY,EAElB,IAGE,GAAoD,EAAI,IAAY,CAC/E,GAAI,OAAO,GAAY,UAAY,CAAC,MAAM,QAAQ,EAAQ,OAAO,CAC/D,MAAU,UAAU,iEAAiE,CAGvF,IAAM,EAAa,EAOb,EAAY,EAAW,aAAe,IAAI,IAC1C,EAAkB,EAAW,mBAAqB,IAAI,IAE5D,EAAQ,OAAO,QAAS,GAAS,CAC/B,EAAS,IAAI,EAAK,KAAM,EAAK,CAEzB,EAAK,aAAa,EAAe,IAAI,EAAK,KAAM,EAAK,EACzD,CAII,gBAAiB,EAAG,SAAS,QAEjC,EAAG,MAAM,MAAM,OAAO,YAAa,cAAe,EAAc,EAAS,CAAE,CACzE,IAAK,CAAC,YAAa,YAAa,aAAc,OAAO,CACtD,CAAC,CAGF,EAAG,SAAS,MAAM,aAAe,EAAiB,IAA0B,CAC1E,IAAM,EAAQ,EAAO,GAGrB,OAAO,EAAS,IAAI,EAAM,KAAK,CAAE,MAAM,EAAM,QAAS,GAAM,GAK5D,EAAe,KAAO,GAAK,EAAE,iBAAkB,EAAG,SAAS,SAE7D,EAAG,OAAO,MAAM,OAAO,WAAY,eAAgB,EAAe,EAAe,CAAC,CAElF,EAAG,SAAS,MAAM,cAAgB,EAAiB,IAA0B,CAC3E,IAAM,EAAQ,EAAO,GAGrB,OAAO,EAAe,IAAI,EAAM,KAAK,CAAE,MAAM,EAAM,QAAS,GAAK"}