markopress 0.0.2 → 0.0.4
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/dist/build/index.d.ts +0 -1
- package/dist/build/index.js +1 -1627
- package/dist/build/types.d.ts +0 -1
- package/dist/build/types.js +1 -5
- package/dist/build/vite-markdown-plugin.d.ts +0 -1
- package/dist/build/vite-markdown-plugin.js +1 -147
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +1 -74
- package/dist/config/app-root.d.ts +0 -1
- package/dist/config/app-root.js +1 -24
- package/dist/config/index.d.ts +0 -1
- package/dist/config/index.js +1 -6
- package/dist/config/loader.d.ts +0 -1
- package/dist/config/loader.js +1 -188
- package/dist/config/types.d.ts +0 -1
- package/dist/config/types.js +1 -5
- package/dist/config/validation.d.ts +0 -1
- package/dist/config/validation.js +1 -139
- package/dist/content/index.d.ts +0 -1
- package/dist/content/index.js +1 -6
- package/dist/content/registry.d.ts +0 -1
- package/dist/content/registry.js +1 -45
- package/dist/content/types.d.ts +0 -1
- package/dist/content/types.js +1 -5
- package/dist/dev/index.d.ts +0 -1
- package/dist/dev/index.js +1 -93
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -17
- package/dist/markdown/base-path-plugin.d.ts +16 -0
- package/dist/markdown/base-path-plugin.js +1 -0
- package/dist/markdown/code.d.ts +0 -1
- package/dist/markdown/code.js +1 -305
- package/dist/markdown/containers.d.ts +0 -1
- package/dist/markdown/containers.js +1 -143
- package/dist/markdown/includes.d.ts +0 -1
- package/dist/markdown/includes.js +1 -9
- package/dist/markdown/index.d.ts +0 -1
- package/dist/markdown/index.js +1 -8
- package/dist/markdown/loader.d.ts +0 -1
- package/dist/markdown/loader.js +1 -325
- package/dist/markdown/md-link-plugin.d.ts +14 -0
- package/dist/markdown/md-link-plugin.js +1 -0
- package/dist/markdown/preserve-tags.d.ts +0 -1
- package/dist/markdown/preserve-tags.js +1 -233
- package/dist/markdown/renderer.d.ts +0 -1
- package/dist/markdown/renderer.js +1 -146
- package/dist/markdown/tag-validator.d.ts +0 -1
- package/dist/markdown/tag-validator.js +1 -118
- package/dist/markdown/types.d.ts +2 -1
- package/dist/markdown/types.js +1 -5
- package/dist/plugin/compat.d.ts +0 -1
- package/dist/plugin/compat.js +1 -78
- package/dist/plugin/context.d.ts +0 -1
- package/dist/plugin/context.js +1 -103
- package/dist/plugin/index.d.ts +0 -1
- package/dist/plugin/index.js +1 -6
- package/dist/plugin/manager.d.ts +0 -1
- package/dist/plugin/manager.js +1 -385
- package/dist/plugin/types.d.ts +1 -1
- package/dist/plugin/types.js +1 -5
- package/dist/plugins/blog-index/index.d.ts +0 -1
- package/dist/plugins/blog-index/index.js +1 -158
- package/dist/plugins/sidenav/index.d.ts +0 -1
- package/dist/plugins/sidenav/index.js +1 -86
- package/dist/plugins/toc/index.d.ts +0 -1
- package/dist/plugins/toc/index.js +1 -79
- package/dist/preview/index.d.ts +0 -1
- package/dist/preview/index.js +1 -25
- package/dist/theme/default/design-systems/default.d.ts +0 -1
- package/dist/theme/default/design-systems/default.js +1 -289
- package/dist/theme/default/design-systems/docusaurus.d.ts +0 -1
- package/dist/theme/default/design-systems/docusaurus.js +1 -299
- package/dist/theme/default/design-systems/index.d.ts +0 -1
- package/dist/theme/default/design-systems/index.js +1 -54
- package/dist/theme/default/design-systems/rspress.d.ts +0 -1
- package/dist/theme/default/design-systems/rspress.js +1 -299
- package/dist/theme/default/design-systems/types.d.ts +0 -1
- package/dist/theme/default/design-systems/types.js +1 -6
- package/dist/theme/default/design-systems/vitepress.d.ts +0 -1
- package/dist/theme/default/design-systems/vitepress.js +1 -299
- package/dist/theme/default/index.d.ts +0 -1
- package/dist/theme/default/index.js +1 -44
- package/dist/theme/default/theme.d.ts +0 -1
- package/dist/theme/default/theme.js +1 -58
- package/dist/theme/index.d.ts +0 -1
- package/dist/theme/index.js +1 -6
- package/dist/theme/loader.d.ts +0 -1
- package/dist/theme/loader.js +1 -125
- package/dist/theme/types.d.ts +1 -1
- package/dist/theme/types.js +1 -5
- package/dist/vite/index.d.ts +0 -1
- package/dist/vite/index.js +1 -6
- package/dist/vite/markdownPlugin.d.ts +0 -1
- package/dist/vite/markdownPlugin.js +1 -111
- package/dist/vite/plugin.d.ts +0 -1
- package/dist/vite/plugin.js +1 -94
- package/package.json +3 -2
- package/src/theme/default/layouts/blog.marko +1 -1
- package/src/theme/default/layouts/default.marko +5 -5
- package/src/theme/default/layouts/docs.marko +6 -6
- package/src/theme/default/layouts/page.marko +1 -1
- package/templates/catch-all-handler.js.template +2 -17
- package/dist/build/index.d.ts.map +0 -1
- package/dist/build/index.js.map +0 -1
- package/dist/build/manifest-generator.d.ts +0 -34
- package/dist/build/manifest-generator.d.ts.map +0 -1
- package/dist/build/manifest-generator.js +0 -86
- package/dist/build/manifest-generator.js.map +0 -1
- package/dist/build/security.test.d.ts +0 -6
- package/dist/build/security.test.d.ts.map +0 -1
- package/dist/build/security.test.js +0 -88
- package/dist/build/security.test.js.map +0 -1
- package/dist/build/types.d.ts.map +0 -1
- package/dist/build/types.js.map +0 -1
- package/dist/build/vite-config.test.d.ts +0 -2
- package/dist/build/vite-config.test.d.ts.map +0 -1
- package/dist/build/vite-config.test.js +0 -53
- package/dist/build/vite-config.test.js.map +0 -1
- package/dist/build/vite-markdown-plugin.d.ts.map +0 -1
- package/dist/build/vite-markdown-plugin.js.map +0 -1
- package/dist/build/vite-markdown-plugin.test.d.ts +0 -2
- package/dist/build/vite-markdown-plugin.test.d.ts.map +0 -1
- package/dist/build/vite-markdown-plugin.test.js +0 -41
- package/dist/build/vite-markdown-plugin.test.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/config/app-root.d.ts.map +0 -1
- package/dist/config/app-root.js.map +0 -1
- package/dist/config/app-root.test.d.ts +0 -2
- package/dist/config/app-root.test.d.ts.map +0 -1
- package/dist/config/app-root.test.js +0 -71
- package/dist/config/app-root.test.js.map +0 -1
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js.map +0 -1
- package/dist/config/loader.d.ts.map +0 -1
- package/dist/config/loader.js.map +0 -1
- package/dist/config/loader.test.d.ts +0 -2
- package/dist/config/loader.test.d.ts.map +0 -1
- package/dist/config/loader.test.js +0 -24
- package/dist/config/loader.test.js.map +0 -1
- package/dist/config/types.d.ts.map +0 -1
- package/dist/config/types.js.map +0 -1
- package/dist/config/validation.d.ts.map +0 -1
- package/dist/config/validation.js.map +0 -1
- package/dist/content/index.d.ts.map +0 -1
- package/dist/content/index.js.map +0 -1
- package/dist/content/registry.d.ts.map +0 -1
- package/dist/content/registry.js.map +0 -1
- package/dist/content/scanner.d.ts +0 -9
- package/dist/content/scanner.d.ts.map +0 -1
- package/dist/content/scanner.js +0 -115
- package/dist/content/scanner.js.map +0 -1
- package/dist/content/types.d.ts.map +0 -1
- package/dist/content/types.js.map +0 -1
- package/dist/dev/index.d.ts.map +0 -1
- package/dist/dev/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/markdown/code.d.ts.map +0 -1
- package/dist/markdown/code.js.map +0 -1
- package/dist/markdown/containers.d.ts.map +0 -1
- package/dist/markdown/containers.js.map +0 -1
- package/dist/markdown/includes.d.ts.map +0 -1
- package/dist/markdown/includes.js.map +0 -1
- package/dist/markdown/index.d.ts.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/markdown/loader.d.ts.map +0 -1
- package/dist/markdown/loader.js.map +0 -1
- package/dist/markdown/preserve-tags.d.ts.map +0 -1
- package/dist/markdown/preserve-tags.js.map +0 -1
- package/dist/markdown/renderer.d.ts.map +0 -1
- package/dist/markdown/renderer.js.map +0 -1
- package/dist/markdown/tag-validator.d.ts.map +0 -1
- package/dist/markdown/tag-validator.js.map +0 -1
- package/dist/markdown/types.d.ts.map +0 -1
- package/dist/markdown/types.js.map +0 -1
- package/dist/plugin/compat.d.ts.map +0 -1
- package/dist/plugin/compat.js.map +0 -1
- package/dist/plugin/context.d.ts.map +0 -1
- package/dist/plugin/context.js.map +0 -1
- package/dist/plugin/index.d.ts.map +0 -1
- package/dist/plugin/index.js.map +0 -1
- package/dist/plugin/manager.d.ts.map +0 -1
- package/dist/plugin/manager.js.map +0 -1
- package/dist/plugin/types.d.ts.map +0 -1
- package/dist/plugin/types.js.map +0 -1
- package/dist/plugins/blog-index/index.d.ts.map +0 -1
- package/dist/plugins/blog-index/index.js.map +0 -1
- package/dist/plugins/sidenav/index.d.ts.map +0 -1
- package/dist/plugins/sidenav/index.js.map +0 -1
- package/dist/plugins/toc/index.d.ts.map +0 -1
- package/dist/plugins/toc/index.js.map +0 -1
- package/dist/preview/index.d.ts.map +0 -1
- package/dist/preview/index.js.map +0 -1
- package/dist/theme/default/build/generate-all.d.ts +0 -9
- package/dist/theme/default/build/generate-all.d.ts.map +0 -1
- package/dist/theme/default/build/generate-all.js +0 -85
- package/dist/theme/default/build/generate-all.js.map +0 -1
- package/dist/theme/default/build/generate-css.d.ts +0 -19
- package/dist/theme/default/build/generate-css.d.ts.map +0 -1
- package/dist/theme/default/build/generate-css.js +0 -199
- package/dist/theme/default/build/generate-css.js.map +0 -1
- package/dist/theme/default/build/index.d.ts +0 -5
- package/dist/theme/default/build/index.d.ts.map +0 -1
- package/dist/theme/default/build/index.js +0 -5
- package/dist/theme/default/build/index.js.map +0 -1
- package/dist/theme/default/design-systems/default.d.ts.map +0 -1
- package/dist/theme/default/design-systems/default.js.map +0 -1
- package/dist/theme/default/design-systems/docusaurus.d.ts.map +0 -1
- package/dist/theme/default/design-systems/docusaurus.js.map +0 -1
- package/dist/theme/default/design-systems/index.d.ts.map +0 -1
- package/dist/theme/default/design-systems/index.js.map +0 -1
- package/dist/theme/default/design-systems/rspress.d.ts.map +0 -1
- package/dist/theme/default/design-systems/rspress.js.map +0 -1
- package/dist/theme/default/design-systems/types.d.ts.map +0 -1
- package/dist/theme/default/design-systems/types.js.map +0 -1
- package/dist/theme/default/design-systems/vitepress.d.ts.map +0 -1
- package/dist/theme/default/design-systems/vitepress.js.map +0 -1
- package/dist/theme/default/index.d.ts.map +0 -1
- package/dist/theme/default/index.js.map +0 -1
- package/dist/theme/default/theme.d.ts.map +0 -1
- package/dist/theme/default/theme.js.map +0 -1
- package/dist/theme/index.d.ts.map +0 -1
- package/dist/theme/index.js.map +0 -1
- package/dist/theme/loader.d.ts.map +0 -1
- package/dist/theme/loader.js.map +0 -1
- package/dist/theme/types.d.ts.map +0 -1
- package/dist/theme/types.js.map +0 -1
- package/dist/vite/index.d.ts.map +0 -1
- package/dist/vite/index.js.map +0 -1
- package/dist/vite/markdownPlugin.d.ts.map +0 -1
- package/dist/vite/markdownPlugin.js.map +0 -1
- package/dist/vite/plugin.d.ts.map +0 -1
- package/dist/vite/plugin.js.map +0 -1
- package/src/theme/default/build/generate-all.ts +0 -99
- package/src/theme/default/build/generate-css.ts +0 -234
- package/src/theme/default/build/index.ts +0 -5
- package/src/theme/default/components/doc-footer.marko +0 -180
- package/src/theme/default/components/footer.marko +0 -32
- package/src/theme/default/components/header.marko +0 -49
- package/src/theme/default/components/nav-bar.marko +0 -191
- package/src/theme/default/components/page-header.marko +0 -20
- package/src/theme/default/components/reading-progress.marko +0 -36
- package/src/theme/default/components/search.marko +0 -239
- package/src/theme/default/components/sidebar.marko +0 -211
- package/src/theme/default/components/site-footer.marko +0 -211
- package/src/theme/default/components/skip-link.marko +0 -49
- package/src/theme/default/components/theme/theme-aside-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-aside-top.marko +0 -1
- package/src/theme/default/components/theme/theme-body-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-body-top.marko +0 -1
- package/src/theme/default/components/theme/theme-doc-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-doc-footer-after.marko +0 -1
- package/src/theme/default/components/theme/theme-doc-footer-before.marko +0 -1
- package/src/theme/default/components/theme/theme-doc-top.marko +0 -1
- package/src/theme/default/components/theme/theme-head-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-head-top.marko +0 -1
- package/src/theme/default/components/theme/theme-home-features-after.marko +0 -1
- package/src/theme/default/components/theme/theme-home-hero-after.marko +0 -1
- package/src/theme/default/components/theme/theme-home-hero-before.marko +0 -1
- package/src/theme/default/components/theme/theme-navbar-center.marko +0 -5
- package/src/theme/default/components/theme/theme-navbar-end.marko +0 -30
- package/src/theme/default/components/theme/theme-navbar-start.marko +0 -1
- package/src/theme/default/components/theme/theme-page-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-page-top.marko +0 -1
- package/src/theme/default/components/theme/theme-sidebar-bottom.marko +0 -1
- package/src/theme/default/components/theme/theme-sidebar-top.marko +0 -1
- package/src/theme/default/components/theme/theme-toc-item.marko +0 -1
- package/src/theme/default/components/theme-toggle.marko +0 -122
- package/src/theme/default/components/toc.marko +0 -140
- package/src/theme/default/design-systems/default.ts +0 -331
- package/src/theme/default/design-systems/docusaurus.ts +0 -341
- package/src/theme/default/design-systems/index.ts +0 -67
- package/src/theme/default/design-systems/rspress.ts +0 -341
- package/src/theme/default/design-systems/types.ts +0 -296
- package/src/theme/default/design-systems/vitepress.ts +0 -341
- package/src/theme/default/index.ts +0 -107
- package/src/theme/default/theme.ts +0 -83
- package/templates/example-tags/README.md +0 -212
- package/templates/example-tags/alert-box.marko +0 -98
- package/templates/example-tags/button-primary.marko +0 -28
- package/templates/example-tags/button-secondary.marko +0 -28
- package/templates/example-tags/button.marko +0 -6
- package/templates/example-tags/card-body.marko +0 -8
- package/templates/example-tags/card-footer.marko +0 -7
- package/templates/example-tags/card-header.marko +0 -7
- package/templates/example-tags/card.marko +0 -20
- package/templates/example-tags/icon.marko +0 -149
|
@@ -1,233 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Markdown-it plugin to preserve Marko tags (kebab-case) during markdown processing
|
|
3
|
-
*
|
|
4
|
-
* This plugin detects Marko component tags and preserves them verbatim,
|
|
5
|
-
* allowing Marko's runtime to handle component discovery and rendering.
|
|
6
|
-
*
|
|
7
|
-
* - Preserves self-closing tags: <my-tag prop="value"/>
|
|
8
|
-
* - Preserves tags with content: <my-tag>content</my-tag>
|
|
9
|
-
* - Converts markdown→HTML inside tags that don't contain Marko syntax
|
|
10
|
-
* - Preserves Marko template content as-is (nested components, slots)
|
|
11
|
-
*/
|
|
12
|
-
// Standard HTML5 elements that should NOT be preserved
|
|
13
|
-
const HTML_ELEMENTS = new Set([
|
|
14
|
-
'div', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'blockquote', 'pre', 'figure', 'figcaption',
|
|
15
|
-
'span', 'a', 'strong', 'em', 'b', 'i', 'u', 's', 'sub', 'sup', 'code', 'small',
|
|
16
|
-
'ul', 'ol', 'li', 'dl', 'dt', 'dd',
|
|
17
|
-
'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'caption', 'col', 'colgroup',
|
|
18
|
-
'form', 'input', 'button', 'select', 'datalist', 'optgroup', 'option', 'textarea',
|
|
19
|
-
'label', 'fieldset', 'legend',
|
|
20
|
-
'img', 'video', 'audio', 'source', 'track', 'canvas', 'map', 'area',
|
|
21
|
-
'script', 'style', 'link', 'meta', 'noscript',
|
|
22
|
-
'html', 'head', 'body', 'title', 'base', 'section', 'article', 'aside', 'header', 'footer', 'nav', 'main', 'address',
|
|
23
|
-
'details', 'summary', 'dialog',
|
|
24
|
-
'iframe', 'object', 'param', 'embed',
|
|
25
|
-
]);
|
|
26
|
-
/**
|
|
27
|
-
* Create placeholder for a detected Marko component
|
|
28
|
-
*/
|
|
29
|
-
function createPlaceholder(id) {
|
|
30
|
-
return `<div data-marko-tag="${id}"></div>`;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Restore Marko components from placeholders
|
|
34
|
-
*/
|
|
35
|
-
function restoreComponents(html, components) {
|
|
36
|
-
let result = html;
|
|
37
|
-
// Restore in reverse order to preserve positions
|
|
38
|
-
for (let i = components.length - 1; i >= 0; i--) {
|
|
39
|
-
const comp = components[i];
|
|
40
|
-
const placeholder = createPlaceholder(comp.id);
|
|
41
|
-
result = result.replace(placeholder, comp.processedTag);
|
|
42
|
-
}
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Check if content contains Marko syntax (nested components or named slots)
|
|
47
|
-
*/
|
|
48
|
-
function hasMarkoSyntax(content) {
|
|
49
|
-
// Check for nested Marko components (kebab-case tags)
|
|
50
|
-
const nestedComponentRegex = /<[a-z][a-z0-9-]*(?:\s[^>]*?)?>/;
|
|
51
|
-
// Check for named slots (@slot-name)
|
|
52
|
-
const namedSlotRegex = /<@[\w-]+/;
|
|
53
|
-
return nestedComponentRegex.test(content) || namedSlotRegex.test(content);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Process component content - convert markdown to HTML if no Marko syntax present
|
|
57
|
-
*/
|
|
58
|
-
function processComponentContent(content, md) {
|
|
59
|
-
if (!content || !content.trim()) {
|
|
60
|
-
return '';
|
|
61
|
-
}
|
|
62
|
-
if (hasMarkoSyntax(content)) {
|
|
63
|
-
// Content is a Marko template - preserve as-is
|
|
64
|
-
return content;
|
|
65
|
-
}
|
|
66
|
-
// Content is plain markdown - convert to HTML
|
|
67
|
-
let html = md.render(content);
|
|
68
|
-
// Unwrap <p> tags if markdown-it wrapped the content
|
|
69
|
-
// (markdown-it wraps plain text in <p> tags)
|
|
70
|
-
const trimmed = html.trim();
|
|
71
|
-
if (trimmed.startsWith('<p>') && trimmed.endsWith('</p>')) {
|
|
72
|
-
const inner = trimmed.slice(3, -4);
|
|
73
|
-
// Check if there are no other block elements, then unwrap
|
|
74
|
-
if (!inner.includes('</div>') && !inner.includes('<pre>')) {
|
|
75
|
-
html = inner;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return html;
|
|
79
|
-
}
|
|
80
|
-
function parseOpeningTag(markdown, pos) {
|
|
81
|
-
const tagRegex = /<([a-z][a-z0-9-]*)(\s[^>]*?)?(\/)?>/g;
|
|
82
|
-
tagRegex.lastIndex = pos;
|
|
83
|
-
const match = tagRegex.exec(markdown);
|
|
84
|
-
if (!match) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
name: match[1],
|
|
89
|
-
attrs: match[2] || '',
|
|
90
|
-
selfClosing: match[3] === '/',
|
|
91
|
-
end: match.index + match[0].length
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Extract full Marko component with content
|
|
96
|
-
*/
|
|
97
|
-
function extractComponent(markdown, startPos, md, onTagDetected, getLineNumber) {
|
|
98
|
-
const openingTag = parseOpeningTag(markdown, startPos);
|
|
99
|
-
if (!openingTag) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const tagName = openingTag.name;
|
|
103
|
-
// Skip if it's a standard HTML element
|
|
104
|
-
if (HTML_ELEMENTS.has(tagName)) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
// Notify callback for validation
|
|
108
|
-
if (onTagDetected && getLineNumber) {
|
|
109
|
-
const lineNumber = getLineNumber(markdown, startPos);
|
|
110
|
-
onTagDetected(tagName, lineNumber);
|
|
111
|
-
}
|
|
112
|
-
// If self-closing, return immediately
|
|
113
|
-
if (openingTag.selfClosing) {
|
|
114
|
-
return {
|
|
115
|
-
id: 0,
|
|
116
|
-
start: startPos,
|
|
117
|
-
end: openingTag.end,
|
|
118
|
-
originalTag: markdown.slice(startPos, openingTag.end),
|
|
119
|
-
content: '',
|
|
120
|
-
processedTag: markdown.slice(startPos, openingTag.end)
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
// Find matching closing tag (handle nesting)
|
|
124
|
-
let pos = openingTag.end;
|
|
125
|
-
let depth = 1;
|
|
126
|
-
const closeTagStart = `</${tagName}`;
|
|
127
|
-
const closeTagFull = `</${tagName}>`;
|
|
128
|
-
while (pos < markdown.length && depth > 0) {
|
|
129
|
-
const nextOpen = markdown.indexOf(`<${tagName}`, pos);
|
|
130
|
-
const nextClose = markdown.indexOf(closeTagFull, pos);
|
|
131
|
-
if (nextClose === -1) {
|
|
132
|
-
// No closing tag found - treat what we have
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
if (nextOpen !== -1 && nextOpen < nextClose) {
|
|
136
|
-
// Found opening tag before closing
|
|
137
|
-
const potentialTag = parseOpeningTag(markdown, nextOpen);
|
|
138
|
-
if (potentialTag && potentialTag.name === tagName) {
|
|
139
|
-
depth++;
|
|
140
|
-
pos = potentialTag.end;
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Found closing tag
|
|
145
|
-
depth--;
|
|
146
|
-
if (depth === 0) {
|
|
147
|
-
const endPos = nextClose + closeTagFull.length;
|
|
148
|
-
const content = markdown.slice(openingTag.end, nextClose);
|
|
149
|
-
// Process content (convert markdown or preserve Marko)
|
|
150
|
-
const processedContent = processComponentContent(content, md);
|
|
151
|
-
return {
|
|
152
|
-
id: 0,
|
|
153
|
-
start: startPos,
|
|
154
|
-
end: endPos,
|
|
155
|
-
originalTag: markdown.slice(startPos, endPos),
|
|
156
|
-
content,
|
|
157
|
-
processedTag: `<${tagName}${openingTag.attrs}>${processedContent}</${tagName}>`
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
pos = nextClose + closeTagFull.length;
|
|
161
|
-
}
|
|
162
|
-
// No matching closing tag found - treat as self-closing
|
|
163
|
-
return {
|
|
164
|
-
id: 0,
|
|
165
|
-
start: startPos,
|
|
166
|
-
end: openingTag.end,
|
|
167
|
-
originalTag: markdown.slice(startPos, openingTag.end),
|
|
168
|
-
content: '',
|
|
169
|
-
processedTag: `<${tagName}${openingTag.attrs}/>`
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Extract all Marko components from markdown
|
|
174
|
-
*/
|
|
175
|
-
function extractComponents(markdown, md, onTagDetected, getLineNumber) {
|
|
176
|
-
const components = [];
|
|
177
|
-
let pos = 0;
|
|
178
|
-
let id = 0;
|
|
179
|
-
while (pos < markdown.length) {
|
|
180
|
-
// Find next potential tag
|
|
181
|
-
const tagStart = markdown.indexOf('<', pos);
|
|
182
|
-
if (tagStart === -1) {
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
const component = extractComponent(markdown, tagStart, md, onTagDetected, getLineNumber);
|
|
186
|
-
if (component) {
|
|
187
|
-
component.id = id++;
|
|
188
|
-
components.push(component);
|
|
189
|
-
pos = component.end;
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
pos = tagStart + 1;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
return components;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Get line number from position in text
|
|
199
|
-
*/
|
|
200
|
-
function getLineNumber(text, position) {
|
|
201
|
-
const before = text.substring(0, position);
|
|
202
|
-
return before.split('\n').length;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Main plugin function
|
|
206
|
-
*/
|
|
207
|
-
export function preserveTagsPlugin(md, options) {
|
|
208
|
-
const { onTagDetected } = options || {};
|
|
209
|
-
// Wrap the render method
|
|
210
|
-
const originalRender = md.render.bind(md);
|
|
211
|
-
md.render = (src, env) => {
|
|
212
|
-
// Extract all Marko components (with content processing)
|
|
213
|
-
const components = extractComponents(src, md, onTagDetected, getLineNumber);
|
|
214
|
-
// Replace with placeholders
|
|
215
|
-
let processedSrc = src;
|
|
216
|
-
let offset = 0;
|
|
217
|
-
for (const comp of components) {
|
|
218
|
-
const placeholder = createPlaceholder(comp.id);
|
|
219
|
-
const adjustedStart = comp.start + offset;
|
|
220
|
-
const adjustedEnd = comp.end + offset;
|
|
221
|
-
processedSrc = processedSrc.substring(0, adjustedStart) +
|
|
222
|
-
placeholder +
|
|
223
|
-
processedSrc.substring(adjustedEnd);
|
|
224
|
-
offset += placeholder.length - (comp.end - comp.start);
|
|
225
|
-
}
|
|
226
|
-
// Render with placeholders
|
|
227
|
-
const result = originalRender(processedSrc, env);
|
|
228
|
-
// Restore Marko components (with processed content)
|
|
229
|
-
const restored = restoreComponents(String(result), components);
|
|
230
|
-
return restored;
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=preserve-tags.js.map
|
|
1
|
+
const t=new Set(["div","p","h1","h2","h3","h4","h5","h6","hr","blockquote","pre","figure","figcaption","span","a","strong","em","b","i","u","s","sub","sup","code","small","ul","ol","li","dl","dt","dd","table","thead","tbody","tfoot","tr","th","td","caption","col","colgroup","form","input","button","select","datalist","optgroup","option","textarea","label","fieldset","legend","img","video","audio","source","track","canvas","map","area","script","style","link","meta","noscript","html","head","body","title","base","section","article","aside","header","footer","nav","main","address","details","summary","dialog","iframe","object","param","embed"]);function e(t){return`<div data-marko-tag="${t}"></div>`}function n(t,e){if(!t||!t.trim())return"";if(function(t){return/<[a-z][a-z0-9-]*(?:\s[^>]*?)?>/.test(t)||/<@[\w-]+/.test(t)}(t))return t;let n=e.render(t);const r=n.trim();if(r.startsWith("<p>")&&r.endsWith("</p>")){const t=r.slice(3,-4);t.includes("</div>")||t.includes("<pre>")||(n=t)}return n}function r(t,e){const n=/<([a-z][a-z0-9-]*)(\s[^>]*?)?(\/)?>/g;n.lastIndex=e;const r=n.exec(t);return r?{name:r[1],attrs:r[2]||"",selfClosing:"/"===r[3],end:r.index+r[0].length}:null}function s(e,s,i,o,a){const d=r(e,s);if(!d)return null;const c=d.name;if(t.has(c))return null;if(o&&a&&o(c,a(e,s)),d.selfClosing)return{id:0,start:s,end:d.end,originalTag:e.slice(s,d.end),content:"",processedTag:e.slice(s,d.end)};let l=d.end,u=1;const f=`</${c}>`;for(;l<e.length&&u>0;){const t=e.indexOf("<"+c,l),o=e.indexOf(f,l);if(-1===o)break;if(-1!==t&&t<o){const n=r(e,t);if(n&&n.name===c){u++,l=n.end;continue}}if(u--,0===u){const t=o+f.length,r=e.slice(d.end,o),a=n(r,i);return{id:0,start:s,end:t,originalTag:e.slice(s,t),content:r,processedTag:`<${c}${d.attrs}>${a}</${c}>`}}l=o+f.length}return{id:0,start:s,end:d.end,originalTag:e.slice(s,d.end),content:"",processedTag:`<${c}${d.attrs}/>`}}function i(t,e){return t.substring(0,e).split("\n").length}export function preserveTagsPlugin(t,n){const{onTagDetected:r}=n||{},o=t.render.bind(t);t.render=(n,a)=>{const d=function(t,e,n,r){const i=[];let o=0,a=0;for(;o<t.length;){const d=t.indexOf("<",o);if(-1===d)break;const c=s(t,d,e,n,r);c?(c.id=a++,i.push(c),o=c.end):o=d+1}return i}(n,t,r,i);let c=n,l=0;for(const t of d){const n=e(t.id),r=t.start+l,s=t.end+l;c=c.substring(0,r)+n+c.substring(s),l+=n.length-(t.end-t.start)}const u=function(t,n){let r=t;for(let t=n.length-1;t>=0;t--){const s=n[t],i=e(s.id);r=r.replace(i,s.processedTag)}return r}(o(c,a)+"",d);return u}}
|
|
@@ -1,146 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Request-time markdown renderer
|
|
3
|
-
* Lazy-loads MarkdownIt + Shiki on first use
|
|
4
|
-
* Used by route handlers to render markdown on demand
|
|
5
|
-
*/
|
|
6
|
-
import matter from 'gray-matter';
|
|
7
|
-
import MarkdownIt from 'markdown-it';
|
|
8
|
-
import { getMarkdownIt } from './loader.js';
|
|
9
|
-
/**
|
|
10
|
-
* Cached MarkdownIt instance (lazy-loaded on first use)
|
|
11
|
-
*/
|
|
12
|
-
let mdInstance = null;
|
|
13
|
-
let mdOptions;
|
|
14
|
-
/**
|
|
15
|
-
* Render markdown source to HTML at request time
|
|
16
|
-
*
|
|
17
|
-
* This function lazy-loads MarkdownIt + Shiki on first call,
|
|
18
|
-
* then reuses the instance for subsequent renders.
|
|
19
|
-
*
|
|
20
|
-
* @param source - Raw markdown source with frontmatter
|
|
21
|
-
* @param options - Markdown parsing options (only used on first call)
|
|
22
|
-
* @returns Processed markdown with frontmatter, HTML, and headers
|
|
23
|
-
*/
|
|
24
|
-
export async function renderMarkdown(source, options) {
|
|
25
|
-
// Lazy init MarkdownIt (one-time cost)
|
|
26
|
-
if (!mdInstance) {
|
|
27
|
-
// Always enable markoTags for component support
|
|
28
|
-
const opts = {
|
|
29
|
-
...options,
|
|
30
|
-
markoTags: {
|
|
31
|
-
enabled: true,
|
|
32
|
-
...options?.markoTags
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
mdInstance = await getMarkdownIt(opts);
|
|
36
|
-
mdOptions = opts;
|
|
37
|
-
}
|
|
38
|
-
// Parse frontmatter
|
|
39
|
-
const { data: frontmatter, content: rawContent, excerpt } = matter(source, {
|
|
40
|
-
excerpt: true,
|
|
41
|
-
excerpt_separator: '<!-- more -->',
|
|
42
|
-
});
|
|
43
|
-
// Render markdown to HTML
|
|
44
|
-
const html = mdInstance.render(rawContent);
|
|
45
|
-
// Extract headers for TOC
|
|
46
|
-
const headers = extractHeaders(rawContent);
|
|
47
|
-
return {
|
|
48
|
-
frontmatter,
|
|
49
|
-
content: rawContent,
|
|
50
|
-
html,
|
|
51
|
-
excerpt,
|
|
52
|
-
headers: buildHeaderTree(headers),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Reset the cached MarkdownIt instance
|
|
57
|
-
* Useful for testing or when options change
|
|
58
|
-
*/
|
|
59
|
-
export function resetRendererCache() {
|
|
60
|
-
mdInstance = null;
|
|
61
|
-
mdOptions = undefined;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Get the current MarkdownIt instance if initialized
|
|
65
|
-
*/
|
|
66
|
-
export function getRendererInstance() {
|
|
67
|
-
return mdInstance;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Strip markdown formatting from text for cleaner TOC entries
|
|
71
|
-
*/
|
|
72
|
-
function stripMarkdownFormatting(text) {
|
|
73
|
-
return text
|
|
74
|
-
.replace(/`([^`]+)`/g, '$1')
|
|
75
|
-
.replace(/\*\*\*\+([^*]+)\*\*\+/g, '$1')
|
|
76
|
-
.replace(/___+([^_]+)___+/g, '$1')
|
|
77
|
-
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
|
78
|
-
.replace(/__([^_]+)__/g, '$1')
|
|
79
|
-
.replace(/\*([^*]+)\*/g, '$1')
|
|
80
|
-
.replace(/_([^_]+)_/g, '$1')
|
|
81
|
-
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
|
82
|
-
.replace(/\[([^\]]+)\]\[[^\]]+\]/g, '$1')
|
|
83
|
-
.trim();
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Extract headers from markdown content
|
|
87
|
-
*/
|
|
88
|
-
function extractHeaders(content) {
|
|
89
|
-
const headers = [];
|
|
90
|
-
const withoutCodeBlocks = content
|
|
91
|
-
.replace(/```[\s\S]*?```/g, '')
|
|
92
|
-
.replace(/~~~[\s\S]*?~~~/g, '')
|
|
93
|
-
.replace(/^(\t| {4}).+$/gm, '');
|
|
94
|
-
const headerRegex = /^(#{1,6})\s+(.+)$/gm;
|
|
95
|
-
let match;
|
|
96
|
-
while ((match = headerRegex.exec(withoutCodeBlocks)) !== null) {
|
|
97
|
-
const level = match[1].length;
|
|
98
|
-
const rawTitle = match[2].trim();
|
|
99
|
-
const title = stripMarkdownFormatting(rawTitle);
|
|
100
|
-
const slug = slugify(rawTitle);
|
|
101
|
-
headers.push({ level, title, slug });
|
|
102
|
-
}
|
|
103
|
-
return headers;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Build header tree from flat list
|
|
107
|
-
*/
|
|
108
|
-
function buildHeaderTree(headers) {
|
|
109
|
-
const result = [];
|
|
110
|
-
const stack = [];
|
|
111
|
-
for (const header of headers) {
|
|
112
|
-
const node = {
|
|
113
|
-
level: header.level,
|
|
114
|
-
title: header.title,
|
|
115
|
-
slug: header.slug,
|
|
116
|
-
children: [],
|
|
117
|
-
};
|
|
118
|
-
while (stack.length > 0 && stack[stack.length - 1].level >= header.level) {
|
|
119
|
-
stack.pop();
|
|
120
|
-
}
|
|
121
|
-
if (stack.length === 0) {
|
|
122
|
-
result.push(node);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
stack[stack.length - 1].children.push(node);
|
|
126
|
-
}
|
|
127
|
-
stack.push(node);
|
|
128
|
-
}
|
|
129
|
-
return result;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Slugify text for URL-safe IDs
|
|
133
|
-
*/
|
|
134
|
-
function slugify(text) {
|
|
135
|
-
return text
|
|
136
|
-
.trim()
|
|
137
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
138
|
-
.replace(/([0-9])([a-zA-Z])/g, '$1-$2')
|
|
139
|
-
.replace(/([a-zA-Z])([0-9])/g, '$1-$2')
|
|
140
|
-
.toLowerCase()
|
|
141
|
-
.replace(/\s+/g, '-')
|
|
142
|
-
.replace(/[^\w\u00A0-\uFFFF\-]+/g, '')
|
|
143
|
-
.replace(/^-+|-+$/g, '')
|
|
144
|
-
.replace(/-+/g, '-');
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=renderer.js.map
|
|
1
|
+
import e from"gray-matter";import r from"markdown-it";import{getMarkdownIt as t}from"./loader.js";let l,n=null;export async function renderMarkdown(r,p){if(!n){const e={...p,markoTags:{enabled:!0,...p?.markoTags}};n=await t(e),l=e}const{data:g,content:s,excerpt:u}=e(r,{excerpt:!0,excerpt_separator:"\x3c!-- more --\x3e"});return{frontmatter:g,content:s,html:n.render(s),excerpt:u,headers:a(function(e){const r=[],t=e.replace(/```[\s\S]*?```/g,"").replace(/~~~[\s\S]*?~~~/g,"").replace(/^(\t| {4}).+$/gm,""),l=/^(#{1,6})\s+(.+)$/gm;let n;for(;null!==(n=l.exec(t));){const e=n[1].length,t=n[2].trim(),l=c(t),a=o(t);r.push({level:e,title:l,slug:a})}return r}(s))}}export function resetRendererCache(){n=null,l=void 0}export function getRendererInstance(){return n}function c(e){return e.replace(/`([^`]+)`/g,"$1").replace(/\*\*\*\+([^*]+)\*\*\+/g,"$1").replace(/___+([^_]+)___+/g,"$1").replace(/\*\*([^*]+)\*\*/g,"$1").replace(/__([^_]+)__/g,"$1").replace(/\*([^*]+)\*/g,"$1").replace(/_([^_]+)_/g,"$1").replace(/\[([^\]]+)\]\([^)]+\)/g,"$1").replace(/\[([^\]]+)\]\[[^\]]+\]/g,"$1").trim()}function a(e){const r=[],t=[];for(const l of e){const e={level:l.level,title:l.title,slug:l.slug,children:[]};for(;t.length>0&&t[t.length-1].level>=l.level;)t.pop();0===t.length?r.push(e):t[t.length-1].children.push(e),t.push(e)}return r}function o(e){return e.trim().replace(/([a-z])([A-Z])/g,"$1-$2").replace(/([0-9])([a-zA-Z])/g,"$1-$2").replace(/([a-zA-Z])([0-9])/g,"$1-$2").toLowerCase().replace(/\s+/g,"-").replace(/[^\w\u00A0-\uFFFF\-]+/g,"").replace(/^-+|-+$/g,"").replace(/-+/g,"-")}
|
|
@@ -1,118 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Tag Validator for Marko components in markdown
|
|
3
|
-
*
|
|
4
|
-
* Tracks all detected Marko tags during the build process,
|
|
5
|
-
* scans the tags/ directory for available components,
|
|
6
|
-
* and validates that all detected tags have corresponding component files.
|
|
7
|
-
*/
|
|
8
|
-
import { promises as fs } from 'node:fs';
|
|
9
|
-
import path from 'node:path';
|
|
10
|
-
export class TagValidator {
|
|
11
|
-
detectedTags = new Map();
|
|
12
|
-
availableTags = new Set();
|
|
13
|
-
/**
|
|
14
|
-
* Add a detected tag for tracking
|
|
15
|
-
*/
|
|
16
|
-
addDetectedTag(tagName, fileName, lineNumber) {
|
|
17
|
-
const normalized = tagName.toLowerCase();
|
|
18
|
-
if (!this.detectedTags.has(normalized)) {
|
|
19
|
-
this.detectedTags.set(normalized, []);
|
|
20
|
-
}
|
|
21
|
-
this.detectedTags.get(normalized).push({
|
|
22
|
-
tagName: normalized,
|
|
23
|
-
fileName,
|
|
24
|
-
lineNumber,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Scan tags directory to find all available Marko components
|
|
29
|
-
*/
|
|
30
|
-
async loadAvailableTags(tagsDir) {
|
|
31
|
-
try {
|
|
32
|
-
await fs.access(tagsDir);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
// Directory doesn't exist, that's OK (no tags available)
|
|
36
|
-
console.warn(`Warning: tags directory not found at ${tagsDir}`);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const files = await fs.readdir(tagsDir);
|
|
40
|
-
for (const file of files) {
|
|
41
|
-
if (file.endsWith('.marko')) {
|
|
42
|
-
const tagName = file.replace('.marko', '');
|
|
43
|
-
this.availableTags.add(tagName);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Get count of available tags
|
|
49
|
-
*/
|
|
50
|
-
getAvailableTagsCount() {
|
|
51
|
-
return this.availableTags.size;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Get list of available tags
|
|
55
|
-
*/
|
|
56
|
-
getAvailableTags() {
|
|
57
|
-
return Array.from(this.availableTags).sort();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Get all detected tags (grouped by tag name)
|
|
61
|
-
*/
|
|
62
|
-
getDetectedTags() {
|
|
63
|
-
return this.detectedTags;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Validate that all detected tags exist in the tags directory
|
|
67
|
-
*
|
|
68
|
-
* @returns Validation result with success flag and list of missing tags
|
|
69
|
-
*/
|
|
70
|
-
validate() {
|
|
71
|
-
const missingTags = [];
|
|
72
|
-
// Check each detected tag
|
|
73
|
-
for (const [tagName, occurrences] of this.detectedTags) {
|
|
74
|
-
if (!this.availableTags.has(tagName)) {
|
|
75
|
-
// Tag is missing - add all occurrences
|
|
76
|
-
missingTags.push(...occurrences);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
success: missingTags.length === 0,
|
|
81
|
-
missingTags,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Clear state for new build
|
|
86
|
-
*/
|
|
87
|
-
reset() {
|
|
88
|
-
this.detectedTags.clear();
|
|
89
|
-
this.availableTags.clear();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Format validation error message
|
|
94
|
-
*/
|
|
95
|
-
export function formatValidationError(missingTags) {
|
|
96
|
-
// Group by tag name
|
|
97
|
-
const uniqueTags = new Map();
|
|
98
|
-
for (const tag of missingTags) {
|
|
99
|
-
if (!uniqueTags.has(tag.tagName)) {
|
|
100
|
-
uniqueTags.set(tag.tagName, []);
|
|
101
|
-
}
|
|
102
|
-
uniqueTags.get(tag.tagName).push(tag);
|
|
103
|
-
}
|
|
104
|
-
let output = '\n❌ Marko tags not found:\n';
|
|
105
|
-
for (const [tagName, occurrences] of uniqueTags) {
|
|
106
|
-
output += `\n <${tagName}> used in:\n`;
|
|
107
|
-
for (const occ of occurrences) {
|
|
108
|
-
output += ` ${occ.fileName}:${occ.lineNumber}\n`;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
output += '\nCreate missing files in tags/ directory or remove tags from markdown.\n';
|
|
112
|
-
return output;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Create a global validator instance
|
|
116
|
-
*/
|
|
117
|
-
export const globalTagValidator = new TagValidator();
|
|
118
|
-
//# sourceMappingURL=tag-validator.js.map
|
|
1
|
+
import{promises as a}from"node:fs";import e from"node:path";export class TagValidator{detectedTags=new Map;availableTags=new Set;addDetectedTag(a,e,t){const s=a.toLowerCase();this.detectedTags.has(s)||this.detectedTags.set(s,[]),this.detectedTags.get(s).push({tagName:s,fileName:e,lineNumber:t})}async loadAvailableTags(e){try{await a.access(e)}catch{return void console.warn("Warning: tags directory not found at "+e)}const t=await a.readdir(e);for(const a of t)if(a.endsWith(".marko")){const e=a.replace(".marko","");this.availableTags.add(e)}}getAvailableTagsCount(){return this.availableTags.size}getAvailableTags(){return Array.from(this.availableTags).sort()}getDetectedTags(){return this.detectedTags}validate(){const a=[];for(const[e,t]of this.detectedTags)this.availableTags.has(e)||a.push(...t);return{success:0===a.length,missingTags:a}}reset(){this.detectedTags.clear(),this.availableTags.clear()}}export function formatValidationError(a){const e=new Map;for(const t of a)e.has(t.tagName)||e.set(t.tagName,[]),e.get(t.tagName).push(t);let t="\n❌ Marko tags not found:\n";for(const[a,s]of e){t+=`\n <${a}> used in:\n`;for(const a of s)t+=` ${a.fileName}:${a.lineNumber}\n`}return t+="\nCreate missing files in tags/ directory or remove tags from markdown.\n",t}export const globalTagValidator=new TagValidator;
|
package/dist/markdown/types.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface MarkdownOptions {
|
|
|
16
16
|
/** Directory containing Marko component files (default: 'tags/') */
|
|
17
17
|
tagsDir?: string;
|
|
18
18
|
};
|
|
19
|
+
/** Base path for link rewriting (e.g., '/markopress'). Links are rewritten only when this is non-root. */
|
|
20
|
+
base?: string;
|
|
19
21
|
}
|
|
20
22
|
export interface MarkdownProcessor {
|
|
21
23
|
process(src: string, filePath?: string): Promise<ProcessedMarkdown>;
|
|
@@ -41,4 +43,3 @@ export interface MarkdownEnv {
|
|
|
41
43
|
/** Enable TOC extraction for this file (default: false) */
|
|
42
44
|
extractToc?: boolean;
|
|
43
45
|
}
|
|
44
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/markdown/types.js
CHANGED
package/dist/plugin/compat.d.ts
CHANGED
package/dist/plugin/compat.js
CHANGED
|
@@ -1,78 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Backward compatibility utilities for plugins
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Wrap legacy plugin to support new hooks
|
|
6
|
-
* Ensures old plugins work without modification
|
|
7
|
-
*/
|
|
8
|
-
export function wrapLegacyPlugin(plugin) {
|
|
9
|
-
// If plugin already has new hooks, return as-is
|
|
10
|
-
if (plugin.loadContent || plugin.allContentLoaded || plugin.postBuild) {
|
|
11
|
-
return plugin;
|
|
12
|
-
}
|
|
13
|
-
// Wrap old contentLoaded signature
|
|
14
|
-
const originalContentLoaded = plugin.contentLoaded;
|
|
15
|
-
if (originalContentLoaded) {
|
|
16
|
-
plugin.contentLoaded = function (ctx) {
|
|
17
|
-
// Old signature: contentLoaded(ctx: ContentContext)
|
|
18
|
-
// New signature: contentLoaded(ctx: { content, allContent, actions })
|
|
19
|
-
// Check if using old signature (has addPage, addPost but no allContent)
|
|
20
|
-
if (ctx.addPage && ctx.addPost && !ctx.allContent) {
|
|
21
|
-
// Old plugin - provide backward compatible context
|
|
22
|
-
return originalContentLoaded.call(this, ctx);
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
// New signature - call as-is
|
|
26
|
-
return originalContentLoaded.call(this, ctx);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
// Convert beforeBuild to allContentLoaded (for migration)
|
|
31
|
-
if (plugin.beforeBuild && !plugin.allContentLoaded) {
|
|
32
|
-
const originalBeforeBuild = plugin.beforeBuild;
|
|
33
|
-
plugin.allContentLoaded = function (ctx) {
|
|
34
|
-
// Map old beforeBuild context to new allContentLoaded context
|
|
35
|
-
const oldContext = {
|
|
36
|
-
content: ctx.allContent,
|
|
37
|
-
routes: ctx.routes,
|
|
38
|
-
config: ctx.config,
|
|
39
|
-
};
|
|
40
|
-
return originalBeforeBuild.call(this, oldContext);
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
// Convert afterBuild to postBuild (for migration)
|
|
44
|
-
if (plugin.afterBuild && !plugin.postBuild) {
|
|
45
|
-
const originalAfterBuild = plugin.afterBuild;
|
|
46
|
-
plugin.postBuild = function (ctx) {
|
|
47
|
-
// Map old afterBuild context to new postBuild context
|
|
48
|
-
const oldContext = {
|
|
49
|
-
outDir: ctx.outDir,
|
|
50
|
-
routes: ctx.routes,
|
|
51
|
-
content: ctx.allContent,
|
|
52
|
-
};
|
|
53
|
-
return originalAfterBuild.call(this, oldContext);
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return plugin;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Check if plugin is using legacy signature
|
|
60
|
-
*/
|
|
61
|
-
export function isLegacyPlugin(plugin) {
|
|
62
|
-
// Check if plugin has old contentLoaded signature but not new one
|
|
63
|
-
if (plugin.contentLoaded) {
|
|
64
|
-
// Can't determine without checking the function signature
|
|
65
|
-
// We'll detect at runtime
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
// Has beforeBuild but not allContentLoaded -> likely legacy
|
|
69
|
-
if (plugin.beforeBuild && !plugin.allContentLoaded) {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
// Has afterBuild but not postBuild -> likely legacy
|
|
73
|
-
if (plugin.afterBuild && !plugin.postBuild) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
//# sourceMappingURL=compat.js.map
|
|
1
|
+
export function wrapLegacyPlugin(t){if(t.loadContent||t.allContentLoaded||t.postBuild)return t;const n=t.contentLoaded;if(n&&(t.contentLoaded=function(t){return t.addPage&&t.addPost&&t.allContent,n.call(this,t)}),t.beforeBuild&&!t.allContentLoaded){const n=t.beforeBuild;t.allContentLoaded=function(t){const o={content:t.allContent,routes:t.routes,config:t.config};return n.call(this,o)}}if(t.afterBuild&&!t.postBuild){const n=t.afterBuild;t.postBuild=function(t){const o={outDir:t.outDir,routes:t.routes,content:t.allContent};return n.call(this,o)}}return t}export function isLegacyPlugin(t){return!(t.contentLoaded||(!t.beforeBuild||t.allContentLoaded)&&(!t.afterBuild||t.postBuild))}
|
package/dist/plugin/context.d.ts
CHANGED