sdocs-dev 1.2.0 → 1.3.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.
@@ -6,7 +6,7 @@ var S = SDocs;
6
6
 
7
7
  // ── CSS var updates ──────────────────────────────────
8
8
 
9
- function applyCtrl(id) {
9
+ function applyControlToCss(id) {
10
10
  var el = document.getElementById(id);
11
11
  if (!el) return;
12
12
  var v = el.value;
@@ -35,14 +35,14 @@ function readAllControlValues() {
35
35
  return vals;
36
36
  }
37
37
 
38
- function linkRangeNum(rangeId, numId) {
38
+ function syncRangeAndNumber(rangeId, numId) {
39
39
  var r = document.getElementById(rangeId);
40
40
  var n = document.getElementById(numId);
41
- r.addEventListener('input', function() { n.value = r.value; applyCtrl(numId); });
42
- n.addEventListener('input', function() { r.value = n.value; applyCtrl(numId); });
41
+ r.addEventListener('input', function() { n.value = r.value; applyControlToCss(numId); });
42
+ n.addEventListener('input', function() { r.value = n.value; applyControlToCss(numId); });
43
43
  }
44
44
 
45
- SDocStyles.RANGE_NUM_PAIRS.forEach(function(pair) { linkRangeNum(pair[0], pair[1]); });
45
+ SDocStyles.RANGE_NUM_PAIRS.forEach(function(pair) { syncRangeAndNumber(pair[0], pair[1]); });
46
46
 
47
47
  var STANDALONE_COLOR_IDS = new Set(SDocStyles.STANDALONE_COLOR_IDS);
48
48
 
@@ -50,10 +50,11 @@ var STANDALONE_COLOR_IDS = new Set(SDocStyles.STANDALONE_COLOR_IDS);
50
50
  'ctrl-font-family','ctrl-h-font-family',
51
51
  'ctrl-h1-weight','ctrl-h2-weight','ctrl-h3-weight','ctrl-h4-weight',
52
52
  'ctrl-bg-color','ctrl-link-color','ctrl-link-decoration',
53
- 'ctrl-code-font','ctrl-code-bg','ctrl-code-color',
54
- 'ctrl-bq-border-color','ctrl-bq-bg','ctrl-bq-color',
53
+ 'ctrl-code-font',
54
+ 'ctrl-bq-border-color',
55
+ 'ctrl-chart-accent','ctrl-chart-palette',
55
56
  ].forEach(function(id) {
56
- var handler = function() { if (STANDALONE_COLOR_IDS.has(id)) S.overriddenColors.add(id); applyCtrl(id); };
57
+ var handler = function() { if (STANDALONE_COLOR_IDS.has(id)) S.overriddenColors.add(id); applyControlToCss(id); S.syncAll('controls'); };
57
58
  document.getElementById(id).addEventListener('input', handler);
58
59
  document.getElementById(id).addEventListener('change', handler);
59
60
  });
@@ -65,7 +66,12 @@ var COLOR_CHILDREN = SDocStyles.COLOR_CASCADE;
65
66
 
66
67
  function setColorValue(ctrlId, value, userAction) {
67
68
  if (userAction) S.overriddenColors.add(ctrlId);
68
- S.setStyleVar(COLOR_VAR[ctrlId], value);
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
+ }
69
75
  var ctrl = document.getElementById(ctrlId);
70
76
  if (ctrl) ctrl.value = value;
71
77
  var children = COLOR_CHILDREN[ctrlId] || [];
@@ -74,30 +80,57 @@ function setColorValue(ctrlId, value, userAction) {
74
80
  setColorValue(children[i], value, false);
75
81
  }
76
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;
77
95
  }
78
96
 
79
97
  function resetColorValue(ctrlId) {
80
98
  S.overriddenColors.delete(ctrlId);
81
- setColorValue(ctrlId, S.getColorDefault(), false);
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);
82
109
  }
83
110
 
84
111
  Object.keys(COLOR_VAR).forEach(function(ctrlId) {
85
112
  var el = document.getElementById(ctrlId);
86
113
  if (!el) return;
87
- el.addEventListener('input', function() { setColorValue(ctrlId, el.value, true); S.syncAll('controls'); });
88
- el.addEventListener('change', function() { setColorValue(ctrlId, el.value, true); S.syncAll('controls'); });
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'); });
89
124
  });
90
125
 
91
- document.getElementById('reset-color').addEventListener('click', function() { S.overriddenColors.delete('ctrl-color'); setColorValue('ctrl-color', S.getColorDefault(), false); S.syncAll('controls'); });
92
- document.getElementById('reset-h-color').addEventListener('click', function() { resetColorValue('ctrl-h-color'); S.syncAll('controls'); });
93
- document.getElementById('reset-h1-color').addEventListener('click', function() { resetColorValue('ctrl-h1-color'); S.syncAll('controls'); });
94
- document.getElementById('reset-h2-color').addEventListener('click', function() { resetColorValue('ctrl-h2-color'); S.syncAll('controls'); });
95
- document.getElementById('reset-h3-color').addEventListener('click', function() { resetColorValue('ctrl-h3-color'); S.syncAll('controls'); });
96
- document.getElementById('reset-h4-color').addEventListener('click', function() { resetColorValue('ctrl-h4-color'); S.syncAll('controls'); });
97
- document.getElementById('reset-p-color').addEventListener('click', function() { resetColorValue('ctrl-p-color'); S.syncAll('controls'); });
98
- document.getElementById('reset-list-color').addEventListener('click', function() { resetColorValue('ctrl-list-color'); S.syncAll('controls'); });
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
+ });
99
132
 
100
- ['ctrl-bg-color','ctrl-link-color','ctrl-code-bg','ctrl-code-color','ctrl-bq-border-color','ctrl-bq-bg','ctrl-bq-color'].forEach(function(ctrlId) {
133
+ ['ctrl-bg-color','ctrl-link-color','ctrl-bq-border-color','ctrl-chart-accent'].forEach(function(ctrlId) {
101
134
  var btnId = 'reset-' + ctrlId.replace('ctrl-', '');
102
135
  document.getElementById(btnId).addEventListener('click', function() {
103
136
  var defaultVal = S.getStandaloneDefault(ctrlId);
@@ -112,7 +145,7 @@ document.getElementById('reset-list-color').addEventListener('click', function()
112
145
 
113
146
  // ── Apply styles from meta → controls ──────────────────
114
147
 
115
- function setCtrl(id, val) {
148
+ function setControlValue(id, val) {
116
149
  if (val === undefined || val === null) return;
117
150
  var el = document.getElementById(id);
118
151
  if (!el) return;
@@ -120,7 +153,7 @@ function setCtrl(id, val) {
120
153
  var rangeId = id.replace(/-num$/, '-range');
121
154
  var rng = document.getElementById(rangeId);
122
155
  if (rng) rng.value = val;
123
- applyCtrl(id);
156
+ applyControlToCss(id);
124
157
  }
125
158
 
126
159
  function applyStylesFromMeta(s) {
@@ -142,31 +175,17 @@ function applyStylesFromMeta(s) {
142
175
  return o.value.replace(/['"]/g,'').split(',')[0].trim() === fontName ||
143
176
  o.textContent === fontName;
144
177
  });
145
- if (match) { sel.value = match.value; applyCtrl(ctrlId); }
178
+ if (match) { sel.value = match.value; applyControlToCss(ctrlId); }
146
179
  }
147
180
  });
148
181
 
149
182
  Object.keys(controls).forEach(function(id) {
150
183
  if (id === 'ctrl-font-family' || id === 'ctrl-h-font-family') return;
151
184
  if (SDocStyles.COLOR_VAR_MAP[id]) return;
152
- setCtrl(id, controls[id]);
185
+ setControlValue(id, controls[id]);
153
186
  });
154
187
 
155
- if (result.hasThemeColors) {
156
- // Per-theme color mode: populate both theme states
157
- S.themeColors.light = result.lightColors || {};
158
- S.themeColors.dark = result.darkColors || {};
159
- S.themeOverridden.light = result.lightOverridden || new Set();
160
- S.themeOverridden.dark = result.darkOverridden || new Set();
161
-
162
- // Load the active theme's colors into controls
163
- S._syncing = wasSyncing;
164
- S.loadThemeColors(S.activeTheme);
165
- return;
166
- }
167
-
168
- // Legacy single-theme path: top-level colors go to light theme only,
169
- // then loadThemeColors applies the correct theme's colors.
188
+ // Top-level colors = light theme. dark: block = explicit dark overrides.
170
189
  var lightOverridden = S.themeOverridden.light;
171
190
  var lightColors = S.themeColors.light;
172
191
  var newOverridden = result.overriddenColors;
@@ -187,33 +206,88 @@ function applyStylesFromMeta(s) {
187
206
  if (s.code.background) legacyStandalone.push(['ctrl-code-bg', s.code.background]);
188
207
  if (s.code.color) legacyStandalone.push(['ctrl-code-color', s.code.color]);
189
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
+ }
190
213
  if (s.blockquote) {
191
214
  if (s.blockquote.borderColor) legacyStandalone.push(['ctrl-bq-border-color', s.blockquote.borderColor]);
192
215
  if (s.blockquote.background) legacyStandalone.push(['ctrl-bq-bg', s.blockquote.background]);
193
216
  if (s.blockquote.color) legacyStandalone.push(['ctrl-bq-color', s.blockquote.color]);
194
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
+ }
195
235
  legacyStandalone.forEach(function(pair) {
196
236
  lightOverridden.add(pair[0]);
197
237
  lightColors[pair[0]] = pair[1];
198
238
  });
199
239
 
200
- // Now apply the active theme's colors (light overrides or dark defaults)
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
201
268
  S._syncing = wasSyncing;
202
269
  S.loadThemeColors(S.activeTheme);
203
270
  }
204
271
 
205
272
  function collectStyles() {
206
273
  S.saveCurrentThemeColors();
207
- var lightHas = S.themeOverridden.light.size > 0;
208
- var darkHas = S.themeOverridden.dark.size > 0;
209
- if (lightHas || darkHas) {
210
- return SDocStyles.collectStylesDual(
211
- readAllControlValues(),
212
- S.themeOverridden.light, S.themeOverridden.dark,
213
- S.themeColors.light, S.themeColors.dark
214
- );
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;
215
283
  }
216
- return SDocStyles.collectStyles(readAllControlValues(), S.overriddenColors);
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;
217
291
  }
218
292
 
219
293
  // ── Reset all styles ──────────────────────────────────
@@ -224,8 +298,15 @@ function resetAllStyles() {
224
298
  S.themeOverridden.dark.clear();
225
299
  S.themeColors.light = {};
226
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', '');
227
305
 
228
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);
229
310
  // Set standalone color controls to theme-appropriate defaults
230
311
  STANDALONE_COLOR_IDS.forEach(function(ctrlId) {
231
312
  var el = document.getElementById(ctrlId);
@@ -243,10 +324,11 @@ function resetAllStyles() {
243
324
  'ctrl-h3-size-num','ctrl-h3-weight','ctrl-h4-size-num','ctrl-h4-weight',
244
325
  'ctrl-p-lh-num','ctrl-p-mb-num',
245
326
  'ctrl-link-color','ctrl-link-decoration',
246
- 'ctrl-code-font','ctrl-code-bg','ctrl-code-color',
247
- 'ctrl-bq-border-color','ctrl-bq-bg','ctrl-bq-bw-num','ctrl-bq-size-num','ctrl-bq-color',
327
+ 'ctrl-code-font',
328
+ 'ctrl-bq-border-color','ctrl-bq-bw-num','ctrl-bq-size-num',
248
329
  'ctrl-list-spacing-num','ctrl-list-indent-num',
249
- ].forEach(function(id) { applyCtrl(id); });
330
+ 'ctrl-chart-accent','ctrl-chart-palette',
331
+ ].forEach(function(id) { applyControlToCss(id); });
250
332
  }
251
333
 
252
334
  // ── Init: set colors to theme-appropriate defaults ──────