@mgks/docmd 0.3.11 → 0.4.1
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 +15 -160
- package/bin/docmd.js +6 -69
- package/package.json +17 -57
- package/bin/postinstall.js +0 -14
- package/src/assets/css/docmd-highlight-dark.css +0 -86
- package/src/assets/css/docmd-highlight-light.css +0 -86
- package/src/assets/css/docmd-main.css +0 -1757
- package/src/assets/css/docmd-theme-retro.css +0 -867
- package/src/assets/css/docmd-theme-ruby.css +0 -629
- package/src/assets/css/docmd-theme-sky.css +0 -617
- package/src/assets/favicon.ico +0 -0
- package/src/assets/images/docmd-logo-dark.png +0 -0
- package/src/assets/images/docmd-logo-light.png +0 -0
- package/src/assets/js/docmd-image-lightbox.js +0 -74
- package/src/assets/js/docmd-main.js +0 -260
- package/src/assets/js/docmd-mermaid.js +0 -205
- package/src/assets/js/docmd-search.js +0 -218
- package/src/commands/build.js +0 -237
- package/src/commands/dev.js +0 -352
- package/src/commands/init.js +0 -277
- package/src/commands/live.js +0 -145
- package/src/core/asset-manager.js +0 -72
- package/src/core/config-loader.js +0 -58
- package/src/core/config-validator.js +0 -80
- package/src/core/file-processor.js +0 -103
- package/src/core/fs-utils.js +0 -40
- package/src/core/html-generator.js +0 -185
- package/src/core/icon-renderer.js +0 -106
- package/src/core/logger.js +0 -21
- package/src/core/markdown/containers.js +0 -94
- package/src/core/markdown/renderers.js +0 -90
- package/src/core/markdown/rules.js +0 -402
- package/src/core/markdown/setup.js +0 -113
- package/src/core/navigation-helper.js +0 -74
- package/src/index.js +0 -12
- package/src/live/core.js +0 -67
- package/src/live/index.html +0 -216
- package/src/live/live.css +0 -256
- package/src/live/shims.js +0 -1
- package/src/plugins/analytics.js +0 -48
- package/src/plugins/seo.js +0 -107
- package/src/plugins/sitemap.js +0 -127
- package/src/templates/layout.ejs +0 -187
- package/src/templates/navigation.ejs +0 -97
- package/src/templates/no-style.ejs +0 -166
- package/src/templates/partials/theme-init.js +0 -36
- package/src/templates/toc.ejs +0 -38
package/src/live/index.html
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
<!-- Source file from the docmd project — https://github.com/docmd-io/docmd -->
|
|
2
|
-
|
|
3
|
-
<!DOCTYPE html>
|
|
4
|
-
<html lang="en">
|
|
5
|
-
<head>
|
|
6
|
-
<meta charset="UTF-8">
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
-
<title>Docmd Live Editor</title>
|
|
9
|
-
<meta name="description" content="Real-time Markdown preview and editor powered by docmd.">
|
|
10
|
-
|
|
11
|
-
<link rel="icon" href="favicon.ico" type="image/x-icon" sizes="any">
|
|
12
|
-
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
|
13
|
-
|
|
14
|
-
<link rel="stylesheet" href="live.css">
|
|
15
|
-
<script src="docmd-live.js"></script>
|
|
16
|
-
|
|
17
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-VCMQ0MCSHN"></script>
|
|
18
|
-
<script>
|
|
19
|
-
window.dataLayer = window.dataLayer || [];
|
|
20
|
-
function gtag(){dataLayer.push(arguments);}
|
|
21
|
-
gtag('js', new Date());
|
|
22
|
-
gtag('config', 'G-VCMQ0MCSHN');
|
|
23
|
-
</script>
|
|
24
|
-
</head>
|
|
25
|
-
<body class="mode-split mobile-tab-editor">
|
|
26
|
-
|
|
27
|
-
<!-- Top Bar (Desktop) -->
|
|
28
|
-
<div class="top-bar">
|
|
29
|
-
<div class="logo">
|
|
30
|
-
<a href="/" class="back-link" id="back-btn" title="Back to Home" aria-label="Back to Home">
|
|
31
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
32
|
-
<path d="m12 19-7-7 7-7"/>
|
|
33
|
-
<path d="M19 12H5"/>
|
|
34
|
-
</svg>
|
|
35
|
-
</a>
|
|
36
|
-
docmd <span>Live</span>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<div class="view-controls desktop-only">
|
|
40
|
-
<button class="view-btn active" onclick="setViewMode('split')" id="btn-split">Split View</button>
|
|
41
|
-
<button class="view-btn" onclick="setViewMode('single')" id="btn-single">Single View</button>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<!-- Single View Tabs (Visible only when in Single Mode on Desktop) -->
|
|
45
|
-
<div class="view-controls" id="single-view-tabs" style="display:none;">
|
|
46
|
-
<button class="view-btn active" onclick="switchSingleTab('editor')" id="btn-tab-edit">Editor</button>
|
|
47
|
-
<button class="view-btn" onclick="switchSingleTab('preview')" id="btn-tab-prev">Preview</button>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<!-- Workspace -->
|
|
52
|
-
<div class="workspace" id="workspace">
|
|
53
|
-
<!-- Editor -->
|
|
54
|
-
<div class="pane editor-pane" id="editorPane">
|
|
55
|
-
<div class="pane-header">Markdown</div>
|
|
56
|
-
<textarea id="input" spellcheck="false">---
|
|
57
|
-
title: My Page
|
|
58
|
-
description: Start editing to see changes instantly.
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
# Hello World
|
|
62
|
-
|
|
63
|
-
This is a **live** preview.
|
|
64
|
-
|
|
65
|
-
::: callout tip
|
|
66
|
-
Try resizing the window or switching to mobile view!
|
|
67
|
-
:::
|
|
68
|
-
|
|
69
|
-
## Features
|
|
70
|
-
1. Responsive Design
|
|
71
|
-
2. Split or Tabbed view
|
|
72
|
-
3. Instant Rendering
|
|
73
|
-
</textarea>
|
|
74
|
-
</div>
|
|
75
|
-
|
|
76
|
-
<!-- Resizer Handle -->
|
|
77
|
-
<div class="resizer" id="resizer"></div>
|
|
78
|
-
|
|
79
|
-
<!-- Preview -->
|
|
80
|
-
<div class="pane preview-pane" id="previewPane">
|
|
81
|
-
<div class="pane-header">Preview</div>
|
|
82
|
-
<iframe id="preview"></iframe>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<!-- Mobile Bottom Tabs -->
|
|
87
|
-
<div class="mobile-tabs">
|
|
88
|
-
<button class="mobile-tab-btn active" onclick="setMobileTab('editor')" id="mob-edit">Editor</button>
|
|
89
|
-
<button class="mobile-tab-btn" onclick="setMobileTab('preview')" id="mob-prev">Preview</button>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<script>
|
|
93
|
-
// --- Core Logic ---
|
|
94
|
-
const input = document.getElementById('input');
|
|
95
|
-
const preview = document.getElementById('preview');
|
|
96
|
-
const backBtn = document.getElementById('back-btn');
|
|
97
|
-
|
|
98
|
-
function render() {
|
|
99
|
-
try {
|
|
100
|
-
let html = docmd.compile(input.value, {
|
|
101
|
-
siteTitle: 'My Project', // User can change this in real config, but here we set a default
|
|
102
|
-
search: false,
|
|
103
|
-
theme: { name: 'sky', defaultMode: 'light' },
|
|
104
|
-
sidebar: { collapsible: false }
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// --- INJECTIONS ---
|
|
108
|
-
|
|
109
|
-
// 1. Force links to open in new tab (Fixes infinite iframe recursion)
|
|
110
|
-
html = html.replace('<head>', '<head><base target="_blank">');
|
|
111
|
-
|
|
112
|
-
// 2. Hide Sidebar Header via CSS
|
|
113
|
-
const customStyle = `
|
|
114
|
-
<style>
|
|
115
|
-
.sidebar-header { display: none !important; }
|
|
116
|
-
.sidebar-nav { margin-top: 1rem; }
|
|
117
|
-
</style>
|
|
118
|
-
`;
|
|
119
|
-
html = html.replace('</body>', `${customStyle}</body>`);
|
|
120
|
-
// ------------------
|
|
121
|
-
|
|
122
|
-
const doc = preview.contentWindow.document;
|
|
123
|
-
doc.open();
|
|
124
|
-
doc.write(html);
|
|
125
|
-
doc.close();
|
|
126
|
-
} catch (e) { console.error(e); }
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Debounce Render
|
|
130
|
-
let timer;
|
|
131
|
-
input.addEventListener('input', () => {
|
|
132
|
-
clearTimeout(timer);
|
|
133
|
-
timer = setTimeout(render, 300);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// Initial Render
|
|
137
|
-
render();
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// --- Resizer Logic ---
|
|
141
|
-
const resizer = document.getElementById('resizer');
|
|
142
|
-
const editorPane = document.getElementById('editorPane');
|
|
143
|
-
const workspace = document.getElementById('workspace');
|
|
144
|
-
let isResizing = false;
|
|
145
|
-
|
|
146
|
-
resizer.addEventListener('mousedown', (e) => {
|
|
147
|
-
isResizing = true;
|
|
148
|
-
resizer.classList.add('resizing');
|
|
149
|
-
preview.style.pointerEvents = 'none';
|
|
150
|
-
document.body.style.cursor = 'col-resize';
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
document.addEventListener('mousemove', (e) => {
|
|
154
|
-
if (!isResizing) return;
|
|
155
|
-
const containerWidth = workspace.offsetWidth;
|
|
156
|
-
const newEditorWidth = (e.clientX / containerWidth) * 100;
|
|
157
|
-
if (newEditorWidth > 15 && newEditorWidth < 85) {
|
|
158
|
-
editorPane.style.width = newEditorWidth + '%';
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
document.addEventListener('mouseup', () => {
|
|
163
|
-
if (isResizing) {
|
|
164
|
-
isResizing = false;
|
|
165
|
-
resizer.classList.remove('resizing');
|
|
166
|
-
preview.style.pointerEvents = 'auto';
|
|
167
|
-
document.body.style.cursor = 'default';
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// --- View Mode Logic (Desktop) ---
|
|
173
|
-
function setViewMode(mode) {
|
|
174
|
-
document.body.classList.remove('mode-split', 'mode-single');
|
|
175
|
-
document.body.classList.add('mode-' + mode);
|
|
176
|
-
|
|
177
|
-
document.getElementById('btn-split').classList.toggle('active', mode === 'split');
|
|
178
|
-
document.getElementById('btn-single').classList.toggle('active', mode === 'single');
|
|
179
|
-
|
|
180
|
-
document.getElementById('single-view-tabs').style.display = mode === 'single' ? 'flex' : 'none';
|
|
181
|
-
|
|
182
|
-
if (mode === 'single') {
|
|
183
|
-
switchSingleTab('editor');
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function switchSingleTab(tab) {
|
|
188
|
-
document.body.classList.remove('show-editor', 'show-preview');
|
|
189
|
-
document.body.classList.add('show-' + tab);
|
|
190
|
-
|
|
191
|
-
document.getElementById('btn-tab-edit').classList.toggle('active', tab === 'editor');
|
|
192
|
-
document.getElementById('btn-tab-prev').classList.toggle('active', tab === 'preview');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
// --- Mobile Logic ---
|
|
197
|
-
function setMobileTab(tab) {
|
|
198
|
-
document.body.classList.remove('mobile-tab-editor', 'mobile-tab-preview');
|
|
199
|
-
document.body.classList.add('mobile-tab-' + tab);
|
|
200
|
-
|
|
201
|
-
document.getElementById('mob-edit').classList.toggle('active', tab === 'editor');
|
|
202
|
-
document.getElementById('mob-prev').classList.toggle('active', tab === 'preview');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// --- Back Button Logic ---
|
|
206
|
-
if (window.history.length <= 1) {
|
|
207
|
-
backBtn.style.display = 'none';
|
|
208
|
-
} else {
|
|
209
|
-
backBtn.addEventListener('click', (e) => {
|
|
210
|
-
e.preventDefault();
|
|
211
|
-
window.history.back();
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
</script>
|
|
215
|
-
</body>
|
|
216
|
-
</html>
|
package/src/live/live.css
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
/* Source file from the docmd project — https://github.com/docmd-io/docmd */
|
|
2
|
-
|
|
3
|
-
:root {
|
|
4
|
-
--header-height: 50px;
|
|
5
|
-
--border-color: #e0e0e0;
|
|
6
|
-
--bg-color: #f9fafb;
|
|
7
|
-
--primary-color: #007bff;
|
|
8
|
-
--resizer-width: 8px
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
body {
|
|
12
|
-
margin: 0;
|
|
13
|
-
height: 100vh;
|
|
14
|
-
display: flex;
|
|
15
|
-
flex-direction: column;
|
|
16
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
17
|
-
overflow: hidden
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.top-bar {
|
|
21
|
-
height: var(--header-height);
|
|
22
|
-
background: #fff;
|
|
23
|
-
border-bottom: 1px solid var(--border-color);
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
padding: 0 1rem;
|
|
28
|
-
flex-shrink: 0
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.logo {
|
|
32
|
-
font-weight: 700;
|
|
33
|
-
font-size: 1.1rem;
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
gap: 12px
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.logo span {
|
|
40
|
-
background: var(--primary-color);
|
|
41
|
-
color: #fff;
|
|
42
|
-
padding: 2px 6px;
|
|
43
|
-
border-radius: 4px;
|
|
44
|
-
font-size: .75rem;
|
|
45
|
-
text-transform: uppercase
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.back-link {
|
|
49
|
-
display: flex;
|
|
50
|
-
align-items: center;
|
|
51
|
-
justify-content: center;
|
|
52
|
-
color: #666;
|
|
53
|
-
transition: color 0.2s, transform .2s;
|
|
54
|
-
text-decoration: none;
|
|
55
|
-
padding: 4px;
|
|
56
|
-
border-radius: 4px
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.back-link:hover {
|
|
60
|
-
color: var(--primary-color);
|
|
61
|
-
background: #f0f0f0;
|
|
62
|
-
transform: translateX(-2px)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.view-controls {
|
|
66
|
-
display: flex;
|
|
67
|
-
gap: 8px;
|
|
68
|
-
background: #f0f0f0;
|
|
69
|
-
padding: 3px;
|
|
70
|
-
border-radius: 6px
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.view-btn {
|
|
74
|
-
border: none;
|
|
75
|
-
background: transparent;
|
|
76
|
-
padding: 6px 10px;
|
|
77
|
-
border-radius: 4px;
|
|
78
|
-
cursor: pointer;
|
|
79
|
-
font-size: .85rem;
|
|
80
|
-
color: #666;
|
|
81
|
-
font-weight: 500
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.view-btn.active {
|
|
85
|
-
background: #fff;
|
|
86
|
-
color: #000;
|
|
87
|
-
box-shadow: 0 1px 3px #0000001a
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.workspace {
|
|
91
|
-
flex: 1;
|
|
92
|
-
display: flex;
|
|
93
|
-
position: relative;
|
|
94
|
-
overflow: hidden
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.pane {
|
|
98
|
-
height: 100%;
|
|
99
|
-
display: flex;
|
|
100
|
-
flex-direction: column;
|
|
101
|
-
min-width: 300px;
|
|
102
|
-
background: #fff
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.pane-header {
|
|
106
|
-
padding: 8px 16px;
|
|
107
|
-
font-size: .75rem;
|
|
108
|
-
font-weight: 600;
|
|
109
|
-
text-transform: uppercase;
|
|
110
|
-
color: #888;
|
|
111
|
-
background: var(--bg-color);
|
|
112
|
-
border-bottom: 1px solid var(--border-color);
|
|
113
|
-
flex-shrink: 0
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.editor-pane {
|
|
117
|
-
width: 50%
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
textarea#input {
|
|
121
|
-
flex: 1;
|
|
122
|
-
border: none;
|
|
123
|
-
resize: none;
|
|
124
|
-
padding: 20px;
|
|
125
|
-
font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
|
|
126
|
-
font-size: 14px;
|
|
127
|
-
line-height: 1.6;
|
|
128
|
-
outline: none;
|
|
129
|
-
background: var(--bg-color)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.preview-pane {
|
|
133
|
-
flex: 1;
|
|
134
|
-
background: #fff
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
iframe#preview {
|
|
138
|
-
width: 100%;
|
|
139
|
-
height: 100%;
|
|
140
|
-
border: none;
|
|
141
|
-
display: block
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.resizer {
|
|
145
|
-
width: var(--resizer-width);
|
|
146
|
-
background: var(--bg-color);
|
|
147
|
-
border-left: 1px solid var(--border-color);
|
|
148
|
-
border-right: 1px solid var(--border-color);
|
|
149
|
-
cursor: col-resize;
|
|
150
|
-
display: flex;
|
|
151
|
-
align-items: center;
|
|
152
|
-
justify-content: center;
|
|
153
|
-
transition: background .2s;
|
|
154
|
-
z-index: 10
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.resizer:hover,
|
|
158
|
-
.resizer.resizing {
|
|
159
|
-
background: #e0e0e0
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.resizer::after {
|
|
163
|
-
content: "||";
|
|
164
|
-
color: #aaa;
|
|
165
|
-
font-size: 10px;
|
|
166
|
-
letter-spacing: 1px
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
body.mode-single .resizer {
|
|
170
|
-
display: none
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
body.mode-single .pane {
|
|
174
|
-
width: 100% !important;
|
|
175
|
-
min-width: 0
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
body.mode-single .editor-pane {
|
|
179
|
-
display: none
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
body.mode-single .preview-pane {
|
|
183
|
-
display: none
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
body.mode-single.show-editor .editor-pane {
|
|
187
|
-
display: flex
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
body.mode-single.show-preview .preview-pane {
|
|
191
|
-
display: flex
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
@media (max-width: 768px) {
|
|
195
|
-
.desktop-only {
|
|
196
|
-
display: none !important
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
.resizer {
|
|
200
|
-
display: none !important
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.pane {
|
|
204
|
-
width: 100% !important
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
.editor-pane {
|
|
208
|
-
display: none
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.preview-pane {
|
|
212
|
-
display: none
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
body.mobile-tab-editor .editor-pane {
|
|
216
|
-
display: flex
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
body.mobile-tab-preview .preview-pane {
|
|
220
|
-
display: flex
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
.mobile-tabs {
|
|
224
|
-
display: flex !important;
|
|
225
|
-
position: fixed;
|
|
226
|
-
bottom: 0;
|
|
227
|
-
left: 0;
|
|
228
|
-
right: 0;
|
|
229
|
-
height: 50px;
|
|
230
|
-
background: #fff;
|
|
231
|
-
border-top: 1px solid var(--border-color);
|
|
232
|
-
z-index: 100
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.mobile-tab-btn {
|
|
236
|
-
flex: 1;
|
|
237
|
-
border: none;
|
|
238
|
-
background: transparent;
|
|
239
|
-
font-weight: 600;
|
|
240
|
-
color: #888;
|
|
241
|
-
cursor: pointer
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.mobile-tab-btn.active {
|
|
245
|
-
color: var(--primary-color);
|
|
246
|
-
border-top: 2px solid var(--primary-color)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
.workspace {
|
|
250
|
-
padding-bottom: 50px
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.mobile-tabs {
|
|
255
|
-
display: none
|
|
256
|
-
}
|
package/src/live/shims.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'buffer'; globalThis.Buffer = Buffer;
|
package/src/plugins/analytics.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Generate analytics scripts for a page
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
function generateAnalyticsScripts(config, pageData) {
|
|
8
|
-
let headScriptsHtml = '';
|
|
9
|
-
let bodyScriptsHtml = ''; // For scripts that need to be at the end of body
|
|
10
|
-
|
|
11
|
-
const analyticsConfig = config.plugins?.analytics || {}; // Assuming analytics is under plugins.analytics
|
|
12
|
-
|
|
13
|
-
// Google Analytics 4 (GA4)
|
|
14
|
-
if (analyticsConfig.googleV4?.measurementId) {
|
|
15
|
-
const id = analyticsConfig.googleV4.measurementId;
|
|
16
|
-
headScriptsHtml += `
|
|
17
|
-
<!-- Google Analytics GA4 -->
|
|
18
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=${id}"></script>
|
|
19
|
-
<script>
|
|
20
|
-
window.dataLayer = window.dataLayer || [];
|
|
21
|
-
function gtag(){dataLayer.push(arguments);}
|
|
22
|
-
gtag('js', new Date());
|
|
23
|
-
gtag('config', '${id}');
|
|
24
|
-
</script>\n`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Google Analytics Universal Analytics (UA) - Legacy
|
|
28
|
-
if (analyticsConfig.googleUA?.trackingId) {
|
|
29
|
-
const id = analyticsConfig.googleUA.trackingId;
|
|
30
|
-
headScriptsHtml += `
|
|
31
|
-
<!-- Google Universal Analytics (Legacy) -->
|
|
32
|
-
<script async src="https://www.google-analytics.com/analytics.js"></script>
|
|
33
|
-
<script>
|
|
34
|
-
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
|
35
|
-
ga('create', '${id}', 'auto');
|
|
36
|
-
ga('send', 'pageview');
|
|
37
|
-
</script>\n`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Example for a hypothetical future plugin requiring body script
|
|
41
|
-
// if (config.plugins?.someOtherAnalytics?.apiKey) {
|
|
42
|
-
// bodyScriptsHtml += `<script src="..."></script>\n`;
|
|
43
|
-
// }
|
|
44
|
-
|
|
45
|
-
return { headScriptsHtml, bodyScriptsHtml };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = { generateAnalyticsScripts };
|
package/src/plugins/seo.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Generate SEO meta tags for a page
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
function generateSeoMetaTags(config, pageData, relativePathToRoot) {
|
|
8
|
-
let metaTagsHtml = '';
|
|
9
|
-
const { frontmatter, outputPath } = pageData;
|
|
10
|
-
const seoFrontmatter = frontmatter.seo || {};
|
|
11
|
-
|
|
12
|
-
if (frontmatter.noindex || seoFrontmatter.noindex) {
|
|
13
|
-
metaTagsHtml += '<meta name="robots" content="noindex">\n';
|
|
14
|
-
return metaTagsHtml;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const siteTitle = config.siteTitle;
|
|
18
|
-
const pageTitle = frontmatter.title || 'Untitled';
|
|
19
|
-
const description = seoFrontmatter.description || frontmatter.description || config.plugins?.seo?.defaultDescription || '';
|
|
20
|
-
|
|
21
|
-
const siteUrl = config.siteUrl ? config.siteUrl.replace(/\/$/, '') : '';
|
|
22
|
-
const pageSegment = outputPath.replace(/index\.html$/, '').replace(/\.html$/, '');
|
|
23
|
-
const pageUrl = `${siteUrl}${pageSegment.startsWith('/') ? pageSegment : '/' + pageSegment}`;
|
|
24
|
-
|
|
25
|
-
metaTagsHtml += `<meta name="description" content="${description}">\n`;
|
|
26
|
-
|
|
27
|
-
const canonicalUrl = seoFrontmatter.permalink || frontmatter.permalink || seoFrontmatter.canonicalUrl || frontmatter.canonicalUrl || pageUrl;
|
|
28
|
-
metaTagsHtml += `<link rel="canonical" href="${canonicalUrl}">\n`;
|
|
29
|
-
|
|
30
|
-
// Open Graph
|
|
31
|
-
metaTagsHtml += `<meta property="og:title" content="${pageTitle} : ${siteTitle}">\n`;
|
|
32
|
-
metaTagsHtml += `<meta property="og:description" content="${description}">\n`;
|
|
33
|
-
metaTagsHtml += `<meta property="og:url" content="${pageUrl}">\n`;
|
|
34
|
-
metaTagsHtml += `<meta property="og:site_name" content="${config.plugins?.seo?.openGraph?.siteName || siteTitle}">\n`;
|
|
35
|
-
|
|
36
|
-
const ogImage = seoFrontmatter.image || frontmatter.image || seoFrontmatter.ogImage || frontmatter.ogImage || config.plugins?.seo?.openGraph?.defaultImage;
|
|
37
|
-
if (ogImage) {
|
|
38
|
-
const ogImageUrl = ogImage.startsWith('http') ? ogImage : `${siteUrl}${ogImage.startsWith('/') ? ogImage : '/' + ogImage}`;
|
|
39
|
-
metaTagsHtml += `<meta property="og:image" content="${ogImageUrl}">\n`;
|
|
40
|
-
}
|
|
41
|
-
metaTagsHtml += `<meta property="og:type" content="${seoFrontmatter.ogType || frontmatter.ogType || 'website'}">\n`;
|
|
42
|
-
|
|
43
|
-
// Twitter Card
|
|
44
|
-
const twitterCardType = seoFrontmatter.twitterCard || frontmatter.twitterCard || config.plugins?.seo?.twitter?.cardType || 'summary';
|
|
45
|
-
metaTagsHtml += `<meta name="twitter:card" content="${twitterCardType}">\n`;
|
|
46
|
-
if (config.plugins?.seo?.twitter?.siteUsername) {
|
|
47
|
-
metaTagsHtml += `<meta name="twitter:site" content="${config.plugins.seo.twitter.siteUsername}">\n`;
|
|
48
|
-
}
|
|
49
|
-
const twitterCreator = seoFrontmatter.twitterCreator || frontmatter.twitterCreator || config.plugins?.seo?.twitter?.creatorUsername;
|
|
50
|
-
if (twitterCreator) {
|
|
51
|
-
metaTagsHtml += `<meta name="twitter:creator" content="${twitterCreator}">\n`;
|
|
52
|
-
}
|
|
53
|
-
metaTagsHtml += `<meta name="twitter:title" content="${pageTitle} : ${siteTitle}">\n`;
|
|
54
|
-
metaTagsHtml += `<meta name="twitter:description" content="${description}">\n`;
|
|
55
|
-
if (ogImage) {
|
|
56
|
-
const twitterImageUrl = ogImage.startsWith('http') ? ogImage : `${siteUrl}${ogImage.startsWith('/') ? ogImage : '/' + ogImage}`;
|
|
57
|
-
metaTagsHtml += `<meta name="twitter:image" content="${twitterImageUrl}">\n`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Keywords
|
|
61
|
-
const keywords = seoFrontmatter.keywords || frontmatter.keywords;
|
|
62
|
-
if (keywords) {
|
|
63
|
-
const keywordsString = Array.isArray(keywords) ? keywords.join(', ') : keywords;
|
|
64
|
-
metaTagsHtml += `<meta name="keywords" content="${keywordsString}">\n`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// LD+JSON Structured Data
|
|
68
|
-
const ldJsonConfig = seoFrontmatter.ldJson || frontmatter.ldJson;
|
|
69
|
-
if (ldJsonConfig) {
|
|
70
|
-
try {
|
|
71
|
-
const baseLdJson = {
|
|
72
|
-
'@context': 'https://schema.org',
|
|
73
|
-
'@type': 'Article',
|
|
74
|
-
mainEntityOfPage: { '@type': 'WebPage', '@id': canonicalUrl },
|
|
75
|
-
headline: pageTitle,
|
|
76
|
-
description: description,
|
|
77
|
-
url: canonicalUrl,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
if (config.siteTitle) {
|
|
81
|
-
baseLdJson.publisher = { '@type': 'Organization', name: config.siteTitle };
|
|
82
|
-
if (config.logo?.light) {
|
|
83
|
-
baseLdJson.publisher.logo = {
|
|
84
|
-
'@type': 'ImageObject',
|
|
85
|
-
url: `${siteUrl}${config.logo.light.startsWith('/') ? config.logo.light : '/' + config.logo.light}`
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (ogImage) {
|
|
91
|
-
baseLdJson.image = `${siteUrl}${ogImage.startsWith('/') ? ogImage : '/' + ogImage}`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const finalLdJson = typeof ldJsonConfig === 'object' ? { ...baseLdJson, ...ldJsonConfig } : baseLdJson;
|
|
95
|
-
|
|
96
|
-
metaTagsHtml += `<script type="application/ld+json">\n`;
|
|
97
|
-
metaTagsHtml += `${JSON.stringify(finalLdJson, null, 2)}\n`;
|
|
98
|
-
metaTagsHtml += `</script>\n`;
|
|
99
|
-
} catch (e) {
|
|
100
|
-
console.error(`❌ Error generating LD+JSON: ${e.message}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return metaTagsHtml;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports = { generateSeoMetaTags };
|