snice 4.17.0 → 4.18.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.
Files changed (252) hide show
  1. package/adapters/react/code-block.d.ts +1 -0
  2. package/adapters/react/code-block.d.ts.map +1 -1
  3. package/adapters/react/code-block.js +1 -1
  4. package/adapters/react/code-block.js.map +1 -1
  5. package/adapters/react/code-block.tsx +2 -1
  6. package/dist/cdn/accordion/snice-accordion.js +1 -1
  7. package/dist/cdn/accordion/snice-accordion.min.js +1 -1
  8. package/dist/cdn/alert/snice-alert.js +1 -1
  9. package/dist/cdn/alert/snice-alert.min.js +1 -1
  10. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  11. package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
  12. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  13. package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
  14. package/dist/cdn/avatar/snice-avatar.js +1 -1
  15. package/dist/cdn/avatar/snice-avatar.min.js +1 -1
  16. package/dist/cdn/badge/snice-badge.js +1 -1
  17. package/dist/cdn/badge/snice-badge.min.js +1 -1
  18. package/dist/cdn/banner/snice-banner.js +1 -1
  19. package/dist/cdn/banner/snice-banner.min.js +1 -1
  20. package/dist/cdn/book/snice-book.js +1 -1
  21. package/dist/cdn/book/snice-book.min.js +1 -1
  22. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  23. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
  24. package/dist/cdn/button/snice-button.js +1 -1
  25. package/dist/cdn/button/snice-button.min.js +1 -1
  26. package/dist/cdn/calendar/snice-calendar.js +1 -1
  27. package/dist/cdn/calendar/snice-calendar.min.js +1 -1
  28. package/dist/cdn/camera/snice-camera.js +1 -1
  29. package/dist/cdn/camera/snice-camera.min.js +1 -1
  30. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  31. package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
  32. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  33. package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
  34. package/dist/cdn/card/snice-card.js +1 -1
  35. package/dist/cdn/card/snice-card.min.js +1 -1
  36. package/dist/cdn/carousel/snice-carousel.js +1 -1
  37. package/dist/cdn/carousel/snice-carousel.min.js +1 -1
  38. package/dist/cdn/chart/snice-chart.js +1 -1
  39. package/dist/cdn/chart/snice-chart.min.js +1 -1
  40. package/dist/cdn/chat/snice-chat.js +1 -1
  41. package/dist/cdn/chat/snice-chat.min.js +1 -1
  42. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  43. package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
  44. package/dist/cdn/chip/snice-chip.js +1 -1
  45. package/dist/cdn/chip/snice-chip.min.js +1 -1
  46. package/dist/cdn/code-block/README.md +2 -2
  47. package/dist/cdn/code-block/snice-code-block.js +314 -3
  48. package/dist/cdn/code-block/snice-code-block.js.map +1 -1
  49. package/dist/cdn/code-block/snice-code-block.min.js +3 -3
  50. package/dist/cdn/code-block/snice-code-block.min.js.map +1 -1
  51. package/dist/cdn/color-display/snice-color-display.js +1 -1
  52. package/dist/cdn/color-display/snice-color-display.min.js +1 -1
  53. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  54. package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
  55. package/dist/cdn/command-palette/snice-command-palette.js +1 -1
  56. package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
  57. package/dist/cdn/comments/snice-comments.js +1 -1
  58. package/dist/cdn/comments/snice-comments.min.js +1 -1
  59. package/dist/cdn/countdown/snice-countdown.js +1 -1
  60. package/dist/cdn/countdown/snice-countdown.min.js +1 -1
  61. package/dist/cdn/cropper/snice-cropper.js +1 -1
  62. package/dist/cdn/cropper/snice-cropper.min.js +1 -1
  63. package/dist/cdn/date-picker/snice-date-picker.js +1 -1
  64. package/dist/cdn/date-picker/snice-date-picker.min.js +1 -1
  65. package/dist/cdn/diff/snice-diff.js +1 -1
  66. package/dist/cdn/diff/snice-diff.min.js +1 -1
  67. package/dist/cdn/divider/snice-divider.js +1 -1
  68. package/dist/cdn/divider/snice-divider.min.js +1 -1
  69. package/dist/cdn/doc/snice-doc.js +1 -1
  70. package/dist/cdn/doc/snice-doc.min.js +1 -1
  71. package/dist/cdn/draw/snice-draw.js +1 -1
  72. package/dist/cdn/draw/snice-draw.min.js +1 -1
  73. package/dist/cdn/drawer/snice-drawer.js +1 -1
  74. package/dist/cdn/drawer/snice-drawer.min.js +1 -1
  75. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  76. package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
  77. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  78. package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
  79. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  80. package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
  81. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  82. package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
  83. package/dist/cdn/flow/snice-flow.js +1 -1
  84. package/dist/cdn/flow/snice-flow.min.js +1 -1
  85. package/dist/cdn/funnel/snice-funnel.js +1 -1
  86. package/dist/cdn/funnel/snice-funnel.min.js +1 -1
  87. package/dist/cdn/gantt/snice-gantt.js +1 -1
  88. package/dist/cdn/gantt/snice-gantt.min.js +1 -1
  89. package/dist/cdn/gauge/snice-gauge.js +1 -1
  90. package/dist/cdn/gauge/snice-gauge.min.js +1 -1
  91. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  92. package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
  93. package/dist/cdn/image/snice-image.js +1 -1
  94. package/dist/cdn/image/snice-image.min.js +1 -1
  95. package/dist/cdn/input/snice-input.js +1 -1
  96. package/dist/cdn/input/snice-input.min.js +1 -1
  97. package/dist/cdn/kanban/snice-kanban.js +1 -1
  98. package/dist/cdn/kanban/snice-kanban.min.js +1 -1
  99. package/dist/cdn/kpi/snice-kpi.js +1 -1
  100. package/dist/cdn/kpi/snice-kpi.min.js +1 -1
  101. package/dist/cdn/layout/snice-layout.js +1 -1
  102. package/dist/cdn/layout/snice-layout.min.js +1 -1
  103. package/dist/cdn/link/snice-link.js +1 -1
  104. package/dist/cdn/link/snice-link.min.js +1 -1
  105. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  106. package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
  107. package/dist/cdn/list/snice-list.js +1 -1
  108. package/dist/cdn/list/snice-list.min.js +1 -1
  109. package/dist/cdn/location/snice-location.js +1 -1
  110. package/dist/cdn/location/snice-location.min.js +1 -1
  111. package/dist/cdn/login/snice-login.js +1 -1
  112. package/dist/cdn/login/snice-login.min.js +1 -1
  113. package/dist/cdn/map/snice-map.js +1 -1
  114. package/dist/cdn/map/snice-map.min.js +1 -1
  115. package/dist/cdn/markdown/snice-markdown.js +1 -1
  116. package/dist/cdn/markdown/snice-markdown.min.js +1 -1
  117. package/dist/cdn/masonry/snice-masonry.js +1 -1
  118. package/dist/cdn/masonry/snice-masonry.min.js +1 -1
  119. package/dist/cdn/menu/snice-menu.js +1 -1
  120. package/dist/cdn/menu/snice-menu.min.js +1 -1
  121. package/dist/cdn/modal/snice-modal.js +1 -1
  122. package/dist/cdn/modal/snice-modal.min.js +1 -1
  123. package/dist/cdn/music-player/snice-music-player.js +1 -1
  124. package/dist/cdn/music-player/snice-music-player.min.js +1 -1
  125. package/dist/cdn/nav/snice-nav.js +1 -1
  126. package/dist/cdn/nav/snice-nav.min.js +1 -1
  127. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  128. package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
  129. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  130. package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
  131. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  132. package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
  133. package/dist/cdn/pagination/snice-pagination.js +1 -1
  134. package/dist/cdn/pagination/snice-pagination.min.js +1 -1
  135. package/dist/cdn/paint/snice-paint.js +1 -1
  136. package/dist/cdn/paint/snice-paint.min.js +1 -1
  137. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
  138. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +1 -1
  139. package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
  140. package/dist/cdn/podcast-player/snice-podcast-player.min.js +1 -1
  141. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  142. package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
  143. package/dist/cdn/progress/snice-progress.js +1 -1
  144. package/dist/cdn/progress/snice-progress.min.js +1 -1
  145. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  146. package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
  147. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  148. package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
  149. package/dist/cdn/radio/snice-radio.js +1 -1
  150. package/dist/cdn/radio/snice-radio.min.js +1 -1
  151. package/dist/cdn/rating/snice-rating.js +1 -1
  152. package/dist/cdn/rating/snice-rating.min.js +1 -1
  153. package/dist/cdn/recipe/snice-recipe.js +1 -1
  154. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  155. package/dist/cdn/runtime/snice-runtime.esm.js +4 -4
  156. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  157. package/dist/cdn/runtime/snice-runtime.esm.min.js +4 -4
  158. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  159. package/dist/cdn/runtime/snice-runtime.js +4 -4
  160. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  161. package/dist/cdn/runtime/snice-runtime.min.js +4 -4
  162. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  163. package/dist/cdn/sankey/snice-sankey.js +1 -1
  164. package/dist/cdn/sankey/snice-sankey.min.js +1 -1
  165. package/dist/cdn/select/snice-select.js +1 -1
  166. package/dist/cdn/select/snice-select.min.js +1 -1
  167. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  168. package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
  169. package/dist/cdn/slider/snice-slider.js +1 -1
  170. package/dist/cdn/slider/snice-slider.min.js +1 -1
  171. package/dist/cdn/sortable/snice-sortable.js +1 -1
  172. package/dist/cdn/sortable/snice-sortable.min.js +1 -1
  173. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  174. package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
  175. package/dist/cdn/spinner/snice-spinner.js +1 -1
  176. package/dist/cdn/spinner/snice-spinner.min.js +1 -1
  177. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  178. package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
  179. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  180. package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
  181. package/dist/cdn/spreadsheet/snice-spreadsheet.js +1 -1
  182. package/dist/cdn/spreadsheet/snice-spreadsheet.min.js +1 -1
  183. package/dist/cdn/stepper/snice-stepper.js +1 -1
  184. package/dist/cdn/stepper/snice-stepper.min.js +1 -1
  185. package/dist/cdn/switch/snice-switch.js +1 -1
  186. package/dist/cdn/switch/snice-switch.min.js +1 -1
  187. package/dist/cdn/table/snice-table.js +1 -1
  188. package/dist/cdn/table/snice-table.min.js +1 -1
  189. package/dist/cdn/tabs/snice-tabs.js +1 -1
  190. package/dist/cdn/tabs/snice-tabs.min.js +1 -1
  191. package/dist/cdn/tag-input/snice-tag-input.js +1 -1
  192. package/dist/cdn/tag-input/snice-tag-input.min.js +1 -1
  193. package/dist/cdn/terminal/snice-terminal.js +1 -1
  194. package/dist/cdn/terminal/snice-terminal.min.js +1 -1
  195. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  196. package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
  197. package/dist/cdn/textarea/snice-textarea.js +1 -1
  198. package/dist/cdn/textarea/snice-textarea.min.js +1 -1
  199. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  200. package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
  201. package/dist/cdn/timeline/snice-timeline.js +1 -1
  202. package/dist/cdn/timeline/snice-timeline.min.js +1 -1
  203. package/dist/cdn/timer/snice-timer.js +1 -1
  204. package/dist/cdn/timer/snice-timer.min.js +1 -1
  205. package/dist/cdn/toast/snice-toast.js +1 -1
  206. package/dist/cdn/toast/snice-toast.min.js +1 -1
  207. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  208. package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
  209. package/dist/cdn/tree/snice-tree.js +1 -1
  210. package/dist/cdn/tree/snice-tree.min.js +1 -1
  211. package/dist/cdn/treemap/snice-treemap.js +1 -1
  212. package/dist/cdn/treemap/snice-treemap.min.js +1 -1
  213. package/dist/cdn/video-player/snice-video-player.js +1 -1
  214. package/dist/cdn/video-player/snice-video-player.min.js +1 -1
  215. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  216. package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
  217. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  218. package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
  219. package/dist/cdn/weather/snice-weather.js +1 -1
  220. package/dist/cdn/weather/snice-weather.min.js +1 -1
  221. package/dist/components/code-block/formatter.d.ts +26 -0
  222. package/dist/components/code-block/formatter.js +245 -0
  223. package/dist/components/code-block/formatter.js.map +1 -0
  224. package/dist/components/code-block/formatters/indent.d.ts +25 -0
  225. package/dist/components/code-block/formatters/indent.js +95 -0
  226. package/dist/components/code-block/formatters/indent.js.map +1 -0
  227. package/dist/components/code-block/formatters/json.d.ts +25 -0
  228. package/dist/components/code-block/formatters/json.js +38 -0
  229. package/dist/components/code-block/formatters/json.js.map +1 -0
  230. package/dist/components/code-block/formatters/prettier.d.ts +53 -0
  231. package/dist/components/code-block/formatters/prettier.js +82 -0
  232. package/dist/components/code-block/formatters/prettier.js.map +1 -0
  233. package/dist/components/code-block/grammars/css.json +13 -0
  234. package/dist/components/code-block/grammars/json.json +13 -0
  235. package/dist/components/code-block/grammars/snice.json +14 -0
  236. package/dist/components/code-block/grammars/typescript.json +14 -0
  237. package/dist/components/code-block/highlighter.d.ts +1 -0
  238. package/dist/components/code-block/highlighter.js.map +1 -1
  239. package/dist/components/code-block/snice-code-block.d.ts +7 -1
  240. package/dist/components/code-block/snice-code-block.js +71 -2
  241. package/dist/components/code-block/snice-code-block.js.map +1 -1
  242. package/dist/components/code-block/snice-code-block.types.d.ts +11 -0
  243. package/dist/index.cjs +1 -1
  244. package/dist/index.esm.js +1 -1
  245. package/dist/index.iife.js +1 -1
  246. package/dist/symbols.cjs +1 -1
  247. package/dist/symbols.esm.js +1 -1
  248. package/dist/transitions.cjs +1 -1
  249. package/dist/transitions.esm.js +1 -1
  250. package/docs/ai/components/code-block.md +71 -0
  251. package/docs/components/code-block.md +126 -0
  252. package/package.json +1 -1
@@ -29,21 +29,146 @@ function hello() {
29
29
  | `highlightLines` | `number[]` | `[]` | Lines to highlight |
30
30
  | `copyable` | `boolean` | `true` | Show copy button |
31
31
  | `filename` | `string` | `''` | File name to display |
32
+ | `format` | `string` | `''` | Formatter name from grammar (e.g. `"pretty"`), or any truthy string with `setFormatter()` |
32
33
 
33
34
  ## Methods
34
35
 
35
36
  - `copy()` - Copy code to clipboard
36
37
  - `highlight()` - Manually trigger syntax highlighting
37
38
  - `setHighlighter(fn)` - Set an external highlighter function for this instance
39
+ - `setFormatter(fn)` - Set a code formatter function for this instance
38
40
 
39
41
  ## Events
40
42
 
41
43
  - `code-copy` - Code copied (detail: `{ code, codeBlock }`)
44
+ - `code-before-format` - Before formatting (detail: `{ code, language, codeBlock }`)
45
+ - `code-after-format` - After formatting (detail: `{ code, language, codeBlock }`)
42
46
  - `code-before-highlight` - Before highlighting (detail: `{ code, language, codeBlock }`)
43
47
  - `code-after-highlight` - After highlighting (detail: `{ code, language, codeBlock }`)
44
48
  - `grammar-request` - Grammar fetch requested (detail: `{ url, language, codeBlock }`). Only dispatched when `fetch-mode="event"`.
45
49
  - `grammar-loaded` - Grammar successfully loaded (detail: `{ grammar, url, language, codeBlock }`). Fired after grammar is fetched (native/virtual), received via event mode, or set programmatically with `setGrammar()`.
46
50
 
51
+ ## Code Formatters
52
+
53
+ Formatters transform code before syntax highlighting — useful for pretty-printing minified or poorly-indented code.
54
+
55
+ ### Grammar-Based Formatters (Declarative)
56
+
57
+ Grammars can include a `formatters` section with named declarative rule sets. Set `format` to the formatter name to use it:
58
+
59
+ ```html
60
+ <snice-code-block grammar="grammars/json.json" format="pretty" code='{"a":1,"b":[2,3]}'></snice-code-block>
61
+ ```
62
+
63
+ The grammar's `"pretty"` formatter will automatically format the code before highlighting. No JavaScript needed.
64
+
65
+ **Grammars with built-in `"pretty"` formatters:** `json.json`, `typescript.json`, `css.json`, `snice.json`.
66
+
67
+ #### Grammar Formatter Rules
68
+
69
+ Each named formatter is a set of declarative rules defined in the grammar JSON:
70
+
71
+ ```json
72
+ {
73
+ "formatters": {
74
+ "pretty": {
75
+ "tabSize": 2,
76
+ "useTabs": false,
77
+ "newlineAfter": "[{\\[,]",
78
+ "newlineBefore": "[}\\]]",
79
+ "spaceAfter": "[:]",
80
+ "indent": "[{\\[]",
81
+ "dedent": "[}\\]]",
82
+ "skipStrings": true,
83
+ "skipComments": true
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ | Field | Type | Default | Description |
90
+ |-------|------|---------|-------------|
91
+ | `tabSize` | `number` | `2` | Indent width |
92
+ | `useTabs` | `boolean` | `false` | Use tabs instead of spaces |
93
+ | `newlineAfter` | `string` (regex) | — | Insert newline after these chars |
94
+ | `newlineBefore` | `string` (regex) | — | Insert newline before these chars |
95
+ | `spaceAfter` | `string` (regex) | — | Insert space after these chars |
96
+ | `spaceBefore` | `string` (regex) | — | Insert space before these chars |
97
+ | `spaceAround` | `string` (regex) | — | Insert space on both sides |
98
+ | `indent` | `string` (regex) | — | Chars that increase indent level |
99
+ | `dedent` | `string` (regex) | — | Chars that decrease indent level |
100
+ | `trimTrailing` | `boolean` | `true` | Remove trailing whitespace per line |
101
+ | `collapseBlankLines` | `number` | — | Max consecutive blank lines |
102
+ | `skipStrings` | `boolean` | `true` | Don't apply rules inside string literals |
103
+ | `skipComments` | `boolean` | `true` | Don't apply rules inside comments |
104
+
105
+ ### Imperative Formatters
106
+
107
+ For cases requiring JavaScript logic, `setFormatter(fn)` still works. When both are present, `setFormatter()` takes priority over grammar-based formatters.
108
+
109
+ ```typescript
110
+ type FormatterFunction = (code: string, language: string) => string | Promise<string>;
111
+ ```
112
+
113
+ ### JSON Formatter
114
+
115
+ Zero-dependency formatter that pretty-prints JSON using `JSON.parse()` + `JSON.stringify()`:
116
+
117
+ ```typescript
118
+ import { createJsonFormatter } from 'snice/components/code-block/formatters/json';
119
+
120
+ const formatter = createJsonFormatter({ indent: 2 });
121
+ codeBlock.setFormatter(formatter);
122
+ codeBlock.format = 'pretty';
123
+ codeBlock.code = '{"name":"snice","version":"4.0.0"}';
124
+ ```
125
+
126
+ ### Indent Formatter
127
+
128
+ Zero-dependency indent normalizer that re-indents code by tracking brace/bracket/paren nesting depth:
129
+
130
+ ```typescript
131
+ import { createIndentFormatter } from 'snice/components/code-block/formatters/indent';
132
+
133
+ const formatter = createIndentFormatter({ tabSize: 2, useTabs: false });
134
+ codeBlock.setFormatter(formatter);
135
+ codeBlock.format = 'pretty';
136
+ ```
137
+
138
+ ### Prettier Formatter
139
+
140
+ Adapter for Prettier (requires `prettier` as a dependency):
141
+
142
+ ```typescript
143
+ import * as prettier from 'prettier/standalone';
144
+ import parserBabel from 'prettier/plugins/babel';
145
+ import parserEstree from 'prettier/plugins/estree';
146
+ import { setupPrettierFormatter } from 'snice/components/code-block/formatters/prettier';
147
+
148
+ const formatter = setupPrettierFormatter(prettier, [parserBabel, parserEstree], {
149
+ tabWidth: 2,
150
+ singleQuote: true,
151
+ });
152
+ codeBlock.setFormatter(formatter);
153
+ codeBlock.format = 'pretty';
154
+ ```
155
+
156
+ ### Whitespace Handling
157
+
158
+ Slotted content is automatically **dedented** — common leading indentation from HTML nesting is stripped while preserving relative indentation. This means code inside deeply nested HTML stays clean:
159
+
160
+ ```html
161
+ <div class="container">
162
+ <snice-code-block language="javascript">
163
+ function hello() {
164
+ console.log("world");
165
+ }
166
+ </snice-code-block>
167
+ </div>
168
+ ```
169
+
170
+ The 4-space indent from HTML nesting is stripped, but the 2-space relative indent inside the function is preserved.
171
+
47
172
  ## Grammar Files
48
173
 
49
174
  Grammars are **external JSON files** loaded on demand — the component ships with no built-in grammars to keep the bundle small.
@@ -178,6 +303,7 @@ interface Grammar {
178
303
  defaultToken?: string; // Token type for unmatched text
179
304
  ignoreCase?: boolean; // Case-insensitive regex matching
180
305
  tokenizer: Record<string, GrammarEntry[]>; // Named states
306
+ formatters?: Record<string, FormatRules>; // Named declarative formatters
181
307
  [key: string]: any; // Lookup tables (keywords, builtins, etc.)
182
308
  }
183
309
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snice",
3
- "version": "4.17.0",
3
+ "version": "4.18.0",
4
4
  "type": "module",
5
5
  "description": "Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.",
6
6
  "main": "dist/index.cjs",