vue3-markdown-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/NOTICE.md +16 -0
- package/README.md +177 -0
- package/SECURITY.md +14 -0
- package/lib/core.cjs +197 -0
- package/lib/core.cjs.map +7 -0
- package/lib/core.js +165 -0
- package/lib/core.js.map +7 -0
- package/lib/index.cjs +363 -0
- package/lib/index.cjs.map +7 -0
- package/lib/index.js +331 -0
- package/lib/index.js.map +7 -0
- package/lib/preview.cjs +325 -0
- package/lib/preview.cjs.map +7 -0
- package/lib/preview.js +295 -0
- package/lib/preview.js.map +7 -0
- package/lib/style/preview.css +23 -0
- package/lib/theme/github.cjs +143 -0
- package/lib/theme/github.cjs.map +7 -0
- package/lib/theme/github.js +111 -0
- package/lib/theme/github.js.map +7 -0
- package/lib/theme/style/github.css +187 -0
- package/package.json +112 -0
- package/types/core.d.ts +40 -0
- package/types/index.d.ts +20 -0
- package/types/preview.d.ts +39 -0
- package/types/theme-github.d.ts +15 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/preview.js", "../src/core/renderer.js", "../src/core/sanitize.js", "../src/version.js"],
|
|
4
|
+
"sourcesContent": ["import { defineComponent, h, shallowRef, watch } from 'vue'\nimport { createMarkdownRenderer } from './core/renderer.js'\nimport { sanitizer } from './core/sanitize.js'\nimport { version } from './version.js'\n\nconst defaultThemeConfig = {\n name: 'base',\n previewClass: 'vmk-markdown-body',\n markdownParser: createMarkdownRenderer(),\n extend(callback) {\n callback(this.markdownParser)\n },\n}\n\nconst markdownExtenders = []\nlet activeThemeConfig = defaultThemeConfig\n\nfunction installTheme(theme, options) {\n if (!theme) return\n\n if (typeof theme === 'function') {\n theme(VMdPreview, options)\n } else if (typeof theme.install === 'function') {\n theme.install(VMdPreview, options)\n } else if (theme.markdownParser) {\n VMdPreview.theme(theme)\n }\n}\n\nconst VMdPreview = defineComponent({\n name: 'v-md-preview',\n\n props: {\n text: {\n type: String,\n default: '',\n },\n theme: {\n type: Object,\n default: undefined,\n },\n tabSize: {\n type: Number,\n default: 2,\n },\n scrollContainer: {\n type: Function,\n default: () => window,\n },\n top: {\n type: Number,\n default: 0,\n },\n sanitizeOptions: {\n type: Object,\n default: () => ({}),\n },\n },\n\n emits: {\n change: (_text, _html) => true,\n 'image-click': (_images, _index) => true,\n },\n\n setup(props, { emit }) {\n const rootElement = shallowRef(null)\n const html = shallowRef('')\n\n if (props.theme) {\n installTheme(props.theme)\n }\n\n for (const extender of markdownExtenders) {\n extender(activeThemeConfig.markdownParser)\n }\n\n const renderMarkdown = () => {\n const rawHtml = activeThemeConfig.markdownParser.render(props.text || '')\n html.value = sanitizer.process(rawHtml, props.sanitizeOptions)\n emit('change', props.text, html.value)\n }\n\n watch([() => props.text, () => props.sanitizeOptions], renderMarkdown, {\n deep: true,\n immediate: true,\n })\n\n const handlePreviewClick = (event) => {\n const target = event.target\n const root = rootElement.value\n\n if (!root || !target || target.tagName !== 'IMG') {\n return\n }\n\n const imageElements = Array.from(root.querySelectorAll('img'))\n const images = imageElements\n .map((image) => image.getAttribute('src'))\n .filter(Boolean)\n const index = imageElements.indexOf(target)\n\n emit('image-click', images, index)\n }\n\n return () =>\n h(\n 'div',\n {\n ref: rootElement,\n class: 'vue-markdown-kit-preview',\n style: {\n tabSize: props.tabSize,\n MozTabSize: props.tabSize,\n },\n onClick: handlePreviewClick,\n },\n [\n h('div', {\n class: activeThemeConfig.previewClass,\n innerHTML: html.value,\n }),\n ],\n )\n },\n})\n\nVMdPreview.version = version\nVMdPreview.install = (app) => {\n app.component(VMdPreview.name, VMdPreview)\n}\nVMdPreview.theme = (themeConfig) => {\n activeThemeConfig = themeConfig || defaultThemeConfig\n return VMdPreview\n}\nVMdPreview.use = (theme, options) => {\n installTheme(theme, options)\n return VMdPreview\n}\nVMdPreview.extendMarkdown = (extender) => {\n markdownExtenders.push(extender)\n return VMdPreview\n}\nVMdPreview.xss = sanitizer\nVMdPreview.lang = {\n use() {},\n add() {},\n}\n\nexport default VMdPreview\n", "import MarkdownIt from 'markdown-it'\nimport markdownItAttrs from 'markdown-it-attrs'\n\nfunction escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n}\n\nexport function slugifyHeading(value) {\n const slug = String(value || '')\n .normalize('NFKC')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^\\p{Letter}\\p{Number}_-]+/gu, '')\n .replace(/-{2,}/g, '-')\n .replace(/^-|-$/g, '')\n\n return slug || 'section'\n}\n\nfunction highlightCode(code, language, options) {\n const {\n Hljs,\n codeHighlightExtensionMap = {},\n codeBlockClass = (lang) => `v-md-hljs-${lang || ''}`,\n } = options\n\n const normalizedLanguage = codeHighlightExtensionMap[language] || language\n let highlighted = escapeHtml(code)\n\n if (\n Hljs &&\n normalizedLanguage &&\n typeof Hljs.getLanguage === 'function' &&\n Hljs.getLanguage(normalizedLanguage)\n ) {\n try {\n highlighted = Hljs.highlight(code, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n }).value\n } catch {\n // highlight.js 10 compatibility.\n highlighted = Hljs.highlight(normalizedLanguage, code, true).value\n }\n }\n\n return `<pre class=\"${escapeHtml(codeBlockClass(normalizedLanguage))}\"><code>${highlighted}</code></pre>`\n}\n\nfunction installHeadingAnchors(parser) {\n parser.core.ruler.before('block', 'vue_markdown_kit_heading_state', (state) => {\n state.env.__vueMarkdownKitHeadingSlugs = new Map()\n })\n\n const fallback =\n parser.renderer.rules.heading_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.heading_open = (tokens, index, options, env, self) => {\n const inline = tokens[index + 1]\n const baseSlug = slugifyHeading(inline && inline.content)\n const slugs = env.__vueMarkdownKitHeadingSlugs || new Map()\n const count = slugs.get(baseSlug) || 0\n const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`\n\n slugs.set(baseSlug, count + 1)\n env.__vueMarkdownKitHeadingSlugs = slugs\n\n tokens[index].attrSet('id', slug)\n tokens[index].attrSet('data-v-md-heading', slug)\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nfunction installSafeExternalLinks(parser) {\n const fallback =\n parser.renderer.rules.link_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.link_open = (tokens, index, options, env, self) => {\n const token = tokens[index]\n const href = token.attrGet('href') || ''\n\n if (/^https?:\\/\\//i.test(href)) {\n token.attrSet('target', '_blank')\n token.attrSet('rel', 'noopener noreferrer')\n }\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nexport function createMarkdownRenderer(options = {}) {\n const parser = new MarkdownIt({\n html: options.html ?? true,\n breaks: options.breaks ?? true,\n linkify: options.linkify ?? false,\n typographer: options.typographer ?? true,\n highlight: (code, language) => highlightCode(code, language, options),\n })\n\n if (options.attrs !== false) {\n parser.use(markdownItAttrs, {\n leftDelimiter: '{{{',\n rightDelimiter: '}}}',\n allowedAttributes: [\n 'class',\n 'height',\n 'id',\n 'title',\n 'width',\n ...(options.allowedAttributes || []),\n ],\n })\n }\n\n installHeadingAnchors(parser)\n installSafeExternalLinks(parser)\n\n return parser\n}\n", "import createDOMPurify from 'dompurify'\n\nconst BASE_SANITIZE_OPTIONS = Object.freeze({\n USE_PROFILES: {\n html: true,\n },\n ADD_ATTR: [\n 'data-mention-id',\n 'data-v-md-anchor',\n 'data-v-md-heading',\n 'data-v-md-line',\n 'rel',\n 'target',\n ],\n FORBID_TAGS: ['script'],\n})\n\nlet sharedOptions = {}\n\nfunction mergeOptions(base, extra) {\n const merged = {\n ...base,\n ...extra,\n }\n\n for (const key of ['ADD_ATTR', 'ADD_TAGS', 'FORBID_ATTR', 'FORBID_TAGS']) {\n if (base[key] || extra[key]) {\n merged[key] = [...new Set([...(base[key] || []), ...(extra[key] || [])])]\n }\n }\n\n if (base.USE_PROFILES || extra.USE_PROFILES) {\n merged.USE_PROFILES = {\n ...(base.USE_PROFILES || {}),\n ...(extra.USE_PROFILES || {}),\n }\n }\n\n return merged\n}\n\nfunction resolvePurifier(windowLike) {\n if (typeof createDOMPurify.sanitize === 'function') {\n return createDOMPurify\n }\n\n if (windowLike && typeof createDOMPurify === 'function') {\n return createDOMPurify(windowLike)\n }\n\n return null\n}\n\nfunction escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\nexport function sanitizeHtml(\n dirtyHtml,\n options = {},\n windowLike = typeof window === 'undefined' ? undefined : window,\n) {\n const purifier = resolvePurifier(windowLike)\n\n // Fail closed in non-DOM environments rather than returning executable HTML.\n if (!purifier || typeof purifier.sanitize !== 'function') {\n return escapeHtml(dirtyHtml || '')\n }\n\n return purifier.sanitize(\n dirtyHtml || '',\n mergeOptions(mergeOptions(BASE_SANITIZE_OPTIONS, sharedOptions), options),\n )\n}\n\nexport const sanitizer = {\n process(dirtyHtml, options) {\n return sanitizeHtml(dirtyHtml, options)\n },\n\n extend(options = {}) {\n sharedOptions = mergeOptions(sharedOptions, options)\n return this\n },\n\n reset() {\n sharedOptions = {}\n return this\n },\n}\n", "export const version = '0.1.0'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["MarkdownIt", "markdownItAttrs", "createDOMPurify", "escapeHtml"]
|
|
7
|
+
}
|
package/lib/preview.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// src/preview.js
|
|
2
|
+
import { defineComponent, h, shallowRef, watch } from "vue";
|
|
3
|
+
|
|
4
|
+
// src/core/renderer.js
|
|
5
|
+
import MarkdownIt from "markdown-it";
|
|
6
|
+
import markdownItAttrs from "markdown-it-attrs";
|
|
7
|
+
function escapeHtml(value) {
|
|
8
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
9
|
+
}
|
|
10
|
+
function slugifyHeading(value) {
|
|
11
|
+
const slug = String(value || "").normalize("NFKC").trim().toLowerCase().replace(/\s+/g, "-").replace(/[^\p{Letter}\p{Number}_-]+/gu, "").replace(/-{2,}/g, "-").replace(/^-|-$/g, "");
|
|
12
|
+
return slug || "section";
|
|
13
|
+
}
|
|
14
|
+
function highlightCode(code, language, options) {
|
|
15
|
+
const {
|
|
16
|
+
Hljs,
|
|
17
|
+
codeHighlightExtensionMap = {},
|
|
18
|
+
codeBlockClass = (lang) => `v-md-hljs-${lang || ""}`
|
|
19
|
+
} = options;
|
|
20
|
+
const normalizedLanguage = codeHighlightExtensionMap[language] || language;
|
|
21
|
+
let highlighted = escapeHtml(code);
|
|
22
|
+
if (Hljs && normalizedLanguage && typeof Hljs.getLanguage === "function" && Hljs.getLanguage(normalizedLanguage)) {
|
|
23
|
+
try {
|
|
24
|
+
highlighted = Hljs.highlight(code, {
|
|
25
|
+
language: normalizedLanguage,
|
|
26
|
+
ignoreIllegals: true
|
|
27
|
+
}).value;
|
|
28
|
+
} catch {
|
|
29
|
+
highlighted = Hljs.highlight(normalizedLanguage, code, true).value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return `<pre class="${escapeHtml(codeBlockClass(normalizedLanguage))}"><code>${highlighted}</code></pre>`;
|
|
33
|
+
}
|
|
34
|
+
function installHeadingAnchors(parser) {
|
|
35
|
+
parser.core.ruler.before("block", "vue_markdown_kit_heading_state", (state) => {
|
|
36
|
+
state.env.__vueMarkdownKitHeadingSlugs = /* @__PURE__ */ new Map();
|
|
37
|
+
});
|
|
38
|
+
const fallback = parser.renderer.rules.heading_open || ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options));
|
|
39
|
+
parser.renderer.rules.heading_open = (tokens, index, options, env, self) => {
|
|
40
|
+
const inline = tokens[index + 1];
|
|
41
|
+
const baseSlug = slugifyHeading(inline && inline.content);
|
|
42
|
+
const slugs = env.__vueMarkdownKitHeadingSlugs || /* @__PURE__ */ new Map();
|
|
43
|
+
const count = slugs.get(baseSlug) || 0;
|
|
44
|
+
const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`;
|
|
45
|
+
slugs.set(baseSlug, count + 1);
|
|
46
|
+
env.__vueMarkdownKitHeadingSlugs = slugs;
|
|
47
|
+
tokens[index].attrSet("id", slug);
|
|
48
|
+
tokens[index].attrSet("data-v-md-heading", slug);
|
|
49
|
+
return fallback(tokens, index, options, env, self);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function installSafeExternalLinks(parser) {
|
|
53
|
+
const fallback = parser.renderer.rules.link_open || ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options));
|
|
54
|
+
parser.renderer.rules.link_open = (tokens, index, options, env, self) => {
|
|
55
|
+
const token = tokens[index];
|
|
56
|
+
const href = token.attrGet("href") || "";
|
|
57
|
+
if (/^https?:\/\//i.test(href)) {
|
|
58
|
+
token.attrSet("target", "_blank");
|
|
59
|
+
token.attrSet("rel", "noopener noreferrer");
|
|
60
|
+
}
|
|
61
|
+
return fallback(tokens, index, options, env, self);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function createMarkdownRenderer(options = {}) {
|
|
65
|
+
var _a, _b, _c, _d;
|
|
66
|
+
const parser = new MarkdownIt({
|
|
67
|
+
html: (_a = options.html) != null ? _a : true,
|
|
68
|
+
breaks: (_b = options.breaks) != null ? _b : true,
|
|
69
|
+
linkify: (_c = options.linkify) != null ? _c : false,
|
|
70
|
+
typographer: (_d = options.typographer) != null ? _d : true,
|
|
71
|
+
highlight: (code, language) => highlightCode(code, language, options)
|
|
72
|
+
});
|
|
73
|
+
if (options.attrs !== false) {
|
|
74
|
+
parser.use(markdownItAttrs, {
|
|
75
|
+
leftDelimiter: "{{{",
|
|
76
|
+
rightDelimiter: "}}}",
|
|
77
|
+
allowedAttributes: [
|
|
78
|
+
"class",
|
|
79
|
+
"height",
|
|
80
|
+
"id",
|
|
81
|
+
"title",
|
|
82
|
+
"width",
|
|
83
|
+
...options.allowedAttributes || []
|
|
84
|
+
]
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
installHeadingAnchors(parser);
|
|
88
|
+
installSafeExternalLinks(parser);
|
|
89
|
+
return parser;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/core/sanitize.js
|
|
93
|
+
import createDOMPurify from "dompurify";
|
|
94
|
+
var BASE_SANITIZE_OPTIONS = Object.freeze({
|
|
95
|
+
USE_PROFILES: {
|
|
96
|
+
html: true
|
|
97
|
+
},
|
|
98
|
+
ADD_ATTR: [
|
|
99
|
+
"data-mention-id",
|
|
100
|
+
"data-v-md-anchor",
|
|
101
|
+
"data-v-md-heading",
|
|
102
|
+
"data-v-md-line",
|
|
103
|
+
"rel",
|
|
104
|
+
"target"
|
|
105
|
+
],
|
|
106
|
+
FORBID_TAGS: ["script"]
|
|
107
|
+
});
|
|
108
|
+
var sharedOptions = {};
|
|
109
|
+
function mergeOptions(base, extra) {
|
|
110
|
+
const merged = {
|
|
111
|
+
...base,
|
|
112
|
+
...extra
|
|
113
|
+
};
|
|
114
|
+
for (const key of ["ADD_ATTR", "ADD_TAGS", "FORBID_ATTR", "FORBID_TAGS"]) {
|
|
115
|
+
if (base[key] || extra[key]) {
|
|
116
|
+
merged[key] = [.../* @__PURE__ */ new Set([...base[key] || [], ...extra[key] || []])];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (base.USE_PROFILES || extra.USE_PROFILES) {
|
|
120
|
+
merged.USE_PROFILES = {
|
|
121
|
+
...base.USE_PROFILES || {},
|
|
122
|
+
...extra.USE_PROFILES || {}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return merged;
|
|
126
|
+
}
|
|
127
|
+
function resolvePurifier(windowLike) {
|
|
128
|
+
if (typeof createDOMPurify.sanitize === "function") {
|
|
129
|
+
return createDOMPurify;
|
|
130
|
+
}
|
|
131
|
+
if (windowLike && typeof createDOMPurify === "function") {
|
|
132
|
+
return createDOMPurify(windowLike);
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
function escapeHtml2(value) {
|
|
137
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
138
|
+
}
|
|
139
|
+
function sanitizeHtml(dirtyHtml, options = {}, windowLike = typeof window === "undefined" ? void 0 : window) {
|
|
140
|
+
const purifier = resolvePurifier(windowLike);
|
|
141
|
+
if (!purifier || typeof purifier.sanitize !== "function") {
|
|
142
|
+
return escapeHtml2(dirtyHtml || "");
|
|
143
|
+
}
|
|
144
|
+
return purifier.sanitize(
|
|
145
|
+
dirtyHtml || "",
|
|
146
|
+
mergeOptions(mergeOptions(BASE_SANITIZE_OPTIONS, sharedOptions), options)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
var sanitizer = {
|
|
150
|
+
process(dirtyHtml, options) {
|
|
151
|
+
return sanitizeHtml(dirtyHtml, options);
|
|
152
|
+
},
|
|
153
|
+
extend(options = {}) {
|
|
154
|
+
sharedOptions = mergeOptions(sharedOptions, options);
|
|
155
|
+
return this;
|
|
156
|
+
},
|
|
157
|
+
reset() {
|
|
158
|
+
sharedOptions = {};
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/version.js
|
|
164
|
+
var version = "0.1.0";
|
|
165
|
+
|
|
166
|
+
// src/preview.js
|
|
167
|
+
var defaultThemeConfig = {
|
|
168
|
+
name: "base",
|
|
169
|
+
previewClass: "vmk-markdown-body",
|
|
170
|
+
markdownParser: createMarkdownRenderer(),
|
|
171
|
+
extend(callback) {
|
|
172
|
+
callback(this.markdownParser);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var markdownExtenders = [];
|
|
176
|
+
var activeThemeConfig = defaultThemeConfig;
|
|
177
|
+
function installTheme(theme, options) {
|
|
178
|
+
if (!theme) return;
|
|
179
|
+
if (typeof theme === "function") {
|
|
180
|
+
theme(VMdPreview, options);
|
|
181
|
+
} else if (typeof theme.install === "function") {
|
|
182
|
+
theme.install(VMdPreview, options);
|
|
183
|
+
} else if (theme.markdownParser) {
|
|
184
|
+
VMdPreview.theme(theme);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
var VMdPreview = defineComponent({
|
|
188
|
+
name: "v-md-preview",
|
|
189
|
+
props: {
|
|
190
|
+
text: {
|
|
191
|
+
type: String,
|
|
192
|
+
default: ""
|
|
193
|
+
},
|
|
194
|
+
theme: {
|
|
195
|
+
type: Object,
|
|
196
|
+
default: void 0
|
|
197
|
+
},
|
|
198
|
+
tabSize: {
|
|
199
|
+
type: Number,
|
|
200
|
+
default: 2
|
|
201
|
+
},
|
|
202
|
+
scrollContainer: {
|
|
203
|
+
type: Function,
|
|
204
|
+
default: () => window
|
|
205
|
+
},
|
|
206
|
+
top: {
|
|
207
|
+
type: Number,
|
|
208
|
+
default: 0
|
|
209
|
+
},
|
|
210
|
+
sanitizeOptions: {
|
|
211
|
+
type: Object,
|
|
212
|
+
default: () => ({})
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
emits: {
|
|
216
|
+
change: (_text, _html) => true,
|
|
217
|
+
"image-click": (_images, _index) => true
|
|
218
|
+
},
|
|
219
|
+
setup(props, { emit }) {
|
|
220
|
+
const rootElement = shallowRef(null);
|
|
221
|
+
const html = shallowRef("");
|
|
222
|
+
if (props.theme) {
|
|
223
|
+
installTheme(props.theme);
|
|
224
|
+
}
|
|
225
|
+
for (const extender of markdownExtenders) {
|
|
226
|
+
extender(activeThemeConfig.markdownParser);
|
|
227
|
+
}
|
|
228
|
+
const renderMarkdown = () => {
|
|
229
|
+
const rawHtml = activeThemeConfig.markdownParser.render(props.text || "");
|
|
230
|
+
html.value = sanitizer.process(rawHtml, props.sanitizeOptions);
|
|
231
|
+
emit("change", props.text, html.value);
|
|
232
|
+
};
|
|
233
|
+
watch([() => props.text, () => props.sanitizeOptions], renderMarkdown, {
|
|
234
|
+
deep: true,
|
|
235
|
+
immediate: true
|
|
236
|
+
});
|
|
237
|
+
const handlePreviewClick = (event) => {
|
|
238
|
+
const target = event.target;
|
|
239
|
+
const root = rootElement.value;
|
|
240
|
+
if (!root || !target || target.tagName !== "IMG") {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const imageElements = Array.from(root.querySelectorAll("img"));
|
|
244
|
+
const images = imageElements.map((image) => image.getAttribute("src")).filter(Boolean);
|
|
245
|
+
const index = imageElements.indexOf(target);
|
|
246
|
+
emit("image-click", images, index);
|
|
247
|
+
};
|
|
248
|
+
return () => h(
|
|
249
|
+
"div",
|
|
250
|
+
{
|
|
251
|
+
ref: rootElement,
|
|
252
|
+
class: "vue-markdown-kit-preview",
|
|
253
|
+
style: {
|
|
254
|
+
tabSize: props.tabSize,
|
|
255
|
+
MozTabSize: props.tabSize
|
|
256
|
+
},
|
|
257
|
+
onClick: handlePreviewClick
|
|
258
|
+
},
|
|
259
|
+
[
|
|
260
|
+
h("div", {
|
|
261
|
+
class: activeThemeConfig.previewClass,
|
|
262
|
+
innerHTML: html.value
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
VMdPreview.version = version;
|
|
269
|
+
VMdPreview.install = (app) => {
|
|
270
|
+
app.component(VMdPreview.name, VMdPreview);
|
|
271
|
+
};
|
|
272
|
+
VMdPreview.theme = (themeConfig) => {
|
|
273
|
+
activeThemeConfig = themeConfig || defaultThemeConfig;
|
|
274
|
+
return VMdPreview;
|
|
275
|
+
};
|
|
276
|
+
VMdPreview.use = (theme, options) => {
|
|
277
|
+
installTheme(theme, options);
|
|
278
|
+
return VMdPreview;
|
|
279
|
+
};
|
|
280
|
+
VMdPreview.extendMarkdown = (extender) => {
|
|
281
|
+
markdownExtenders.push(extender);
|
|
282
|
+
return VMdPreview;
|
|
283
|
+
};
|
|
284
|
+
VMdPreview.xss = sanitizer;
|
|
285
|
+
VMdPreview.lang = {
|
|
286
|
+
use() {
|
|
287
|
+
},
|
|
288
|
+
add() {
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
var preview_default = VMdPreview;
|
|
292
|
+
export {
|
|
293
|
+
preview_default as default
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=preview.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/preview.js", "../src/core/renderer.js", "../src/core/sanitize.js", "../src/version.js"],
|
|
4
|
+
"sourcesContent": ["import { defineComponent, h, shallowRef, watch } from 'vue'\nimport { createMarkdownRenderer } from './core/renderer.js'\nimport { sanitizer } from './core/sanitize.js'\nimport { version } from './version.js'\n\nconst defaultThemeConfig = {\n name: 'base',\n previewClass: 'vmk-markdown-body',\n markdownParser: createMarkdownRenderer(),\n extend(callback) {\n callback(this.markdownParser)\n },\n}\n\nconst markdownExtenders = []\nlet activeThemeConfig = defaultThemeConfig\n\nfunction installTheme(theme, options) {\n if (!theme) return\n\n if (typeof theme === 'function') {\n theme(VMdPreview, options)\n } else if (typeof theme.install === 'function') {\n theme.install(VMdPreview, options)\n } else if (theme.markdownParser) {\n VMdPreview.theme(theme)\n }\n}\n\nconst VMdPreview = defineComponent({\n name: 'v-md-preview',\n\n props: {\n text: {\n type: String,\n default: '',\n },\n theme: {\n type: Object,\n default: undefined,\n },\n tabSize: {\n type: Number,\n default: 2,\n },\n scrollContainer: {\n type: Function,\n default: () => window,\n },\n top: {\n type: Number,\n default: 0,\n },\n sanitizeOptions: {\n type: Object,\n default: () => ({}),\n },\n },\n\n emits: {\n change: (_text, _html) => true,\n 'image-click': (_images, _index) => true,\n },\n\n setup(props, { emit }) {\n const rootElement = shallowRef(null)\n const html = shallowRef('')\n\n if (props.theme) {\n installTheme(props.theme)\n }\n\n for (const extender of markdownExtenders) {\n extender(activeThemeConfig.markdownParser)\n }\n\n const renderMarkdown = () => {\n const rawHtml = activeThemeConfig.markdownParser.render(props.text || '')\n html.value = sanitizer.process(rawHtml, props.sanitizeOptions)\n emit('change', props.text, html.value)\n }\n\n watch([() => props.text, () => props.sanitizeOptions], renderMarkdown, {\n deep: true,\n immediate: true,\n })\n\n const handlePreviewClick = (event) => {\n const target = event.target\n const root = rootElement.value\n\n if (!root || !target || target.tagName !== 'IMG') {\n return\n }\n\n const imageElements = Array.from(root.querySelectorAll('img'))\n const images = imageElements\n .map((image) => image.getAttribute('src'))\n .filter(Boolean)\n const index = imageElements.indexOf(target)\n\n emit('image-click', images, index)\n }\n\n return () =>\n h(\n 'div',\n {\n ref: rootElement,\n class: 'vue-markdown-kit-preview',\n style: {\n tabSize: props.tabSize,\n MozTabSize: props.tabSize,\n },\n onClick: handlePreviewClick,\n },\n [\n h('div', {\n class: activeThemeConfig.previewClass,\n innerHTML: html.value,\n }),\n ],\n )\n },\n})\n\nVMdPreview.version = version\nVMdPreview.install = (app) => {\n app.component(VMdPreview.name, VMdPreview)\n}\nVMdPreview.theme = (themeConfig) => {\n activeThemeConfig = themeConfig || defaultThemeConfig\n return VMdPreview\n}\nVMdPreview.use = (theme, options) => {\n installTheme(theme, options)\n return VMdPreview\n}\nVMdPreview.extendMarkdown = (extender) => {\n markdownExtenders.push(extender)\n return VMdPreview\n}\nVMdPreview.xss = sanitizer\nVMdPreview.lang = {\n use() {},\n add() {},\n}\n\nexport default VMdPreview\n", "import MarkdownIt from 'markdown-it'\nimport markdownItAttrs from 'markdown-it-attrs'\n\nfunction escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n}\n\nexport function slugifyHeading(value) {\n const slug = String(value || '')\n .normalize('NFKC')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^\\p{Letter}\\p{Number}_-]+/gu, '')\n .replace(/-{2,}/g, '-')\n .replace(/^-|-$/g, '')\n\n return slug || 'section'\n}\n\nfunction highlightCode(code, language, options) {\n const {\n Hljs,\n codeHighlightExtensionMap = {},\n codeBlockClass = (lang) => `v-md-hljs-${lang || ''}`,\n } = options\n\n const normalizedLanguage = codeHighlightExtensionMap[language] || language\n let highlighted = escapeHtml(code)\n\n if (\n Hljs &&\n normalizedLanguage &&\n typeof Hljs.getLanguage === 'function' &&\n Hljs.getLanguage(normalizedLanguage)\n ) {\n try {\n highlighted = Hljs.highlight(code, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n }).value\n } catch {\n // highlight.js 10 compatibility.\n highlighted = Hljs.highlight(normalizedLanguage, code, true).value\n }\n }\n\n return `<pre class=\"${escapeHtml(codeBlockClass(normalizedLanguage))}\"><code>${highlighted}</code></pre>`\n}\n\nfunction installHeadingAnchors(parser) {\n parser.core.ruler.before('block', 'vue_markdown_kit_heading_state', (state) => {\n state.env.__vueMarkdownKitHeadingSlugs = new Map()\n })\n\n const fallback =\n parser.renderer.rules.heading_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.heading_open = (tokens, index, options, env, self) => {\n const inline = tokens[index + 1]\n const baseSlug = slugifyHeading(inline && inline.content)\n const slugs = env.__vueMarkdownKitHeadingSlugs || new Map()\n const count = slugs.get(baseSlug) || 0\n const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`\n\n slugs.set(baseSlug, count + 1)\n env.__vueMarkdownKitHeadingSlugs = slugs\n\n tokens[index].attrSet('id', slug)\n tokens[index].attrSet('data-v-md-heading', slug)\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nfunction installSafeExternalLinks(parser) {\n const fallback =\n parser.renderer.rules.link_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.link_open = (tokens, index, options, env, self) => {\n const token = tokens[index]\n const href = token.attrGet('href') || ''\n\n if (/^https?:\\/\\//i.test(href)) {\n token.attrSet('target', '_blank')\n token.attrSet('rel', 'noopener noreferrer')\n }\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nexport function createMarkdownRenderer(options = {}) {\n const parser = new MarkdownIt({\n html: options.html ?? true,\n breaks: options.breaks ?? true,\n linkify: options.linkify ?? false,\n typographer: options.typographer ?? true,\n highlight: (code, language) => highlightCode(code, language, options),\n })\n\n if (options.attrs !== false) {\n parser.use(markdownItAttrs, {\n leftDelimiter: '{{{',\n rightDelimiter: '}}}',\n allowedAttributes: [\n 'class',\n 'height',\n 'id',\n 'title',\n 'width',\n ...(options.allowedAttributes || []),\n ],\n })\n }\n\n installHeadingAnchors(parser)\n installSafeExternalLinks(parser)\n\n return parser\n}\n", "import createDOMPurify from 'dompurify'\n\nconst BASE_SANITIZE_OPTIONS = Object.freeze({\n USE_PROFILES: {\n html: true,\n },\n ADD_ATTR: [\n 'data-mention-id',\n 'data-v-md-anchor',\n 'data-v-md-heading',\n 'data-v-md-line',\n 'rel',\n 'target',\n ],\n FORBID_TAGS: ['script'],\n})\n\nlet sharedOptions = {}\n\nfunction mergeOptions(base, extra) {\n const merged = {\n ...base,\n ...extra,\n }\n\n for (const key of ['ADD_ATTR', 'ADD_TAGS', 'FORBID_ATTR', 'FORBID_TAGS']) {\n if (base[key] || extra[key]) {\n merged[key] = [...new Set([...(base[key] || []), ...(extra[key] || [])])]\n }\n }\n\n if (base.USE_PROFILES || extra.USE_PROFILES) {\n merged.USE_PROFILES = {\n ...(base.USE_PROFILES || {}),\n ...(extra.USE_PROFILES || {}),\n }\n }\n\n return merged\n}\n\nfunction resolvePurifier(windowLike) {\n if (typeof createDOMPurify.sanitize === 'function') {\n return createDOMPurify\n }\n\n if (windowLike && typeof createDOMPurify === 'function') {\n return createDOMPurify(windowLike)\n }\n\n return null\n}\n\nfunction escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\nexport function sanitizeHtml(\n dirtyHtml,\n options = {},\n windowLike = typeof window === 'undefined' ? undefined : window,\n) {\n const purifier = resolvePurifier(windowLike)\n\n // Fail closed in non-DOM environments rather than returning executable HTML.\n if (!purifier || typeof purifier.sanitize !== 'function') {\n return escapeHtml(dirtyHtml || '')\n }\n\n return purifier.sanitize(\n dirtyHtml || '',\n mergeOptions(mergeOptions(BASE_SANITIZE_OPTIONS, sharedOptions), options),\n )\n}\n\nexport const sanitizer = {\n process(dirtyHtml, options) {\n return sanitizeHtml(dirtyHtml, options)\n },\n\n extend(options = {}) {\n sharedOptions = mergeOptions(sharedOptions, options)\n return this\n },\n\n reset() {\n sharedOptions = {}\n return this\n },\n}\n", "export const version = '0.1.0'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["escapeHtml"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.vue-markdown-kit-preview {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
width: 100%;
|
|
4
|
+
overflow-wrap: break-word;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.vue-markdown-kit-preview *,
|
|
8
|
+
.vue-markdown-kit-preview *::before,
|
|
9
|
+
.vue-markdown-kit-preview *::after {
|
|
10
|
+
box-sizing: inherit;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.vue-markdown-kit-preview img {
|
|
14
|
+
max-width: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.vue-markdown-kit-preview pre {
|
|
18
|
+
overflow: auto;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.vue-markdown-kit-preview .vmk-markdown-body {
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/theme/github.js
|
|
30
|
+
var github_exports = {};
|
|
31
|
+
__export(github_exports, {
|
|
32
|
+
createGithubTheme: () => createGithubTheme,
|
|
33
|
+
default: () => github_default
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(github_exports);
|
|
36
|
+
|
|
37
|
+
// src/core/renderer.js
|
|
38
|
+
var import_markdown_it = __toESM(require("markdown-it"), 1);
|
|
39
|
+
var import_markdown_it_attrs = __toESM(require("markdown-it-attrs"), 1);
|
|
40
|
+
function escapeHtml(value) {
|
|
41
|
+
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
42
|
+
}
|
|
43
|
+
function slugifyHeading(value) {
|
|
44
|
+
const slug = String(value || "").normalize("NFKC").trim().toLowerCase().replace(/\s+/g, "-").replace(/[^\p{Letter}\p{Number}_-]+/gu, "").replace(/-{2,}/g, "-").replace(/^-|-$/g, "");
|
|
45
|
+
return slug || "section";
|
|
46
|
+
}
|
|
47
|
+
function highlightCode(code, language, options) {
|
|
48
|
+
const {
|
|
49
|
+
Hljs,
|
|
50
|
+
codeHighlightExtensionMap = {},
|
|
51
|
+
codeBlockClass = (lang) => `v-md-hljs-${lang || ""}`
|
|
52
|
+
} = options;
|
|
53
|
+
const normalizedLanguage = codeHighlightExtensionMap[language] || language;
|
|
54
|
+
let highlighted = escapeHtml(code);
|
|
55
|
+
if (Hljs && normalizedLanguage && typeof Hljs.getLanguage === "function" && Hljs.getLanguage(normalizedLanguage)) {
|
|
56
|
+
try {
|
|
57
|
+
highlighted = Hljs.highlight(code, {
|
|
58
|
+
language: normalizedLanguage,
|
|
59
|
+
ignoreIllegals: true
|
|
60
|
+
}).value;
|
|
61
|
+
} catch {
|
|
62
|
+
highlighted = Hljs.highlight(normalizedLanguage, code, true).value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return `<pre class="${escapeHtml(codeBlockClass(normalizedLanguage))}"><code>${highlighted}</code></pre>`;
|
|
66
|
+
}
|
|
67
|
+
function installHeadingAnchors(parser) {
|
|
68
|
+
parser.core.ruler.before("block", "vue_markdown_kit_heading_state", (state) => {
|
|
69
|
+
state.env.__vueMarkdownKitHeadingSlugs = /* @__PURE__ */ new Map();
|
|
70
|
+
});
|
|
71
|
+
const fallback = parser.renderer.rules.heading_open || ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options));
|
|
72
|
+
parser.renderer.rules.heading_open = (tokens, index, options, env, self) => {
|
|
73
|
+
const inline = tokens[index + 1];
|
|
74
|
+
const baseSlug = slugifyHeading(inline && inline.content);
|
|
75
|
+
const slugs = env.__vueMarkdownKitHeadingSlugs || /* @__PURE__ */ new Map();
|
|
76
|
+
const count = slugs.get(baseSlug) || 0;
|
|
77
|
+
const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`;
|
|
78
|
+
slugs.set(baseSlug, count + 1);
|
|
79
|
+
env.__vueMarkdownKitHeadingSlugs = slugs;
|
|
80
|
+
tokens[index].attrSet("id", slug);
|
|
81
|
+
tokens[index].attrSet("data-v-md-heading", slug);
|
|
82
|
+
return fallback(tokens, index, options, env, self);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function installSafeExternalLinks(parser) {
|
|
86
|
+
const fallback = parser.renderer.rules.link_open || ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options));
|
|
87
|
+
parser.renderer.rules.link_open = (tokens, index, options, env, self) => {
|
|
88
|
+
const token = tokens[index];
|
|
89
|
+
const href = token.attrGet("href") || "";
|
|
90
|
+
if (/^https?:\/\//i.test(href)) {
|
|
91
|
+
token.attrSet("target", "_blank");
|
|
92
|
+
token.attrSet("rel", "noopener noreferrer");
|
|
93
|
+
}
|
|
94
|
+
return fallback(tokens, index, options, env, self);
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function createMarkdownRenderer(options = {}) {
|
|
98
|
+
var _a, _b, _c, _d;
|
|
99
|
+
const parser = new import_markdown_it.default({
|
|
100
|
+
html: (_a = options.html) != null ? _a : true,
|
|
101
|
+
breaks: (_b = options.breaks) != null ? _b : true,
|
|
102
|
+
linkify: (_c = options.linkify) != null ? _c : false,
|
|
103
|
+
typographer: (_d = options.typographer) != null ? _d : true,
|
|
104
|
+
highlight: (code, language) => highlightCode(code, language, options)
|
|
105
|
+
});
|
|
106
|
+
if (options.attrs !== false) {
|
|
107
|
+
parser.use(import_markdown_it_attrs.default, {
|
|
108
|
+
leftDelimiter: "{{{",
|
|
109
|
+
rightDelimiter: "}}}",
|
|
110
|
+
allowedAttributes: [
|
|
111
|
+
"class",
|
|
112
|
+
"height",
|
|
113
|
+
"id",
|
|
114
|
+
"title",
|
|
115
|
+
"width",
|
|
116
|
+
...options.allowedAttributes || []
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
installHeadingAnchors(parser);
|
|
121
|
+
installSafeExternalLinks(parser);
|
|
122
|
+
return parser;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/theme/github.js
|
|
126
|
+
function createGithubTheme(options = {}) {
|
|
127
|
+
const markdownParser = createMarkdownRenderer(options);
|
|
128
|
+
return {
|
|
129
|
+
name: "github",
|
|
130
|
+
previewClass: "github-markdown-body",
|
|
131
|
+
markdownParser,
|
|
132
|
+
extend(callback) {
|
|
133
|
+
callback(markdownParser, options.Hljs);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
var githubTheme = {
|
|
138
|
+
install(VMdPreview, options = {}) {
|
|
139
|
+
VMdPreview.theme(createGithubTheme(options));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var github_default = githubTheme;
|
|
143
|
+
//# sourceMappingURL=github.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/theme/github.js", "../../src/core/renderer.js"],
|
|
4
|
+
"sourcesContent": ["import { createMarkdownRenderer } from '../core/renderer.js'\n\nexport function createGithubTheme(options = {}) {\n const markdownParser = createMarkdownRenderer(options)\n\n return {\n name: 'github',\n previewClass: 'github-markdown-body',\n markdownParser,\n extend(callback) {\n callback(markdownParser, options.Hljs)\n },\n }\n}\n\nconst githubTheme = {\n install(VMdPreview, options = {}) {\n VMdPreview.theme(createGithubTheme(options))\n },\n}\n\nexport default githubTheme\n", "import MarkdownIt from 'markdown-it'\nimport markdownItAttrs from 'markdown-it-attrs'\n\nfunction escapeHtml(value) {\n return String(value)\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n}\n\nexport function slugifyHeading(value) {\n const slug = String(value || '')\n .normalize('NFKC')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^\\p{Letter}\\p{Number}_-]+/gu, '')\n .replace(/-{2,}/g, '-')\n .replace(/^-|-$/g, '')\n\n return slug || 'section'\n}\n\nfunction highlightCode(code, language, options) {\n const {\n Hljs,\n codeHighlightExtensionMap = {},\n codeBlockClass = (lang) => `v-md-hljs-${lang || ''}`,\n } = options\n\n const normalizedLanguage = codeHighlightExtensionMap[language] || language\n let highlighted = escapeHtml(code)\n\n if (\n Hljs &&\n normalizedLanguage &&\n typeof Hljs.getLanguage === 'function' &&\n Hljs.getLanguage(normalizedLanguage)\n ) {\n try {\n highlighted = Hljs.highlight(code, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n }).value\n } catch {\n // highlight.js 10 compatibility.\n highlighted = Hljs.highlight(normalizedLanguage, code, true).value\n }\n }\n\n return `<pre class=\"${escapeHtml(codeBlockClass(normalizedLanguage))}\"><code>${highlighted}</code></pre>`\n}\n\nfunction installHeadingAnchors(parser) {\n parser.core.ruler.before('block', 'vue_markdown_kit_heading_state', (state) => {\n state.env.__vueMarkdownKitHeadingSlugs = new Map()\n })\n\n const fallback =\n parser.renderer.rules.heading_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.heading_open = (tokens, index, options, env, self) => {\n const inline = tokens[index + 1]\n const baseSlug = slugifyHeading(inline && inline.content)\n const slugs = env.__vueMarkdownKitHeadingSlugs || new Map()\n const count = slugs.get(baseSlug) || 0\n const slug = count === 0 ? baseSlug : `${baseSlug}-${count}`\n\n slugs.set(baseSlug, count + 1)\n env.__vueMarkdownKitHeadingSlugs = slugs\n\n tokens[index].attrSet('id', slug)\n tokens[index].attrSet('data-v-md-heading', slug)\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nfunction installSafeExternalLinks(parser) {\n const fallback =\n parser.renderer.rules.link_open ||\n ((tokens, index, options, _env, self) => self.renderToken(tokens, index, options))\n\n parser.renderer.rules.link_open = (tokens, index, options, env, self) => {\n const token = tokens[index]\n const href = token.attrGet('href') || ''\n\n if (/^https?:\\/\\//i.test(href)) {\n token.attrSet('target', '_blank')\n token.attrSet('rel', 'noopener noreferrer')\n }\n\n return fallback(tokens, index, options, env, self)\n }\n}\n\nexport function createMarkdownRenderer(options = {}) {\n const parser = new MarkdownIt({\n html: options.html ?? true,\n breaks: options.breaks ?? true,\n linkify: options.linkify ?? false,\n typographer: options.typographer ?? true,\n highlight: (code, language) => highlightCode(code, language, options),\n })\n\n if (options.attrs !== false) {\n parser.use(markdownItAttrs, {\n leftDelimiter: '{{{',\n rightDelimiter: '}}}',\n allowedAttributes: [\n 'class',\n 'height',\n 'id',\n 'title',\n 'width',\n ...(options.allowedAttributes || []),\n ],\n })\n }\n\n installHeadingAnchors(parser)\n installSafeExternalLinks(parser)\n\n return parser\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["MarkdownIt", "markdownItAttrs"]
|
|
7
|
+
}
|