sdocs-dev 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,354 +0,0 @@
1
- // sdocs-controls.js — CSS variable management and control wiring
2
- (function () {
3
- 'use strict';
4
-
5
- var S = SDocs;
6
-
7
- // ── CSS var updates ──────────────────────────────────
8
-
9
- function applyControlToCss(id) {
10
- var el = document.getElementById(id);
11
- if (!el) return;
12
- var v = el.value;
13
-
14
- if (id === 'ctrl-font-family' || id === 'ctrl-h-font-family') {
15
- var name = v.replace(/['"]/g,'').split(',')[0].trim();
16
- if (S.GOOGLE_FONTS.includes(name)) S.loadGoogleFont(name);
17
- }
18
-
19
- var allVals = readAllControlValues();
20
- SDocStyles.controlToCssVars(id, v, allVals)
21
- .forEach(function(a) { S.setStyleVar(a.cssVar, a.value); });
22
- S.syncAll('controls');
23
- }
24
-
25
- function readAllControlValues() {
26
- var vals = {};
27
- Object.keys(SDocStyles.CTRL_CSS_MAP).forEach(function(id) {
28
- var el = document.getElementById(id);
29
- if (el) vals[id] = el.value;
30
- });
31
- Object.keys(SDocStyles.COLOR_VAR_MAP).forEach(function(id) {
32
- var el = document.getElementById(id);
33
- if (el) vals[id] = el.value;
34
- });
35
- return vals;
36
- }
37
-
38
- function syncRangeAndNumber(rangeId, numId) {
39
- var r = document.getElementById(rangeId);
40
- var n = document.getElementById(numId);
41
- r.addEventListener('input', function() { n.value = r.value; applyControlToCss(numId); });
42
- n.addEventListener('input', function() { r.value = n.value; applyControlToCss(numId); });
43
- }
44
-
45
- SDocStyles.RANGE_NUM_PAIRS.forEach(function(pair) { syncRangeAndNumber(pair[0], pair[1]); });
46
-
47
- var STANDALONE_COLOR_IDS = new Set(SDocStyles.STANDALONE_COLOR_IDS);
48
-
49
- [
50
- 'ctrl-font-family','ctrl-h-font-family',
51
- 'ctrl-h1-weight','ctrl-h2-weight','ctrl-h3-weight','ctrl-h4-weight',
52
- 'ctrl-bg-color','ctrl-link-color','ctrl-link-decoration',
53
- 'ctrl-code-font',
54
- 'ctrl-bq-border-color',
55
- 'ctrl-chart-accent','ctrl-chart-palette',
56
- ].forEach(function(id) {
57
- var handler = function() { if (STANDALONE_COLOR_IDS.has(id)) S.overriddenColors.add(id); applyControlToCss(id); S.syncAll('controls'); };
58
- document.getElementById(id).addEventListener('input', handler);
59
- document.getElementById(id).addEventListener('change', handler);
60
- });
61
-
62
- // ── Color cascade ──────────────────────────────────
63
-
64
- var COLOR_VAR = SDocStyles.COLOR_VAR_MAP;
65
- var COLOR_CHILDREN = SDocStyles.COLOR_CASCADE;
66
-
67
- function setColorValue(ctrlId, value, userAction) {
68
- if (userAction) S.overriddenColors.add(ctrlId);
69
- var varName = COLOR_VAR[ctrlId];
70
- if (Array.isArray(varName)) {
71
- varName.forEach(function(v) { S.setStyleVar(v, value); });
72
- } else {
73
- S.setStyleVar(varName, value);
74
- }
75
- var ctrl = document.getElementById(ctrlId);
76
- if (ctrl) ctrl.value = value;
77
- var children = COLOR_CHILDREN[ctrlId] || [];
78
- for (var i = 0; i < children.length; i++) {
79
- if (!S.overriddenColors.has(children[i])) {
80
- setColorValue(children[i], value, false);
81
- }
82
- }
83
- // Refresh charts when block/chart colors change
84
- if (S.refreshChartColors && (ctrlId === 'ctrl-chart-bg' || ctrlId === 'ctrl-chart-text' ||
85
- ctrlId === 'ctrl-block-bg' || ctrlId === 'ctrl-block-text')) {
86
- S.refreshChartColors();
87
- }
88
- }
89
-
90
- function findParent(ctrlId) {
91
- for (var pid in COLOR_CHILDREN) {
92
- if (COLOR_CHILDREN[pid].indexOf(ctrlId) !== -1) return pid;
93
- }
94
- return null;
95
- }
96
-
97
- function resetColorValue(ctrlId) {
98
- S.overriddenColors.delete(ctrlId);
99
- var parent = findParent(ctrlId);
100
- var value;
101
- if (!parent) {
102
- // Cascade root: use theme default
103
- value = ctrlId === 'ctrl-color' ? S.getColorDefault() : S.getStandaloneDefault(ctrlId);
104
- } else {
105
- var parentEl = document.getElementById(parent);
106
- value = parentEl ? parentEl.value : S.getColorDefault();
107
- }
108
- setColorValue(ctrlId, value, false);
109
- }
110
-
111
- Object.keys(COLOR_VAR).forEach(function(ctrlId) {
112
- var el = document.getElementById(ctrlId);
113
- if (!el) return;
114
- var handler = function() { setColorValue(ctrlId, el.value, true); S.syncAll('controls'); };
115
- el.addEventListener('input', handler);
116
- el.addEventListener('change', handler);
117
- });
118
-
119
- // Cascade color reset buttons
120
- document.getElementById('reset-color').addEventListener('click', function() { S.overriddenColors.delete('ctrl-color'); setColorValue('ctrl-color', S.getColorDefault(), false); S.syncAll('controls'); });
121
- ['ctrl-h-color','ctrl-h1-color','ctrl-h2-color','ctrl-h3-color','ctrl-h4-color','ctrl-p-color','ctrl-list-color'].forEach(function(ctrlId) {
122
- var btn = document.getElementById('reset-' + ctrlId.replace('ctrl-', ''));
123
- if (btn) btn.addEventListener('click', function() { resetColorValue(ctrlId); S.syncAll('controls'); });
124
- });
125
-
126
- // Block cascade resets
127
- ['ctrl-block-bg','ctrl-block-text','ctrl-code-bg','ctrl-code-color','ctrl-bq-bg','ctrl-bq-color','ctrl-chart-bg','ctrl-chart-text'].forEach(function(ctrlId) {
128
- var btnId = 'reset-' + ctrlId.replace('ctrl-', '');
129
- var btn = document.getElementById(btnId);
130
- if (btn) btn.addEventListener('click', function() { resetColorValue(ctrlId); S.syncAll('controls'); });
131
- });
132
-
133
- ['ctrl-bg-color','ctrl-link-color','ctrl-bq-border-color','ctrl-chart-accent'].forEach(function(ctrlId) {
134
- var btnId = 'reset-' + ctrlId.replace('ctrl-', '');
135
- document.getElementById(btnId).addEventListener('click', function() {
136
- var defaultVal = S.getStandaloneDefault(ctrlId);
137
- var el = document.getElementById(ctrlId);
138
- S.overriddenColors.delete(ctrlId);
139
- el.value = defaultVal;
140
- var assignments = SDocStyles.controlToCssVars(ctrlId, defaultVal, readAllControlValues());
141
- assignments.forEach(function(a) { S.setStyleVar(a.cssVar, a.value); });
142
- S.syncAll('controls');
143
- });
144
- });
145
-
146
- // ── Apply styles from meta → controls ──────────────────
147
-
148
- function setControlValue(id, val) {
149
- if (val === undefined || val === null) return;
150
- var el = document.getElementById(id);
151
- if (!el) return;
152
- el.value = val;
153
- var rangeId = id.replace(/-num$/, '-range');
154
- var rng = document.getElementById(rangeId);
155
- if (rng) rng.value = val;
156
- applyControlToCss(id);
157
- }
158
-
159
- function applyStylesFromMeta(s) {
160
- if (!s) return;
161
- // Suppress syncAll during batch updates to avoid capturing partial state
162
- var wasSyncing = S._syncing;
163
- S._syncing = true;
164
-
165
- var result = SDocStyles.stylesToControls(s);
166
- var controls = result.controls;
167
-
168
- // Font family selects need special handling to match bare names against <option> values
169
- [['fontFamily', 'ctrl-font-family'], ['headers.fontFamily', 'ctrl-h-font-family']].forEach(function(pair) {
170
- var styleKey = pair[0], ctrlId = pair[1];
171
- var fontName = styleKey === 'fontFamily' ? s.fontFamily : (s.headers || {}).fontFamily;
172
- if (fontName) {
173
- var sel = document.getElementById(ctrlId);
174
- var match = [].slice.call(sel.options).find(function(o) {
175
- return o.value.replace(/['"]/g,'').split(',')[0].trim() === fontName ||
176
- o.textContent === fontName;
177
- });
178
- if (match) { sel.value = match.value; applyControlToCss(ctrlId); }
179
- }
180
- });
181
-
182
- Object.keys(controls).forEach(function(id) {
183
- if (id === 'ctrl-font-family' || id === 'ctrl-h-font-family') return;
184
- if (SDocStyles.COLOR_VAR_MAP[id]) return;
185
- setControlValue(id, controls[id]);
186
- });
187
-
188
- // Top-level colors = light theme. dark: block = explicit dark overrides.
189
- var lightOverridden = S.themeOverridden.light;
190
- var lightColors = S.themeColors.light;
191
- var newOverridden = result.overriddenColors;
192
-
193
- lightOverridden.clear();
194
- S.themeOverridden.dark.clear();
195
-
196
- newOverridden.forEach(function(id) {
197
- lightOverridden.add(id);
198
- lightColors[id] = controls[id];
199
- });
200
-
201
- // Also store standalone colors from legacy format into light theme
202
- var legacyStandalone = [];
203
- if (s.background) legacyStandalone.push(['ctrl-bg-color', s.background]);
204
- if (s.link && s.link.color) legacyStandalone.push(['ctrl-link-color', s.link.color]);
205
- if (s.code) {
206
- if (s.code.background) legacyStandalone.push(['ctrl-code-bg', s.code.background]);
207
- if (s.code.color) legacyStandalone.push(['ctrl-code-color', s.code.color]);
208
- }
209
- if (s.blocks) {
210
- if (s.blocks.background) legacyStandalone.push(['ctrl-block-bg', s.blocks.background]);
211
- if (s.blocks.color) legacyStandalone.push(['ctrl-block-text', s.blocks.color]);
212
- }
213
- if (s.blockquote) {
214
- if (s.blockquote.borderColor) legacyStandalone.push(['ctrl-bq-border-color', s.blockquote.borderColor]);
215
- if (s.blockquote.background) legacyStandalone.push(['ctrl-bq-bg', s.blockquote.background]);
216
- if (s.blockquote.color) legacyStandalone.push(['ctrl-bq-color', s.blockquote.color]);
217
- }
218
- if (s.chart) {
219
- if (s.chart.background) legacyStandalone.push(['ctrl-chart-bg', s.chart.background]);
220
- if (s.chart.textColor) legacyStandalone.push(['ctrl-chart-text', s.chart.textColor]);
221
- }
222
-
223
- // File-info card overrides (no UI controls — driven entirely by YAML).
224
- S.fileinfoStyles = {};
225
- if (s.fileinfo) {
226
- if (s.fileinfo.background) {
227
- S.fileinfoStyles.background = s.fileinfo.background;
228
- S.setStyleVar('--md-fic-bg', s.fileinfo.background);
229
- }
230
- if (s.fileinfo.color) {
231
- S.fileinfoStyles.color = s.fileinfo.color;
232
- S.setStyleVar('--md-fic-text', s.fileinfo.color);
233
- }
234
- }
235
- legacyStandalone.forEach(function(pair) {
236
- lightOverridden.add(pair[0]);
237
- lightColors[pair[0]] = pair[1];
238
- });
239
-
240
- // Auto-generate dark theme from light colors via lightness inversion
241
- var darkOverridden = S.themeOverridden.dark;
242
- var darkColors = S.themeColors.dark;
243
-
244
- // Parse explicit dark: overrides from YAML and persist for serialization
245
- var explicitDark = s.dark ? SDocStyles.parseDarkBlock(s.dark) : {};
246
- S._explicitDarkOverrides = s.dark || null;
247
-
248
- // For every light color, auto-generate dark unless explicitly overridden
249
- lightOverridden.forEach(function(id) {
250
- if (explicitDark[id]) {
251
- darkOverridden.add(id);
252
- darkColors[id] = explicitDark[id];
253
- } else {
254
- darkOverridden.add(id);
255
- darkColors[id] = SDocStyles.invertLightness(lightColors[id]);
256
- }
257
- });
258
-
259
- // Also apply any dark: colors that weren't in light (e.g. dark-only overrides)
260
- Object.keys(explicitDark).forEach(function(id) {
261
- if (!darkOverridden.has(id)) {
262
- darkOverridden.add(id);
263
- darkColors[id] = explicitDark[id];
264
- }
265
- });
266
-
267
- // Now apply the active theme's colors
268
- S._syncing = wasSyncing;
269
- S.loadThemeColors(S.activeTheme);
270
- }
271
-
272
- function collectStyles() {
273
- S.saveCurrentThemeColors();
274
- // Always emit top-level colors (light) via the simple collector
275
- var styles = SDocStyles.collectStyles(readAllControlValues(), S.overriddenColors);
276
-
277
- // Emit dark: block for any explicitly set dark overrides
278
- // (don't emit auto-inverted values — those are generated on load)
279
- if (S._explicitDarkOverrides && Object.keys(S._explicitDarkOverrides).length > 0) {
280
- var darkBlock = SDocStyles.parseDarkBlock(S._explicitDarkOverrides);
281
- // parseDarkBlock expects the YAML format, but _explicitDarkOverrides IS the YAML dark: object
282
- styles.dark = S._explicitDarkOverrides;
283
- }
284
-
285
- // File-info card overrides (no UI controls; round-trip from YAML)
286
- if (S.fileinfoStyles && Object.keys(S.fileinfoStyles).length > 0) {
287
- styles.fileinfo = Object.assign({}, S.fileinfoStyles);
288
- }
289
-
290
- return styles;
291
- }
292
-
293
- // ── Reset all styles ──────────────────────────────────
294
-
295
- function resetAllStyles() {
296
- // Clear both theme states
297
- S.themeOverridden.light.clear();
298
- S.themeOverridden.dark.clear();
299
- S.themeColors.light = {};
300
- S.themeColors.dark = {};
301
- // Clear file-info-card overrides and the CSS vars they set
302
- S.fileinfoStyles = {};
303
- S.setStyleVar('--md-fic-bg', '');
304
- S.setStyleVar('--md-fic-text', '');
305
-
306
- setColorValue('ctrl-color', S.getColorDefault(), false);
307
- // Reset block cascade roots to theme defaults
308
- setColorValue('ctrl-block-bg', S.getStandaloneDefault('ctrl-block-bg') || '#f4f1ed', false);
309
- setColorValue('ctrl-block-text', S.getStandaloneDefault('ctrl-block-text') || '#6b6560', false);
310
- // Set standalone color controls to theme-appropriate defaults
311
- STANDALONE_COLOR_IDS.forEach(function(ctrlId) {
312
- var el = document.getElementById(ctrlId);
313
- if (el) el.value = S.getStandaloneDefault(ctrlId);
314
- });
315
- document.querySelectorAll('#right input, #right select').forEach(function(el) {
316
- if (STANDALONE_COLOR_IDS.has(el.id)) return; // already set above
317
- if (el.type === 'range' || el.type === 'number') el.value = el.defaultValue;
318
- else if (el.tagName === 'SELECT') el.selectedIndex = [].slice.call(el.options).findIndex(function(o) { return o.defaultSelected; });
319
- else if (el.type === 'color') el.value = el.defaultValue;
320
- });
321
- ['ctrl-bg-color','ctrl-font-family','ctrl-base-size-num','ctrl-line-height-num',
322
- 'ctrl-h-font-family','ctrl-h-scale-num','ctrl-h-mb-num',
323
- 'ctrl-h1-size-num','ctrl-h1-weight','ctrl-h2-size-num','ctrl-h2-weight',
324
- 'ctrl-h3-size-num','ctrl-h3-weight','ctrl-h4-size-num','ctrl-h4-weight',
325
- 'ctrl-p-lh-num','ctrl-p-mb-num',
326
- 'ctrl-link-color','ctrl-link-decoration',
327
- 'ctrl-code-font',
328
- 'ctrl-bq-border-color','ctrl-bq-bw-num','ctrl-bq-size-num',
329
- 'ctrl-list-spacing-num','ctrl-list-indent-num',
330
- 'ctrl-chart-accent','ctrl-chart-palette',
331
- ].forEach(function(id) { applyControlToCss(id); });
332
- }
333
-
334
- // ── Init: set colors to theme-appropriate defaults ──────
335
-
336
- if (document.documentElement.dataset.theme === 'dark') {
337
- STANDALONE_COLOR_IDS.forEach(function(ctrlId) {
338
- var el = document.getElementById(ctrlId);
339
- if (el) el.value = S.getStandaloneDefault(ctrlId);
340
- });
341
- }
342
-
343
- setColorValue('ctrl-color', S.getColorDefault(), false);
344
-
345
- // ── Register on SDocs for cross-module access ──────────
346
-
347
- S.setColorValue = setColorValue;
348
- S.readAllControlValues = readAllControlValues;
349
- S.collectStyles = collectStyles;
350
- S.applyStylesFromMeta = applyStylesFromMeta;
351
- S.resetAllStyles = resetAllStyles;
352
- S.STANDALONE_COLOR_IDS = STANDALONE_COLOR_IDS;
353
-
354
- })();