sdocs-dev 1.3.0 → 1.3.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/package.json +9 -10
- package/public/sdocs-styles.js +162 -162
- package/public/brotli-wasm-v1.js +0 -518
- package/public/brotli_wasm_bg.wasm +0 -0
- package/public/css/layout.css +0 -240
- package/public/css/mobile.css +0 -196
- package/public/css/panel.css +0 -393
- package/public/css/rendered.css +0 -478
- package/public/css/tokens.css +0 -116
- package/public/css/write.css +0 -128
- package/public/fonts/inter-400.woff2 +0 -0
- package/public/fonts/inter-500.woff2 +0 -0
- package/public/fonts/inter-600.woff2 +0 -0
- package/public/images/examples.png +0 -0
- package/public/index.html +0 -694
- package/public/sdoc.md +0 -542
- package/public/sdocs-app.js +0 -812
- package/public/sdocs-charts.js +0 -905
- package/public/sdocs-controls.js +0 -354
- package/public/sdocs-export.js +0 -1090
- package/public/sdocs-state.js +0 -73
- package/public/sdocs-theme.js +0 -262
- package/public/sdocs-write.js +0 -740
- package/public/sw.js +0 -110
- package/public/vendor/marked.min.js +0 -6
- package/public/vendor/purify.min.js +0 -3
- package/server.js +0 -176
package/public/sdocs-state.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// sdocs-state.js — Shared mutable state namespace
|
|
2
|
-
// All modules read/write through window.SDocs
|
|
3
|
-
(function () {
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
window.SDocs = {
|
|
7
|
-
// Document state
|
|
8
|
-
currentBody: '',
|
|
9
|
-
currentMeta: {},
|
|
10
|
-
|
|
11
|
-
// Runtime-only metadata (path, fullPath) passed via &local= URL param.
|
|
12
|
-
// Stripped from the URL on load so it isn't in anything the user copies/shares.
|
|
13
|
-
localMeta: {},
|
|
14
|
-
|
|
15
|
-
// Per-doc overrides for the file-info card. Set from `styles.fileinfo` in
|
|
16
|
-
// YAML front matter; emitted back via collectStyles so they round-trip.
|
|
17
|
-
fileinfoStyles: {},
|
|
18
|
-
|
|
19
|
-
// Per-theme color state
|
|
20
|
-
activeTheme: 'light',
|
|
21
|
-
themeColors: { light: {}, dark: {} },
|
|
22
|
-
themeOverridden: { light: new Set(), dark: new Set() },
|
|
23
|
-
|
|
24
|
-
// DOM references
|
|
25
|
-
renderedEl: document.getElementById('rendered'),
|
|
26
|
-
rawEl: document.getElementById('raw'),
|
|
27
|
-
writeEl: null,
|
|
28
|
-
|
|
29
|
-
// Mode tracking
|
|
30
|
-
currentMode: 'read',
|
|
31
|
-
|
|
32
|
-
// Sync flags
|
|
33
|
-
_syncing: false,
|
|
34
|
-
_isDefaultState: true,
|
|
35
|
-
_hashTimer: null,
|
|
36
|
-
_rawSyncTimer: null,
|
|
37
|
-
_writeSyncTimer: null,
|
|
38
|
-
|
|
39
|
-
// Cross-module functions (registered by defining module)
|
|
40
|
-
// Theme: toggleTheme, getThemeDefaults, getColorDefault, getStandaloneDefault,
|
|
41
|
-
// loadGoogleFont, updateDefaultColors, GOOGLE_FONTS,
|
|
42
|
-
// switchThemeAndUpdate, saveCurrentThemeColors, loadThemeColors
|
|
43
|
-
// Controls: setColorValue, readAllControlValues, collectStyles,
|
|
44
|
-
// applyStylesFromMeta, resetAllStyles, STANDALONE_COLOR_IDS
|
|
45
|
-
// App: syncAll, setStatus, setMode, render, loadText
|
|
46
|
-
// Write: enterWriteMode, exitWriteMode
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// Backwards compat: S.overriddenColors delegates to active theme's set
|
|
50
|
-
Object.defineProperty(SDocs, 'overriddenColors', {
|
|
51
|
-
get: function() { return SDocs.themeOverridden[SDocs.activeTheme]; },
|
|
52
|
-
set: function(v) { SDocs.themeOverridden[SDocs.activeTheme] = v; },
|
|
53
|
-
enumerable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
SDocs.contentAreaEl = document.getElementById('content-area');
|
|
58
|
-
|
|
59
|
-
SDocs.setStyleVar = function(cssVar, value) {
|
|
60
|
-
SDocs.renderedEl.style.setProperty(cssVar, value);
|
|
61
|
-
if (SDocs.writeEl) SDocs.writeEl.style.setProperty(cssVar, value);
|
|
62
|
-
// File-info card is a sibling of #rendered, so it doesn't inherit vars set
|
|
63
|
-
// on #rendered. Mirror the relevant block-cascade vars to it directly.
|
|
64
|
-
var ficEl = document.getElementById('file-info-card');
|
|
65
|
-
if (ficEl && /^--md-(fic-|block-)/.test(cssVar)) {
|
|
66
|
-
ficEl.style.setProperty(cssVar, value);
|
|
67
|
-
}
|
|
68
|
-
if (cssVar === '--md-bg') {
|
|
69
|
-
SDocs.contentAreaEl.style.setProperty('background-color', value);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
})();
|
package/public/sdocs-theme.js
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
// sdocs-theme.js — Theme, fonts, and dark mode
|
|
2
|
-
(function () {
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
var S = SDocs;
|
|
6
|
-
|
|
7
|
-
// ── Google Fonts ──────────────────────────────────
|
|
8
|
-
|
|
9
|
-
const GOOGLE_FONTS = [
|
|
10
|
-
'Inter', 'Roboto', 'Open Sans', 'Lato', 'Montserrat', 'Source Sans 3',
|
|
11
|
-
'Oswald', 'Raleway', 'Poppins', 'Merriweather', 'Ubuntu',
|
|
12
|
-
'Nunito', 'Playfair Display', 'Roboto Slab', 'PT Sans', 'Lora',
|
|
13
|
-
'Mulish', 'Noto Sans', 'Rubik', 'Dosis',
|
|
14
|
-
'Josefin Sans', 'PT Serif', 'Libre Franklin', 'Crimson Text'
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
const loadedFonts = new Set(['Inter']);
|
|
18
|
-
|
|
19
|
-
function loadGoogleFont(family) {
|
|
20
|
-
if (loadedFonts.has(family)) return;
|
|
21
|
-
loadedFonts.add(family);
|
|
22
|
-
const link = document.createElement('link');
|
|
23
|
-
link.rel = 'stylesheet';
|
|
24
|
-
link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}:wght@400;600;700&display=swap`;
|
|
25
|
-
document.head.appendChild(link);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function populateFontSelect(sel, includeInherit) {
|
|
29
|
-
if (includeInherit) {
|
|
30
|
-
const opt = document.createElement('option');
|
|
31
|
-
opt.value = 'inherit';
|
|
32
|
-
opt.textContent = '— Same as body —';
|
|
33
|
-
sel.appendChild(opt);
|
|
34
|
-
}
|
|
35
|
-
GOOGLE_FONTS.forEach(f => {
|
|
36
|
-
const opt = document.createElement('option');
|
|
37
|
-
opt.value = `'${f}', sans-serif`;
|
|
38
|
-
opt.textContent = f;
|
|
39
|
-
sel.appendChild(opt);
|
|
40
|
-
});
|
|
41
|
-
[['Georgia, serif','Georgia'],['Times New Roman, serif','Times New Roman'],
|
|
42
|
-
['system-ui, sans-serif','System UI']].forEach(([v,l]) => {
|
|
43
|
-
const opt = document.createElement('option');
|
|
44
|
-
opt.value = v; opt.textContent = l;
|
|
45
|
-
sel.appendChild(opt);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ── Dark mode ──────────────────────────────────
|
|
50
|
-
|
|
51
|
-
const LIGHT_DEFAULTS = {
|
|
52
|
-
bgColor: '#ffffff',
|
|
53
|
-
colorDefault: '#1c1917',
|
|
54
|
-
codeBg: '#f4f1ed',
|
|
55
|
-
codeColor: '#6b21a8',
|
|
56
|
-
linkColor: '#2563eb',
|
|
57
|
-
bqBorderColor: '#2563eb',
|
|
58
|
-
bqBg: '#f7f5f2',
|
|
59
|
-
bqColor: '#6b6560',
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const DARK_DEFAULTS = {
|
|
63
|
-
bgColor: '#2c2a26',
|
|
64
|
-
colorDefault: '#e7e5e2',
|
|
65
|
-
codeBg: '#1a1816',
|
|
66
|
-
codeColor: '#b8a99a',
|
|
67
|
-
linkColor: '#60a5fa',
|
|
68
|
-
bqBorderColor: '#60a5fa',
|
|
69
|
-
bqBg: '#252320',
|
|
70
|
-
bqColor: '#a8a29e',
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
function getThemeDefaults() {
|
|
74
|
-
return document.documentElement.dataset.theme === 'dark' ? DARK_DEFAULTS : LIGHT_DEFAULTS;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function getThemeDefaultsFor(theme) {
|
|
78
|
-
return theme === 'dark' ? DARK_DEFAULTS : LIGHT_DEFAULTS;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function getColorDefault() {
|
|
82
|
-
return getThemeDefaults().colorDefault;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function getPreferredTheme() {
|
|
86
|
-
const stored = localStorage.getItem('sdocs-theme');
|
|
87
|
-
if (stored === 'dark' || stored === 'light') return stored;
|
|
88
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const SUN_ICON = '<circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>';
|
|
92
|
-
const MOON_ICON = '<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" stroke-width="1.5"/>';
|
|
93
|
-
|
|
94
|
-
function updateThemeIcon(theme) {
|
|
95
|
-
const icon = document.getElementById('icon-theme');
|
|
96
|
-
if (icon) icon.innerHTML = theme === 'dark' ? SUN_ICON : MOON_ICON;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function applyTheme(theme) {
|
|
100
|
-
document.documentElement.dataset.theme = theme;
|
|
101
|
-
S.activeTheme = theme;
|
|
102
|
-
localStorage.setItem('sdocs-theme', theme);
|
|
103
|
-
updateThemeIcon(theme);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ── Per-theme color save/load ──────────────────────
|
|
107
|
-
|
|
108
|
-
function saveCurrentThemeColors() {
|
|
109
|
-
var theme = S.activeTheme;
|
|
110
|
-
var colors = S.themeColors[theme];
|
|
111
|
-
// Save all 13 color control values
|
|
112
|
-
SDocStyles.ALL_COLOR_IDS.forEach(function(ctrlId) {
|
|
113
|
-
var el = document.getElementById(ctrlId);
|
|
114
|
-
if (el) colors[ctrlId] = el.value;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function loadThemeColors(theme) {
|
|
119
|
-
var colors = S.themeColors[theme];
|
|
120
|
-
var overridden = S.themeOverridden[theme];
|
|
121
|
-
var defaults = getThemeDefaultsFor(theme);
|
|
122
|
-
|
|
123
|
-
// Cascade roots: text color and block bg/text
|
|
124
|
-
var cascadeRoots = [
|
|
125
|
-
['ctrl-color', defaults.colorDefault],
|
|
126
|
-
['ctrl-block-bg', defaults.codeBg],
|
|
127
|
-
['ctrl-block-text', defaults.bqColor],
|
|
128
|
-
];
|
|
129
|
-
cascadeRoots.forEach(function(pair) {
|
|
130
|
-
var id = pair[0], def = pair[1];
|
|
131
|
-
if (overridden.has(id)) {
|
|
132
|
-
S.setColorValue(id, colors[id], true);
|
|
133
|
-
} else {
|
|
134
|
-
S.setColorValue(id, def, false);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// Then cascade children that are overridden (overrides the parent cascade)
|
|
139
|
-
var cascadeIds = Object.keys(SDocStyles.COLOR_VAR_MAP);
|
|
140
|
-
cascadeIds.forEach(function(ctrlId) {
|
|
141
|
-
if (ctrlId === 'ctrl-color' || ctrlId === 'ctrl-block-bg' || ctrlId === 'ctrl-block-text') return;
|
|
142
|
-
if (overridden.has(ctrlId)) {
|
|
143
|
-
S.setColorValue(ctrlId, colors[ctrlId], true);
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Standalone colors (not in cascade)
|
|
148
|
-
var standaloneMap = {
|
|
149
|
-
'ctrl-bg-color': defaults.bgColor,
|
|
150
|
-
'ctrl-link-color': defaults.linkColor,
|
|
151
|
-
'ctrl-bq-border-color': defaults.bqBorderColor,
|
|
152
|
-
};
|
|
153
|
-
for (var ctrlId in standaloneMap) {
|
|
154
|
-
var el = document.getElementById(ctrlId);
|
|
155
|
-
if (!el) continue;
|
|
156
|
-
if (overridden.has(ctrlId)) {
|
|
157
|
-
el.value = colors[ctrlId];
|
|
158
|
-
} else {
|
|
159
|
-
el.value = standaloneMap[ctrlId];
|
|
160
|
-
}
|
|
161
|
-
var allVals = S.readAllControlValues();
|
|
162
|
-
SDocStyles.controlToCssVars(ctrlId, el.value, allVals)
|
|
163
|
-
.forEach(function(a) { S.setStyleVar(a.cssVar, a.value); });
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function updateThemeTabs(theme) {
|
|
168
|
-
var lightTab = document.getElementById('theme-tab-light');
|
|
169
|
-
var darkTab = document.getElementById('theme-tab-dark');
|
|
170
|
-
if (lightTab) lightTab.classList.toggle('active', theme === 'light');
|
|
171
|
-
if (darkTab) darkTab.classList.toggle('active', theme === 'dark');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function switchThemeAndUpdate(theme) {
|
|
175
|
-
if (theme === S.activeTheme) return;
|
|
176
|
-
saveCurrentThemeColors();
|
|
177
|
-
applyTheme(theme);
|
|
178
|
-
loadThemeColors(theme);
|
|
179
|
-
updateThemeTabs(theme);
|
|
180
|
-
S.syncAll('controls');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function toggleTheme() {
|
|
184
|
-
var current = S.activeTheme;
|
|
185
|
-
switchThemeAndUpdate(current === 'dark' ? 'light' : 'dark');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function updateDefaultColors() {
|
|
189
|
-
const defaults = getThemeDefaults();
|
|
190
|
-
if (!S.overriddenColors) return;
|
|
191
|
-
if (!S.overriddenColors.has('ctrl-color')) {
|
|
192
|
-
S.setColorValue('ctrl-color', defaults.colorDefault, false);
|
|
193
|
-
}
|
|
194
|
-
// Update standalone color defaults for reset buttons
|
|
195
|
-
const standaloneMap = {
|
|
196
|
-
'ctrl-bg-color': defaults.bgColor,
|
|
197
|
-
'ctrl-link-color': defaults.linkColor,
|
|
198
|
-
'ctrl-code-bg': defaults.codeBg,
|
|
199
|
-
'ctrl-code-color': defaults.codeColor,
|
|
200
|
-
'ctrl-bq-border-color': defaults.bqBorderColor,
|
|
201
|
-
'ctrl-bq-bg': defaults.bqBg,
|
|
202
|
-
'ctrl-bq-color': defaults.bqColor,
|
|
203
|
-
};
|
|
204
|
-
for (const [ctrlId, val] of Object.entries(standaloneMap)) {
|
|
205
|
-
if (!S.overriddenColors.has(ctrlId)) {
|
|
206
|
-
const el = document.getElementById(ctrlId);
|
|
207
|
-
if (el) {
|
|
208
|
-
el.value = val;
|
|
209
|
-
const allVals = S.readAllControlValues();
|
|
210
|
-
SDocStyles.controlToCssVars(ctrlId, val, allVals)
|
|
211
|
-
.forEach(a => S.setStyleVar(a.cssVar, a.value));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
S.syncAll('controls');
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function getStandaloneDefault(ctrlId) {
|
|
219
|
-
const d = getThemeDefaults();
|
|
220
|
-
const map = {
|
|
221
|
-
'ctrl-bg-color': d.bgColor,
|
|
222
|
-
'ctrl-link-color': d.linkColor,
|
|
223
|
-
'ctrl-bq-border-color': d.bqBorderColor,
|
|
224
|
-
'ctrl-block-bg': d.codeBg,
|
|
225
|
-
'ctrl-block-text': d.bqColor,
|
|
226
|
-
'ctrl-chart-accent': '#3b82f6',
|
|
227
|
-
};
|
|
228
|
-
return map[ctrlId];
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// ── Init at load time ──────────────────────────────────
|
|
232
|
-
|
|
233
|
-
var initTheme = getPreferredTheme();
|
|
234
|
-
applyTheme(initTheme);
|
|
235
|
-
|
|
236
|
-
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
|
|
237
|
-
if (!localStorage.getItem('sdocs-theme')) {
|
|
238
|
-
switchThemeAndUpdate(e.matches ? 'dark' : 'light');
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
populateFontSelect(document.getElementById('ctrl-font-family'), false);
|
|
243
|
-
document.getElementById('ctrl-font-family').value = "'Inter', sans-serif";
|
|
244
|
-
populateFontSelect(document.getElementById('ctrl-h-font-family'), true);
|
|
245
|
-
|
|
246
|
-
// ── Register on SDocs for cross-module access ──────────
|
|
247
|
-
|
|
248
|
-
S.GOOGLE_FONTS = GOOGLE_FONTS;
|
|
249
|
-
S.loadGoogleFont = loadGoogleFont;
|
|
250
|
-
S.getThemeDefaults = getThemeDefaults;
|
|
251
|
-
S.getThemeDefaultsFor = getThemeDefaultsFor;
|
|
252
|
-
S.getColorDefault = getColorDefault;
|
|
253
|
-
S.getStandaloneDefault = getStandaloneDefault;
|
|
254
|
-
S.updateDefaultColors = updateDefaultColors;
|
|
255
|
-
S.toggleTheme = toggleTheme;
|
|
256
|
-
S.switchThemeAndUpdate = switchThemeAndUpdate;
|
|
257
|
-
S.getPreferredTheme = getPreferredTheme;
|
|
258
|
-
S.saveCurrentThemeColors = saveCurrentThemeColors;
|
|
259
|
-
S.loadThemeColors = loadThemeColors;
|
|
260
|
-
S.updateThemeTabs = updateThemeTabs;
|
|
261
|
-
|
|
262
|
-
})();
|