@dr-ishaan/remake-blocks 1.8.0 → 1.10.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.
package/dist/dx.js ADDED
@@ -0,0 +1,230 @@
1
+ /**
2
+ * v1.10.0: Developer Experience utilities.
3
+ *
4
+ * Exports:
5
+ * - CLASSES: frozen object of CSS class name constants for programmatic use
6
+ * - warn(message, ...args): dev-mode warning emitter (gated on devWarnings option)
7
+ * - validateCustomCallouts(configs, strict): validates customCallouts at init time
8
+ * - suggestSimilarType(type, knownTypes): Levenshtein-based "did you mean" suggester
9
+ *
10
+ * @module dx
11
+ */
12
+ // ---------------------------------------------------------------------------
13
+ // CLASSES — exported CSS class name constants
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * v1.10.0+: Frozen object of CSS class names used by the plugin. Use these
17
+ * in CSS-in-JS, tests, or any code that needs to reference callout classes
18
+ * programmatically without hardcoding strings.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { CLASSES } from '@dr-ishaan/remake-blocks';
23
+ *
24
+ * document.querySelector(`.${CLASSES.CALLOUT_NOTE}`) // '.callout-note'
25
+ * ```
26
+ */
27
+ export const CLASSES = Object.freeze({
28
+ // Container classes
29
+ CALLOUT: "callout",
30
+ CALLOUT_NOTE: "callout-note",
31
+ CALLOUT_TIP: "callout-tip",
32
+ CALLOUT_IMPORTANT: "callout-important",
33
+ CALLOUT_WARNING: "callout-warning",
34
+ CALLOUT_CAUTION: "callout-caution",
35
+ CALLOUT_ABSTRACT: "callout-abstract",
36
+ CALLOUT_INFO: "callout-info",
37
+ CALLOUT_SUCCESS: "callout-success",
38
+ CALLOUT_QUESTION: "callout-question",
39
+ CALLOUT_FAILURE: "callout-failure",
40
+ CALLOUT_DANGER: "callout-danger",
41
+ CALLOUT_QUOTE: "callout-quote",
42
+ CALLOUT_BUG: "callout-bug",
43
+ CALLOUT_EXAMPLE: "callout-example",
44
+ CALLOUT_TODO: "callout-todo",
45
+ CALLOUT_SUMMARY: "callout-summary",
46
+ CALLOUT_TLDR: "callout-tldr",
47
+ CALLOUT_HINT: "callout-hint",
48
+ CALLOUT_CHECK: "callout-check",
49
+ CALLOUT_DONE: "callout-done",
50
+ CALLOUT_HELP: "callout-help",
51
+ CALLOUT_FAQ: "callout-faq",
52
+ CALLOUT_ATTENTION: "callout-attention",
53
+ CALLOUT_FAIL: "callout-fail",
54
+ CALLOUT_MISSING: "callout-missing",
55
+ CALLOUT_ERROR: "callout-error",
56
+ CALLOUT_CITE: "callout-cite",
57
+ // v1.6.0 types
58
+ CALLOUT_DEFINITION: "callout-definition",
59
+ CALLOUT_ASIDE: "callout-aside",
60
+ CALLOUT_CORRECTION: "callout-correction",
61
+ CALLOUT_UPDATE: "callout-update",
62
+ CALLOUT_FIGURE: "callout-figure",
63
+ CALLOUT_FURTHER_READING: "callout-further-reading",
64
+ CALLOUT_PREREQUISITE: "callout-prerequisite",
65
+ CALLOUT_EXERCISE: "callout-exercise",
66
+ CALLOUT_SIDENOTE: "callout-sidenote",
67
+ CALLOUT_TIMELINE: "callout-timeline",
68
+ CALLOUT_ANNOUNCEMENT: "callout-announcement",
69
+ CALLOUT_BIBLIOGRAPHY: "callout-bibliography",
70
+ CALLOUT_DRAFT: "callout-draft",
71
+ CALLOUT_TRANSLATION: "callout-translation",
72
+ CALLOUT_DISCUSSION: "callout-discussion",
73
+ CALLOUT_RETRO: "callout-retro",
74
+ // Sub-element classes
75
+ CALLOUT_TITLE: "callout-title",
76
+ CALLOUT_TITLE_TEXT: "callout-title-text",
77
+ CALLOUT_ICON: "callout-icon",
78
+ CALLOUT_BODY: "callout-body",
79
+ CALLOUT_COLLAPSIBLE: "collapsible",
80
+ // Disclosure / accordion
81
+ DISCLOSURE: "disclosure",
82
+ DISCLOSURE_TITLE: "disclosure-title",
83
+ DISCLOSURE_BODY: "disclosure-body",
84
+ DISCLOSURE_ACCORDION: "disclosure-accordion",
85
+ DISCLOSURE_TREE: "disclosure-tree",
86
+ // Pull quote / epigraph
87
+ PULL_QUOTE: "pull-quote",
88
+ PULL_QUOTE_TEXT: "pull-quote-text",
89
+ PULL_QUOTE_ATTRIBUTION: "pull-quote-attribution",
90
+ EPIGRAPH: "epigraph",
91
+ EPIGRAPH_TEXT: "epigraph-text",
92
+ EPIGRAPH_ATTRIBUTION: "epigraph-attribution",
93
+ // Blockquote enhancement
94
+ BLOCKQUOTE_ENHANCED: "blockquote-enhanced",
95
+ });
96
+ // ---------------------------------------------------------------------------
97
+ // warn — dev-mode warning emitter
98
+ // ---------------------------------------------------------------------------
99
+ /**
100
+ * v1.10.0+: Emit a developer-mode warning via `console.warn`.
101
+ *
102
+ * The warning is prefixed with `[remake-blocks]` for easy identification
103
+ * and filtering. No-op when `devWarnings` is false OR when running in
104
+ * production (`process.env.NODE_ENV === 'production'`).
105
+ *
106
+ * @param enabled — whether devWarnings is enabled (from plugin options)
107
+ * @param message — warning message (without prefix)
108
+ * @param args — additional context args
109
+ */
110
+ export function warn(enabled, message, ...args) {
111
+ if (!enabled)
112
+ return;
113
+ if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production" && enabled !== true) {
114
+ // Auto-disable in production unless explicitly enabled
115
+ return;
116
+ }
117
+ console.warn(`[remake-blocks] ${message}`, ...args);
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // suggestSimilarType — Levenshtein-based "did you mean" suggester
121
+ // ---------------------------------------------------------------------------
122
+ /**
123
+ * Compute Levenshtein edit distance between two strings.
124
+ * Used by `suggestSimilarType` to find the closest match.
125
+ */
126
+ function levenshtein(a, b) {
127
+ const m = a.length;
128
+ const n = b.length;
129
+ if (m === 0)
130
+ return n;
131
+ if (n === 0)
132
+ return m;
133
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
134
+ for (let i = 0; i <= m; i++)
135
+ dp[i][0] = i;
136
+ for (let j = 0; j <= n; j++)
137
+ dp[0][j] = j;
138
+ for (let i = 1; i <= m; i++) {
139
+ for (let j = 1; j <= n; j++) {
140
+ const cost = a[i - 1].toLowerCase() === b[j - 1].toLowerCase() ? 0 : 1;
141
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, // deletion
142
+ dp[i][j - 1] + 1, // insertion
143
+ dp[i - 1][j - 1] + cost);
144
+ }
145
+ }
146
+ return dp[m][n];
147
+ }
148
+ /**
149
+ * Find the closest matching type from a list of known types.
150
+ * Returns the best match if its edit distance is ≤ 3 (reasonable threshold
151
+ * for typo detection), or null if no close match exists.
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * suggestSimilarType('TYPO', ['note', 'tip', 'warning']) // → 'tip'
156
+ * suggestSimilarType('XYZ', ['note', 'tip']) // → null
157
+ * ```
158
+ */
159
+ export function suggestSimilarType(input, knownTypes) {
160
+ let bestMatch = null;
161
+ let bestDistance = Infinity;
162
+ for (const candidate of knownTypes) {
163
+ const dist = levenshtein(input, candidate);
164
+ if (dist < bestDistance) {
165
+ bestDistance = dist;
166
+ bestMatch = candidate;
167
+ }
168
+ }
169
+ // Only suggest if the edit distance is reasonable (≤ 3 edits, or ≤ half
170
+ // the input length for longer type names like 'further-reading').
171
+ const threshold = Math.max(3, Math.floor(input.length / 2));
172
+ return bestDistance <= threshold ? bestMatch : null;
173
+ }
174
+ // ---------------------------------------------------------------------------
175
+ // validateCustomCallouts — strict config validation
176
+ // ---------------------------------------------------------------------------
177
+ const REQUIRED_CALLOUT_FIELDS = ["type", "icon", "className", "defaultTitle", "color", "backgroundColor"];
178
+ /**
179
+ * v1.10.0+: Validate `customCallouts` config entries.
180
+ *
181
+ * When `strict` is true, throws a descriptive Error for the first config
182
+ * entry that's missing a required field. When `strict` is false, returns
183
+ * an array of validation errors without throwing (caller decides what to do).
184
+ *
185
+ * Required fields per CalloutConfig:
186
+ * - type (non-empty string)
187
+ * - icon (string, may be empty for icon-less callouts)
188
+ * - className (non-empty string, used for CSS targeting)
189
+ * - defaultTitle (non-empty string)
190
+ * - color (valid CSS color)
191
+ * - backgroundColor (valid CSS color)
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * validateCustomCallouts([
196
+ * { type: 'x', icon: '🔥', className: 'callout-x', defaultTitle: 'X', color: '#f00', backgroundColor: '#fee' }
197
+ * ], true); // OK — no throw
198
+ *
199
+ * validateCustomCallouts([
200
+ * { type: 'x', icon: '🔥' /* missing className, defaultTitle, color, backgroundColor *\/ }
201
+ * ], true); // throws: "Custom callout config[0] ('x') is missing required fields: className, defaultTitle, color, backgroundColor"
202
+ * ```
203
+ */
204
+ export function validateCustomCallouts(configs, strict) {
205
+ const errors = [];
206
+ for (let i = 0; i < configs.length; i++) {
207
+ const c = configs[i];
208
+ if (!c || typeof c !== "object") {
209
+ errors.push(`Custom callout config[${i}] is not an object`);
210
+ continue;
211
+ }
212
+ const missing = [];
213
+ for (const field of REQUIRED_CALLOUT_FIELDS) {
214
+ const val = c[field];
215
+ if (val === undefined || val === null || (typeof val === "string" && val.trim() === "" && field !== "icon")) {
216
+ missing.push(field);
217
+ }
218
+ }
219
+ if (missing.length > 0) {
220
+ const name = typeof c.type === "string" ? `'${c.type}'` : `at index ${i}`;
221
+ const msg = `Custom callout config[${i}] (${name}) is missing required fields: ${missing.join(", ")}`;
222
+ errors.push(msg);
223
+ if (strict) {
224
+ throw new Error(`[remake-blocks] ${msg}`);
225
+ }
226
+ }
227
+ }
228
+ return errors;
229
+ }
230
+ //# sourceMappingURL=dx.js.map
package/dist/dx.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dx.js","sourceRoot":"","sources":["../src/dx.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,7 +8,9 @@
8
8
  */
9
9
  export { remarkRemakeBlocks, remarkCalloutBlocks, BUILTIN_CALLOUTS } from "./remark-remake-blocks.js";
10
10
  export { escapeHtml, escapeAttribute, sanitizeColor } from "./remark-remake-blocks.js";
11
- export { generateCss } from "./css-generator.js";
11
+ export { generateCss, generateMinimalThemeCss } from "./css-generator.js";
12
+ export { CLASSES, validateCustomCallouts, suggestSimilarType } from "./dx.js";
13
+ export type { CalloutClassName } from "./dx.js";
12
14
  export { default } from "./astro.js";
13
- export type { RemakeBlocksOptions, AstroRemakeBlocksOptions, CalloutConfig, CalloutType, BuiltinCalloutType, ParsedCallout, CustomCalloutType, CalloutConfigMap, } from "./types.js";
15
+ export type { RemakeBlocksOptions, AstroRemakeBlocksOptions, CalloutConfig, CalloutType, BuiltinCalloutType, LucideIconName, ParsedCallout, CustomCalloutType, CalloutConfigMap, } from "./types.js";
14
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEtG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAGvF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEtG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAIvF,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG1E,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC9E,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,YAAY,EACV,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -11,7 +11,10 @@ export { remarkRemakeBlocks, remarkCalloutBlocks, BUILTIN_CALLOUTS } from "./rem
11
11
  // Helpers (for users who supply a custom `build` render function)
12
12
  export { escapeHtml, escapeAttribute, sanitizeColor } from "./remark-remake-blocks.js";
13
13
  // v1.7.0+: CSS generator (for advanced usage outside Astro)
14
- export { generateCss } from "./css-generator.js";
14
+ // v1.9.0+: also exports generateMinimalThemeCss for tree-shaken theme CSS
15
+ export { generateCss, generateMinimalThemeCss } from "./css-generator.js";
16
+ // v1.10.0+: DX utilities — CSS class constants, validation, "did you mean" suggester
17
+ export { CLASSES, validateCustomCallouts, suggestSimilarType } from "./dx.js";
15
18
  // Astro integration (default export, re-exported for backward compatibility)
16
19
  export { default } from "./astro.js";
17
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAqB;AACrB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACtG,kEAAkE;AAClE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAEvF,4DAA4D;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,6EAA6E;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAqB;AACrB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACtG,kEAAkE;AAClE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAEvF,4DAA4D;AAC5D,0EAA0E;AAC1E,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE1E,qFAAqF;AACrF,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAG9E,6EAA6E;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"remark-remake-blocks.d.ts","sourceRoot":"","sources":["../src/remark-remake-blocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAqC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EAId,MAAM,YAAY,CAAC;AAMpB,QAAA,MAAM,gBAAgB,EAAE,aAAa,EAyQpC,CAAC;AAsNF,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAUD,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAW9D;AAgTD,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOvC;AA26BD,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,CAAC,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAsHnE,CAAC;AAiFF,eAAO,MAAM,mBAAmB,oDAAqB,CAAC;AAItD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"remark-remake-blocks.d.ts","sourceRoot":"","sources":["../src/remark-remake-blocks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAqC,MAAM,OAAO,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EAId,MAAM,YAAY,CAAC;AAQpB,QAAA,MAAM,gBAAgB,EAAE,aAAa,EAyQpC,CAAC;AAkOF,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAUD,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAW9D;AA6TD,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOvC;AA08BD,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,CAAC,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAgMnE,CAAC;AAiFF,eAAO,MAAM,mBAAmB,oDAAqB,CAAC;AAItD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -14,6 +14,9 @@
14
14
  * `allowDangerousHtml: true` in plugin options to disable escaping —
15
15
  * only do this if you fully trust your markdown source.
16
16
  */
17
+ import { visit } from "unist-util-visit";
18
+ // v1.10.0: DX utilities — warnings, validation, "did you mean" suggester
19
+ import { warn, validateCustomCallouts, suggestSimilarType } from "./dx.js";
17
20
  // ---------------------------------------------------------------------------
18
21
  // 27 Built-in callout configurations
19
22
  // ---------------------------------------------------------------------------
@@ -443,6 +446,12 @@ const DEFAULT_OPTIONS = {
443
446
  types: undefined,
444
447
  defaultCollapse: undefined,
445
448
  syntax: undefined,
449
+ // v1.9.0 defaults — all opt-in
450
+ icons: undefined,
451
+ cssMinimalTheme: false,
452
+ // v1.10.0 defaults — devWarnings auto-resolves (undefined = auto), strict off
453
+ devWarnings: undefined,
454
+ strictConfigValidation: false,
446
455
  };
447
456
  // ---------------------------------------------------------------------------
448
457
  // Helper: Validate + normalize a single custom callout config.
@@ -690,7 +699,7 @@ function parseDirectiveAttrs(attrsBlock) {
690
699
  // ---------------------------------------------------------------------------
691
700
  // Helper: Parse the first paragraph of a blockquote to detect a callout
692
701
  // ---------------------------------------------------------------------------
693
- function parseCalloutDirective(blockquote, calloutPattern, configMap, enableDisclosures, defaultCollapse) {
702
+ function parseCalloutDirective(blockquote, calloutPattern, configMap, enableDisclosures, defaultCollapse, options) {
694
703
  const firstChild = blockquote.children[0];
695
704
  if (!firstChild || firstChild.type !== "paragraph")
696
705
  return null;
@@ -705,8 +714,19 @@ function parseCalloutDirective(blockquote, calloutPattern, configMap, enableDisc
705
714
  const lowerType = rawType.toLowerCase();
706
715
  const isPullQuote = lowerType === "pull";
707
716
  const isEpigraph = lowerType === "epigraph";
708
- if (!isDisclosure && !isPullQuote && !isEpigraph && !configMap.has(lowerType))
717
+ if (!isDisclosure && !isPullQuote && !isEpigraph && !configMap.has(lowerType)) {
718
+ // v1.10.0: dev warning for unknown callout types with "did you mean" suggestion
719
+ const devWarn = options?._devWarnings;
720
+ if (devWarn) {
721
+ const known = options?._knownTypes;
722
+ const suggestion = known && known.length > 0 ? suggestSimilarType(rawType, known) : null;
723
+ const msg = suggestion
724
+ ? `Unknown callout type '${rawType}'. Did you mean '${suggestion}'?`
725
+ : `Unknown callout type '${rawType}'. It will render as a plain blockquote.`;
726
+ warn(true, msg);
727
+ }
709
728
  return null;
729
+ }
710
730
  const type = isDisclosure ? "disclosure"
711
731
  : isPullQuote ? "pull"
712
732
  : isEpigraph ? "epigraph"
@@ -969,8 +989,36 @@ function buildCalloutHtml(parsed, blockquote, calloutPattern, configMap, options
969
989
  }
970
990
  }
971
991
  const effectiveRenderIcon = renderIcon && resolvedIcon.length > 0;
972
- const iconHtml = effectiveRenderIcon
973
- ? `<span class="callout-icon" style="color:${safeIconColor}" aria-hidden="true">${resolvedIcon}</span>`
992
+ // v1.9.0: icon sprite strategy. When icons.strategy === 'sprite', extract
993
+ // the inner SVG content (paths, circles, etc.) and register a <symbol> in
994
+ // the document-level sprite collector. The callout then references the
995
+ // symbol via <use href="#rb-icon-{key}"/> instead of inlining the full SVG.
996
+ //
997
+ // This dramatically reduces HTML size for callout-heavy pages: N callouts
998
+ // of the same type share ONE <symbol> definition instead of N inline SVGs.
999
+ const _iconStrategy = options._iconStrategy;
1000
+ const _spriteCollector = options._spriteCollector;
1001
+ let effectiveIconHtml = resolvedIcon;
1002
+ if (_iconStrategy === "none") {
1003
+ effectiveIconHtml = "";
1004
+ }
1005
+ else if (_iconStrategy === "sprite" && _spriteCollector && effectiveRenderIcon) {
1006
+ // Build a stable symbol ID from the callout type or icon name.
1007
+ // Per-callout {icon="rocket"} overrides get their own symbol; otherwise
1008
+ // the type name is the key (so all [!NOTE] callouts share one symbol).
1009
+ const symbolKey = parsed.overrides?.iconName
1010
+ ? `rb-icon-${parsed.overrides.iconName.replace(/[^a-zA-Z0-9-]/g, "-")}`
1011
+ : `rb-icon-${parsed.type.replace(/[^a-zA-Z0-9-]/g, "-")}`;
1012
+ // Extract inner SVG content: everything between <svg ...> and </svg>.
1013
+ const innerMatch = resolvedIcon.match(/<svg[^>]*>([\s\S]*)<\/svg>/i);
1014
+ const inner = innerMatch ? innerMatch[1].trim() : resolvedIcon;
1015
+ if (!_spriteCollector.has(symbolKey)) {
1016
+ _spriteCollector.set(symbolKey, inner);
1017
+ }
1018
+ effectiveIconHtml = `<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" aria-hidden="true"><use href="#${symbolKey}"/></svg>`;
1019
+ }
1020
+ const iconHtml = effectiveRenderIcon && effectiveIconHtml
1021
+ ? `<span class="callout-icon" style="color:${safeIconColor}" aria-hidden="true">${effectiveIconHtml}</span>`
974
1022
  : "";
975
1023
  // v1.2.0: title-text always rendered (unless appearance="hidden")
976
1024
  const renderTitle = appearance !== "hidden";
@@ -985,8 +1033,9 @@ function buildCalloutHtml(parsed, blockquote, calloutPattern, configMap, options
985
1033
  const titleTextTag = tags.titleText || "span";
986
1034
  const bodyTag = tags.body || "div";
987
1035
  // Build icon span with custom tag if provided
988
- const iconSpan = effectiveRenderIcon
989
- ? `<${iconTag} class="callout-icon" style="color:${safeIconColor}" aria-hidden="true">${resolvedIcon}</${iconTag}>`
1036
+ // v1.9.0: uses effectiveIconHtml (sprite <use> reference when sprite mode)
1037
+ const iconSpan = effectiveRenderIcon && effectiveIconHtml
1038
+ ? `<${iconTag} class="callout-icon" style="color:${safeIconColor}" aria-hidden="true">${effectiveIconHtml}</${iconTag}>`
990
1039
  : "";
991
1040
  // Build the title block (or skip for "hidden" appearance)
992
1041
  const titleBlock = renderTitle
@@ -1592,6 +1641,19 @@ export const remarkRemakeBlocks = (userOptions) => {
1592
1641
  ...DEFAULT_OPTIONS,
1593
1642
  ...userOptions,
1594
1643
  };
1644
+ // v1.10.0: resolve devWarnings. undefined → auto (true in dev, false in prod).
1645
+ const isProd = typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production";
1646
+ const devWarningsEnabled = options.devWarnings === undefined ? !isProd : options.devWarnings;
1647
+ // v1.10.0: strict customCallouts validation. Throws at init time when
1648
+ // strictConfigValidation is true and any config entry is missing required
1649
+ // fields. In non-strict mode, emits a dev warning instead.
1650
+ if (options.customCallouts && options.customCallouts.length > 0) {
1651
+ const errors = validateCustomCallouts(options.customCallouts, options.strictConfigValidation);
1652
+ if (errors.length > 0 && !options.strictConfigValidation) {
1653
+ for (const e of errors)
1654
+ warn(devWarningsEnabled, e);
1655
+ }
1656
+ }
1595
1657
  // v1.8.0: resolve `syntax` into enableDirectiveSyntax / enableMkDocsSyntax.
1596
1658
  // Explicit `enableDirectiveSyntax` / `enableMkDocsSyntax` (v1.3.0 / v1.4.0
1597
1659
  // API) take precedence over `syntax` for backward compatibility.
@@ -1611,11 +1673,24 @@ export const remarkRemakeBlocks = (userOptions) => {
1611
1673
  }
1612
1674
  const configMap = buildCalloutConfigMap(options);
1613
1675
  const calloutPattern = options.calloutPattern || buildCalloutPattern(configMap, options.enableDisclosures);
1676
+ // v1.10.0: stash devWarnings flag + known types list on options so
1677
+ // buildCalloutHtml / parseCalloutDirective can emit warnings.
1678
+ options._devWarnings = devWarningsEnabled;
1679
+ options._knownTypes = Array.from(configMap.keys());
1680
+ // v1.9.0: sprite collector — accumulates { symbolId: svgInnerHtml } entries
1681
+ // across all callouts in this document. Populated by buildCalloutHtml when
1682
+ // icons.strategy === 'sprite'. Emitted as a single <svg> sprite at the top
1683
+ // of the document after Pass 1 completes.
1684
+ const iconStrategy = options.icons?.strategy ?? "inline";
1685
+ const spriteCollector = new Map();
1614
1686
  return (tree) => {
1615
1687
  // v1.2.0: reset per-tree counter for idempotent output (same markdown →
1616
1688
  // same HTML, including same ids). This is important for snapshot tests
1617
1689
  // and for SSR/deterministic rendering.
1618
1690
  resetCalloutIdCounter();
1691
+ // v1.9.0: reset sprite collector per-tree so repeated process() calls
1692
+ // don't accumulate stale entries.
1693
+ spriteCollector.clear();
1619
1694
  // v1.3.0: Pass 0 — Transform :::type[Title]{overrides} ... ::: directive syntax
1620
1695
  // into callouts (Starlight/Docusaurus/MkDocs content portability).
1621
1696
  if (options.enableDirectiveSyntax) {
@@ -1626,6 +1701,37 @@ export const remarkRemakeBlocks = (userOptions) => {
1626
1701
  if (options.enableMkDocsSyntax) {
1627
1702
  transformMkDocsSyntax(tree, configMap, options);
1628
1703
  }
1704
+ // v1.10.0: Pass 0c — Scan for unknown callout directives and emit dev warnings.
1705
+ // The calloutPattern only matches KNOWN types, so unknown types like
1706
+ // [!TYPO] fall through to plain blockquotes WITHOUT entering parseCalloutDirective.
1707
+ // This pre-scan catches them so users get a "did you mean" hint.
1708
+ if (devWarningsEnabled) {
1709
+ const knownTypes = options._knownTypes;
1710
+ const anyDirectiveRe = /^\[!([A-Za-z][A-Za-z0-9-]*)\]/;
1711
+ visit(tree, "blockquote", (bq) => {
1712
+ const first = bq.children[0];
1713
+ if (!first || first.type !== "paragraph")
1714
+ return;
1715
+ const text = extractTextContent(first);
1716
+ if (!text)
1717
+ return;
1718
+ const m = text.match(anyDirectiveRe);
1719
+ if (!m)
1720
+ return;
1721
+ const rawType = m[1];
1722
+ const lowerType = rawType.toLowerCase();
1723
+ // Skip disclosures (empty type), pull quotes, epigraphs, and known types
1724
+ if (lowerType === "" || lowerType === "pull" || lowerType === "epigraph")
1725
+ return;
1726
+ if (configMap.has(lowerType))
1727
+ return;
1728
+ const suggestion = suggestSimilarType(rawType, knownTypes);
1729
+ const msg = suggestion
1730
+ ? `Unknown callout type '${rawType}'. Did you mean '${suggestion}'?`
1731
+ : `Unknown callout type '${rawType}'. It will render as a plain blockquote.`;
1732
+ warn(true, msg);
1733
+ });
1734
+ }
1629
1735
  // ── Pass 1: Transform blockquotes → callouts / disclosures ──────
1630
1736
  // We must process DEEPEST blockquotes first (inside-out) so that
1631
1737
  // nested [!] directives are converted before their parents read them.
@@ -1662,11 +1768,14 @@ export const remarkRemakeBlocks = (userOptions) => {
1662
1768
  if (foundIdx === -1)
1663
1769
  continue; // Already replaced
1664
1770
  }
1665
- const parsed = parseCalloutDirective(bq, calloutPattern, configMap, options.enableDisclosures, options.defaultCollapse);
1771
+ const parsed = parseCalloutDirective(bq, calloutPattern, configMap, options.enableDisclosures, options.defaultCollapse, options);
1666
1772
  if (parsed) {
1667
1773
  // For disclosures: depth > 0 means it's nested inside another blockquote
1668
1774
  // (which is likely another disclosure or callout) → tree view
1669
1775
  const disclosureDepth = parsed.isDisclosure ? depth : 0;
1776
+ // v1.9.0: attach sprite collector + strategy to options for buildCalloutHtml
1777
+ options._iconStrategy = iconStrategy;
1778
+ options._spriteCollector = spriteCollector;
1670
1779
  const calloutNode = buildCalloutHtml(parsed, bq, calloutPattern, configMap, options, disclosureDepth);
1671
1780
  // Replace using the actual current index
1672
1781
  const actualIdx = parent.children.indexOf(bq);
@@ -1691,6 +1800,19 @@ export const remarkRemakeBlocks = (userOptions) => {
1691
1800
  if (options.enableAccordion && options.enableDisclosures) {
1692
1801
  groupAccordions(tree, options.accordionClass);
1693
1802
  }
1803
+ // v1.9.0: Pass 3 — Emit icon sprite at the top of the document.
1804
+ // Only when icons.strategy === 'sprite' AND at least one callout
1805
+ // registered an icon. The sprite uses display:none so it doesn't
1806
+ // affect layout; <use href="#rb-icon-{key}"/> references resolve
1807
+ // against it.
1808
+ if (iconStrategy === "sprite" && spriteCollector.size > 0) {
1809
+ const symbols = Array.from(spriteCollector.entries())
1810
+ .map(([id, inner]) => `<symbol id="${id}" viewBox="0 0 24 24">${inner}</symbol>`)
1811
+ .join("");
1812
+ const spriteHtml = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">${symbols}</svg>`;
1813
+ // Prepend to the document tree as a raw HTML node
1814
+ tree.children.unshift(html(spriteHtml));
1815
+ }
1694
1816
  };
1695
1817
  };
1696
1818
  // ---------------------------------------------------------------------------