@sullux/markdown-docs 1.0.0 → 1.0.2
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/README.md +80 -33
- package/bin/cli.js +3 -2
- package/lib/config.js +51 -19
- package/lib/icons.js +10 -0
- package/lib/layout.js +87 -45
- package/lib/site.js +28 -32
- package/lib/summary.js +19 -8
- package/lib/theme.css +719 -0
- package/lib/theme.js +16 -70
- package/lib/toc.js +12 -5
- package/lib/yaml.js +82 -0
- package/package.json +1 -1
package/lib/theme.js
CHANGED
|
@@ -1,75 +1,21 @@
|
|
|
1
|
-
const
|
|
2
|
-
:
|
|
3
|
-
--bg-primary: #ffffff;
|
|
4
|
-
--bg-sidebar: #f7f9fa;
|
|
5
|
-
--text-primary: #1c1e21;
|
|
6
|
-
--text-muted: #5c6975;
|
|
7
|
-
--border-color: #e8ecf0;
|
|
8
|
-
--accent-color: #3b82f6;
|
|
9
|
-
--accent-hover: #1d4ed8;
|
|
10
|
-
--code-bg: #f3f4f6;
|
|
11
|
-
--callout-info-bg: #eff6ff;
|
|
12
|
-
--callout-info-border: #3b82f6;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
[data-theme="dark"] {
|
|
16
|
-
--bg-primary: #0f172a;
|
|
17
|
-
--bg-sidebar: #1e293b;
|
|
18
|
-
--text-primary: #f8fafc;
|
|
19
|
-
--text-muted: #94a3b8;
|
|
20
|
-
--border-color: #334155;
|
|
21
|
-
--accent-color: #60a5fa;
|
|
22
|
-
--accent-hover: #93c5fd;
|
|
23
|
-
--code-bg: #1e293b;
|
|
24
|
-
--callout-info-bg: #1e3a8a;
|
|
25
|
-
--callout-info-border: #60a5fa;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
29
|
-
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; color: var(--text-primary); background: var(--bg-primary); line-height: 1.6; display: flex; min-height: 100vh; }
|
|
30
|
-
|
|
31
|
-
.app-sidebar { width: 280px; background: var(--bg-sidebar); border-right: 1px solid var(--border-color); padding: 1.5rem; display: flex; flex-direction: column; shrink: 0; }
|
|
32
|
-
.app-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 1rem; color: var(--text-primary); text-decoration: none; display: flex; align-items: center; gap: 0.5rem; }
|
|
33
|
-
.search-box { margin-bottom: 1rem; position: relative; }
|
|
34
|
-
.search-input { width: 100%; padding: 0.5rem 0.75rem; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); color: var(--text-primary); }
|
|
35
|
-
.search-results { position: absolute; top: 100%; left: 0; right: 0; background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 6px; max-height: 250px; overflow-y: auto; z-index: 100; display: none; }
|
|
36
|
-
.search-item { padding: 0.5rem; text-decoration: none; color: var(--text-primary); display: block; border-bottom: 1px solid var(--border-color); }
|
|
37
|
-
.search-item:hover { background: var(--code-bg); }
|
|
1
|
+
const fs = require('node:fs')
|
|
2
|
+
const path = require('node:path')
|
|
38
3
|
|
|
39
|
-
|
|
40
|
-
.nav-item { margin-bottom: 0.25rem; }
|
|
41
|
-
.nav-link { display: block; padding: 0.4rem 0.6rem; color: var(--text-muted); text-decoration: none; border-radius: 4px; font-size: 0.95rem; }
|
|
42
|
-
.nav-link:hover, .nav-link.active { color: var(--accent-color); font-weight: 600; background: var(--code-bg); }
|
|
43
|
-
.nav-sub { list-style: none; padding-left: 1rem; margin-top: 0.25rem; }
|
|
4
|
+
const cssTemplate = fs.readFileSync(path.join(__dirname, 'theme.css'), 'utf8')
|
|
44
5
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
th, td { border: 1px solid var(--border-color); padding: 0.6rem 0.8rem; text-align: left; }
|
|
59
|
-
th { background: var(--code-bg); }
|
|
60
|
-
|
|
61
|
-
.hl-kw { color: #d73a49; font-weight: bold; }
|
|
62
|
-
.hl-str { color: #032f62; }
|
|
63
|
-
.hl-num { color: #005cc5; }
|
|
64
|
-
.hl-cmt { color: #6a737d; font-style: italic; }
|
|
65
|
-
.hl-id { color: #6f42c1; }
|
|
66
|
-
.hl-punc { color: #24292e; }
|
|
67
|
-
|
|
68
|
-
@media (max-width: 768px) {
|
|
69
|
-
body { flex-direction: column; }
|
|
70
|
-
.app-sidebar { width: 100%; border-right: none; border-bottom: 1px solid var(--border-color); }
|
|
71
|
-
.app-content { padding: 1.5rem; }
|
|
6
|
+
const getCss = (theme = {}) => {
|
|
7
|
+
const vars = `
|
|
8
|
+
:root {
|
|
9
|
+
--theme-light-bg: ${theme.bgLight || theme.light?.bg || '#ffffff'};
|
|
10
|
+
--theme-light-accent: ${theme.accentLight || theme.light?.accent || theme.accent || '#2563eb'};
|
|
11
|
+
--theme-light-code-bg: ${theme.light?.codeBg || '#f8fafc'};
|
|
12
|
+
--theme-light-code-text: ${theme.light?.codeText || '#0f172a'};
|
|
13
|
+
--theme-dark-bg: ${theme.bgDark || theme.dark?.bg || '#121316'};
|
|
14
|
+
--theme-dark-accent: ${theme.accentDark || theme.dark?.accent || theme.accent || '#3b82f6'};
|
|
15
|
+
--theme-dark-code-bg: ${theme.dark?.codeBg || '#0a0b0e'};
|
|
16
|
+
--theme-dark-code-text: ${theme.dark?.codeText || '#f3f4f6'};
|
|
17
|
+
}`
|
|
18
|
+
return `${vars}\n${cssTemplate}`
|
|
72
19
|
}
|
|
73
|
-
`
|
|
74
20
|
|
|
75
21
|
module.exports = { getCss }
|
package/lib/toc.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
const { slugify } = require('@sullux/markdown-html/lib/markdown-to-html/slugify')
|
|
2
2
|
|
|
3
|
+
const getNodeText = (node) => {
|
|
4
|
+
if (!node) return ''
|
|
5
|
+
if (node.value) return node.value
|
|
6
|
+
if (node.children) return node.children.map(getNodeText).join('')
|
|
7
|
+
return ''
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
const extractToc = (ast) => {
|
|
4
11
|
if (!ast || !ast.blocks) return []
|
|
5
12
|
const usedSlugs = new Set()
|
|
@@ -7,11 +14,11 @@ const extractToc = (ast) => {
|
|
|
7
14
|
|
|
8
15
|
for (const block of ast.blocks) {
|
|
9
16
|
if (block.type === 'header' && (block.level === 2 || block.level === 3)) {
|
|
10
|
-
const rawText = block.children
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
const rawText = block.children ? block.children.map(getNodeText).join('') : ''
|
|
18
|
+
if (rawText) {
|
|
19
|
+
const slug = slugify(rawText, usedSlugs)
|
|
20
|
+
toc.push({ level: block.level, title: rawText, id: slug })
|
|
21
|
+
}
|
|
15
22
|
}
|
|
16
23
|
}
|
|
17
24
|
|
package/lib/yaml.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const parseYaml = (str) => {
|
|
2
|
+
if (!str) return {}
|
|
3
|
+
const lines = str.split(/\r?\n/)
|
|
4
|
+
const root = {}
|
|
5
|
+
const stack = [{ indent: -1, node: root }]
|
|
6
|
+
|
|
7
|
+
for (const raw of lines) {
|
|
8
|
+
if (!raw.trim() || raw.trim().startsWith('#')) continue
|
|
9
|
+
const indent = raw.search(/\S/)
|
|
10
|
+
const line = raw.trim()
|
|
11
|
+
|
|
12
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
|
|
13
|
+
stack.pop()
|
|
14
|
+
}
|
|
15
|
+
const parent = stack[stack.length - 1].node
|
|
16
|
+
|
|
17
|
+
if (line.startsWith('- ')) {
|
|
18
|
+
const rest = line.slice(2).trim()
|
|
19
|
+
const colon = rest.indexOf(':')
|
|
20
|
+
let item = parseVal(rest)
|
|
21
|
+
if (colon !== -1) {
|
|
22
|
+
const k = rest.slice(0, colon).trim()
|
|
23
|
+
const v = parseVal(rest.slice(colon + 1).trim())
|
|
24
|
+
item = { [k]: v }
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(parent)) {
|
|
27
|
+
parent.push(item)
|
|
28
|
+
if (typeof item === 'object') stack.push({ indent: indent + 2, node: item })
|
|
29
|
+
} else if (typeof parent === 'object') {
|
|
30
|
+
const top = stack[stack.length - 1]
|
|
31
|
+
if (top.parent && top.key) {
|
|
32
|
+
const arr = [item]
|
|
33
|
+
top.parent[top.key] = arr
|
|
34
|
+
stack[stack.length - 1].node = arr
|
|
35
|
+
if (typeof item === 'object') stack.push({ indent: indent + 2, node: item })
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
continue
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const colon = line.indexOf(':')
|
|
42
|
+
if (colon !== -1) {
|
|
43
|
+
const k = line.slice(0, colon).trim()
|
|
44
|
+
const rawV = line.slice(colon + 1).trim()
|
|
45
|
+
const v = parseVal(rawV)
|
|
46
|
+
|
|
47
|
+
if (!rawV) {
|
|
48
|
+
const child = {}
|
|
49
|
+
if (Array.isArray(parent)) {
|
|
50
|
+
parent.push({ [k]: child })
|
|
51
|
+
} else {
|
|
52
|
+
parent[k] = child
|
|
53
|
+
}
|
|
54
|
+
stack.push({ indent, node: child, key: k, parent })
|
|
55
|
+
} else {
|
|
56
|
+
if (Array.isArray(parent)) {
|
|
57
|
+
let last = parent[parent.length - 1]
|
|
58
|
+
if (typeof last !== 'object' || last[k] !== undefined) {
|
|
59
|
+
last = {}
|
|
60
|
+
parent.push(last)
|
|
61
|
+
}
|
|
62
|
+
last[k] = v
|
|
63
|
+
} else {
|
|
64
|
+
parent[k] = v
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return root
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const parseVal = (v) => {
|
|
74
|
+
if (!v) return ''
|
|
75
|
+
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) return v.slice(1, -1)
|
|
76
|
+
if (v === 'true') return true
|
|
77
|
+
if (v === 'false') return false
|
|
78
|
+
if (!isNaN(v) && v !== '') return Number(v)
|
|
79
|
+
return v
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = { parseYaml }
|
package/package.json
CHANGED