@miliastry/quasar 1.0.6 → 1.2.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 (278) hide show
  1. package/README.md +1 -1
  2. package/dist/Visuals/lyne.css +374 -9
  3. package/dist/Visuals/osu.css +393 -11
  4. package/dist/index.js +10470 -3336
  5. package/dist/index.mjs +10336 -3337
  6. package/dist/types/Analysis/Contracts/AnalysisReport.d.ts +22 -0
  7. package/dist/types/Analysis/Contracts/Contribution.d.ts +68 -0
  8. package/dist/types/Analysis/Contracts/Pass.d.ts +59 -0
  9. package/dist/types/Analysis/Contracts/PipelineContext.d.ts +34 -0
  10. package/dist/types/Analysis/Passes/Analysis/ColorUsageAnalyzer.d.ts +56 -0
  11. package/dist/types/Analysis/Passes/Analysis/GradientAnalyzer.d.ts +111 -0
  12. package/dist/types/Analysis/Passes/Analysis/MergeableColorAnalyzer.d.ts +26 -0
  13. package/dist/types/Analysis/Passes/Analysis/RainbowAnalyzer.d.ts +47 -0
  14. package/dist/types/Analysis/Passes/Analysis/SymbolAnalyzer.d.ts +89 -0
  15. package/dist/types/Analysis/Passes/Analysis/WaveAnalyzer.d.ts +44 -0
  16. package/dist/types/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.d.ts +4 -0
  17. package/dist/types/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.d.ts +4 -0
  18. package/dist/types/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.d.ts +4 -0
  19. package/dist/types/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.d.ts +4 -0
  20. package/dist/types/Analysis/Passes/Decision/DefaultDecision.d.ts +30 -0
  21. package/dist/types/Analysis/Passes/Decision/PaletteRemapDecision.d.ts +169 -0
  22. package/dist/types/Analysis/Passes/Decision/__tests__/DefaultDecision.test.d.ts +4 -0
  23. package/dist/types/Analysis/Passes/Transform/CollapseGradientTransform.d.ts +37 -0
  24. package/dist/types/Analysis/Passes/Transform/MergeColorsTransform.d.ts +28 -0
  25. package/dist/types/Analysis/Passes/Transform/RainbowCollapseTransform.d.ts +19 -0
  26. package/dist/types/Analysis/Passes/Transform/WaveCollapseTransform.d.ts +20 -0
  27. package/dist/types/Analysis/Passes/Utility/CharacterCountAnalyzer.d.ts +19 -0
  28. package/dist/types/Analysis/Pipeline/Pipeline.d.ts +69 -0
  29. package/dist/types/Analysis/Pipeline/PipelineBuilder.d.ts +31 -0
  30. package/dist/types/Analysis/Pipeline/PipelineStage.d.ts +17 -0
  31. package/dist/types/Analysis/Utils/color-utils.d.ts +60 -0
  32. package/dist/types/Analysis/__tests__/Integration.test.d.ts +8 -0
  33. package/dist/types/Analysis/__tests__/PaletteRemap.test.d.ts +14 -0
  34. package/dist/types/Analysis/__tests__/Pipeline.test.d.ts +10 -0
  35. package/dist/types/Analysis/__tests__/RoundTrip.test.d.ts +30 -0
  36. package/dist/types/Analysis/__tests__/SymbolAnalyzer.test.d.ts +11 -0
  37. package/dist/types/Analysis/index.d.ts +40 -0
  38. package/dist/types/BBCode/BBCodeDocumentModel.d.ts +102 -0
  39. package/dist/types/BBCode/BBCodeToGreenNode.d.ts +111 -0
  40. package/dist/types/BBCode/Parser.d.ts +78 -0
  41. package/dist/types/BBCode/index.d.ts +4 -0
  42. package/dist/types/Collab/positions.d.ts +55 -0
  43. package/dist/types/Commands/Command.d.ts +37 -0
  44. package/dist/types/Commands/CommandRegistry.d.ts +48 -0
  45. package/dist/types/Commands/DeleteNode.d.ts +7 -0
  46. package/dist/types/Commands/InsertText.d.ts +8 -0
  47. package/dist/types/Commands/SplitMerge.d.ts +9 -0
  48. package/dist/types/Commands/WrapInTag.d.ts +8 -0
  49. package/dist/types/Commands/index.d.ts +6 -0
  50. package/dist/types/Diff/TreeDiffer.d.ts +52 -0
  51. package/dist/types/Diff/__tests__/TreeDiffer.test.d.ts +1 -0
  52. package/dist/types/Diff/index.d.ts +2 -0
  53. package/dist/types/Edits/EditPlan.d.ts +144 -0
  54. package/dist/types/Edits/Optimizer.d.ts +78 -0
  55. package/dist/types/Edits/Rules/Rule.d.ts +91 -0
  56. package/dist/types/Edits/Rules/dropEmptyTags.d.ts +40 -0
  57. package/dist/types/Edits/Rules/dropRedundantNesting.d.ts +59 -0
  58. package/dist/types/Edits/Rules/index.d.ts +9 -0
  59. package/dist/types/Edits/Rules/mergeAdjacent.d.ts +93 -0
  60. package/dist/types/Edits/Rules/reorderWrappers.d.ts +42 -0
  61. package/dist/types/Edits/Rules/shortenHex.d.ts +30 -0
  62. package/dist/types/Edits/Rules/tagValue.d.ts +56 -0
  63. package/dist/types/Edits/Rules/unwrapInvisibleColor.d.ts +47 -0
  64. package/dist/types/Edits/applyEdits.d.ts +36 -0
  65. package/dist/types/Edits/index.d.ts +6 -0
  66. package/dist/types/Events/EventBus.d.ts +103 -0
  67. package/dist/types/Events/index.d.ts +2 -0
  68. package/dist/types/Formatter/Formatter.d.ts +32 -0
  69. package/dist/types/Formatter/index.d.ts +2 -0
  70. package/dist/types/HTML/HTMLDocumentModel.d.ts +13 -0
  71. package/dist/types/HTML/HTMLToGreenNode.d.ts +4 -0
  72. package/dist/types/Incremental/BracketIndex.d.ts +101 -0
  73. package/dist/types/Incremental/ChangeTracker.d.ts +69 -0
  74. package/dist/types/Incremental/IncrementalParser.d.ts +246 -0
  75. package/dist/types/Incremental/__tests__/BracketIndex.test.d.ts +1 -0
  76. package/dist/types/Incremental/__tests__/IncrementalParser.test.d.ts +1 -0
  77. package/dist/types/Incremental/index.d.ts +4 -0
  78. package/dist/types/Lexer/BBCodeLexer.d.ts +74 -0
  79. package/dist/types/Lexer/Lexer.d.ts +54 -0
  80. package/dist/types/Lexer/index.d.ts +4 -0
  81. package/dist/types/Linter/Linter.d.ts +58 -0
  82. package/dist/types/Linter/index.d.ts +2 -0
  83. package/dist/types/Markdown/MarkdownAST.d.ts +122 -0
  84. package/dist/types/Markdown/MarkdownDocumentModel.d.ts +15 -0
  85. package/dist/types/Markdown/MarkdownLexer.d.ts +155 -0
  86. package/dist/types/Markdown/MarkdownParser.d.ts +42 -0
  87. package/dist/types/Markdown/MarkdownToGreenNode.d.ts +6 -0
  88. package/dist/types/MilHibri/MilHibriDocumentModel.d.ts +21 -0
  89. package/dist/types/Model/DocumentModel.d.ts +318 -0
  90. package/dist/types/Model/NodeFactory.d.ts +29 -0
  91. package/dist/types/Model/TagRegistry.d.ts +165 -0
  92. package/dist/types/Model/index.d.ts +5 -0
  93. package/dist/types/Plugins/PluginAPI.d.ts +44 -0
  94. package/dist/types/Plugins/PluginRegistry.d.ts +81 -0
  95. package/dist/types/Plugins/index.d.ts +3 -0
  96. package/dist/types/Queries/QueryEngine.d.ts +32 -0
  97. package/dist/types/Queries/index.d.ts +1 -0
  98. package/dist/types/Reconciler/SurgicalReconciler.d.ts +23 -0
  99. package/dist/types/RenderPipeline/RenderPipeline.d.ts +46 -0
  100. package/dist/types/RenderPipeline/RenderTree.d.ts +55 -0
  101. package/dist/types/RenderPipeline/index.d.ts +4 -0
  102. package/dist/types/Repair/NestingRepair.d.ts +48 -0
  103. package/dist/types/Repair/index.d.ts +1 -0
  104. package/dist/types/Semantic/SemanticAnalyzer.d.ts +321 -0
  105. package/dist/types/Semantic/index.d.ts +2 -0
  106. package/dist/types/Symbols/SymbolTable.d.ts +47 -0
  107. package/dist/types/Symbols/index.d.ts +1 -0
  108. package/dist/types/Syntax/GreenNode.d.ts +154 -0
  109. package/dist/types/Syntax/GreenNodePool.d.ts +134 -0
  110. package/dist/types/Syntax/NodeMatcher.d.ts +75 -0
  111. package/dist/types/Syntax/RedNode.d.ts +280 -0
  112. package/dist/types/Syntax/RedNodeStore.d.ts +116 -0
  113. package/dist/types/Syntax/TreeBuilder.d.ts +54 -0
  114. package/dist/types/Syntax/__tests__/GreenNode.test.d.ts +1 -0
  115. package/dist/types/Syntax/__tests__/RedNode.test.d.ts +1 -0
  116. package/dist/types/Syntax/__tests__/RedNodeStore.test.d.ts +1 -0
  117. package/dist/types/Syntax/greenEdit.d.ts +64 -0
  118. package/dist/types/Syntax/hash.d.ts +17 -0
  119. package/dist/types/Syntax/index.d.ts +8 -0
  120. package/dist/types/Syntax/nodeAttr.d.ts +63 -0
  121. package/dist/types/Syntax/partition.d.ts +67 -0
  122. package/dist/types/Syntax/preserveNodeIds.d.ts +47 -0
  123. package/dist/types/Tokens/TokenResolver.d.ts +25 -0
  124. package/dist/types/Tokens/index.d.ts +1 -0
  125. package/dist/types/Transactions/Transaction.d.ts +36 -0
  126. package/dist/types/Transactions/UndoManager.d.ts +63 -0
  127. package/dist/types/Transactions/index.d.ts +3 -0
  128. package/dist/types/Transformers/ASTOptimizer.d.ts +34 -0
  129. package/dist/types/Transformers/GradientTransformer.d.ts +18 -0
  130. package/dist/types/Transformers/GrowTransformer.d.ts +16 -0
  131. package/dist/types/Transformers/RainbowTransformer.d.ts +17 -0
  132. package/dist/types/Transformers/SineWaveTransformer.d.ts +17 -0
  133. package/dist/types/Transformers/Transformer.d.ts +17 -0
  134. package/dist/types/Types/core.d.ts +104 -0
  135. package/dist/types/Types/diagnostics.d.ts +85 -0
  136. package/dist/types/Types/index.d.ts +11 -0
  137. package/dist/types/Types/operations.d.ts +109 -0
  138. package/dist/types/Types/queries.d.ts +67 -0
  139. package/dist/types/Types/symbols.d.ts +42 -0
  140. package/dist/types/Types/tokens.d.ts +75 -0
  141. package/dist/types/Utils/BBCodeGenerator.d.ts +21 -0
  142. package/dist/types/Utils/ColorMath.d.ts +92 -0
  143. package/dist/types/Utils/EffectMath.d.ts +643 -0
  144. package/dist/types/Utils/TagVocabulary.d.ts +104 -0
  145. package/dist/types/Utils/TagVocabulary.test.d.ts +1 -0
  146. package/dist/types/Utils/color.d.ts +29 -0
  147. package/dist/types/Utils/dom-to-svg.d.ts +28 -0
  148. package/dist/types/Utils/dom-to-svg.test.d.ts +1 -0
  149. package/dist/types/Utils/treeTransformers.d.ts +160 -0
  150. package/dist/types/Visitors/BBBlocksExporter.d.ts +27 -0
  151. package/dist/types/Visitors/BBCodeExporter.d.ts +90 -0
  152. package/dist/types/Visitors/BlockPatcher.d.ts +91 -0
  153. package/dist/types/Visitors/DOMMorpher.d.ts +19 -0
  154. package/dist/types/Visitors/HTMLRenderer.d.ts +492 -0
  155. package/dist/types/Visitors/JSONExporter.d.ts +42 -0
  156. package/dist/types/Visitors/MarkdownExporter.d.ts +28 -0
  157. package/dist/types/Visitors/SVGRenderer.d.ts +16 -0
  158. package/dist/types/Visitors/TiptapExporter.d.ts +40 -0
  159. package/dist/types/Visitors/Visitor.d.ts +35 -0
  160. package/dist/types/Visitors/index.d.ts +9 -0
  161. package/dist/types/Visuals/BoxDrawer.d.ts +54 -0
  162. package/dist/types/Visuals/LyneAudio.d.ts +8 -0
  163. package/dist/types/Visuals/index.d.ts +39 -0
  164. package/dist/types/index.d.ts +155 -0
  165. package/package.json +14 -10
  166. package/src/Analysis/Passes/Analysis/ColorUsageAnalyzer.ts +103 -0
  167. package/src/Analysis/Passes/Analysis/GradientAnalyzer.ts +294 -20
  168. package/src/Analysis/Passes/Analysis/SymbolAnalyzer.ts +257 -0
  169. package/src/Analysis/Passes/Decision/PaletteRemapDecision.ts +425 -0
  170. package/src/Analysis/Pipeline/Pipeline.ts +15 -2
  171. package/src/Analysis/index.ts +8 -2
  172. package/src/BBCode/BBCodeDocumentModel.ts +39 -1
  173. package/src/BBCode/BBCodeToGreenNode.ts +18 -12
  174. package/src/BBCode/Parser.ts +38 -1
  175. package/src/Edits/EditPlan.ts +290 -0
  176. package/src/Edits/Optimizer.ts +185 -0
  177. package/src/Edits/Rules/Rule.ts +145 -0
  178. package/src/Edits/Rules/dropEmptyTags.ts +110 -0
  179. package/src/Edits/Rules/dropRedundantNesting.ts +120 -0
  180. package/src/Edits/Rules/index.ts +28 -0
  181. package/src/Edits/Rules/mergeAdjacent.ts +224 -0
  182. package/src/Edits/Rules/reorderWrappers.ts +154 -0
  183. package/src/Edits/Rules/shortenHex.ts +79 -0
  184. package/src/Edits/Rules/tagValue.ts +105 -0
  185. package/src/Edits/Rules/unwrapInvisibleColor.ts +93 -0
  186. package/src/Edits/applyEdits.ts +54 -0
  187. package/src/Edits/index.ts +22 -0
  188. package/src/Events/EventBus.ts +18 -0
  189. package/src/HTML/HTMLToGreenNode.ts +193 -37
  190. package/src/Incremental/BracketIndex.ts +249 -0
  191. package/src/Incremental/IncrementalParser.ts +464 -41
  192. package/src/Lexer/BBCodeLexer.ts +25 -3
  193. package/src/Lexer/index.ts +1 -1
  194. package/src/Markdown/MarkdownAST.ts +65 -2
  195. package/src/Markdown/MarkdownLexer.ts +69 -14
  196. package/src/Markdown/MarkdownParser.ts +749 -62
  197. package/src/Markdown/MarkdownToGreenNode.ts +148 -27
  198. package/src/MilHibri/MilHibriDocumentModel.ts +56 -0
  199. package/src/Model/DocumentModel.ts +138 -5
  200. package/src/Model/TagRegistry.ts +129 -134
  201. package/src/Reconciler/SurgicalReconciler.ts +460 -0
  202. package/src/Repair/NestingRepair.ts +116 -0
  203. package/src/Repair/index.ts +1 -0
  204. package/src/Semantic/SemanticAnalyzer.ts +1845 -65
  205. package/src/Syntax/GreenNodePool.ts +12 -12
  206. package/src/Syntax/RedNode.ts +17 -3
  207. package/src/Syntax/RedNodeStore.ts +9 -1
  208. package/src/Syntax/nodeAttr.ts +172 -0
  209. package/src/Tokens/TokenResolver.ts +55 -0
  210. package/src/Tokens/index.ts +1 -0
  211. package/src/Types/core.ts +15 -0
  212. package/src/Utils/ColorMath.ts +276 -55
  213. package/src/Utils/EffectMath.ts +2462 -0
  214. package/src/Utils/TagVocabulary.ts +141 -0
  215. package/src/Utils/dom-to-svg.ts +28 -12
  216. package/src/Visitors/BBBlocksExporter.ts +15 -1
  217. package/src/Visitors/BBCodeExporter.ts +365 -32
  218. package/src/Visitors/BlockPatcher.ts +123 -22
  219. package/src/Visitors/DOMMorpher.ts +44 -28
  220. package/src/Visitors/HTMLRenderer.ts +771 -205
  221. package/src/Visitors/MarkdownExporter.ts +98 -41
  222. package/src/Visitors/TiptapExporter.ts +1 -0
  223. package/src/Visitors/index.ts +1 -1
  224. package/src/Visuals/BoxDrawer.ts +56 -10
  225. package/src/Visuals/LyneAudio.ts +346 -0
  226. package/src/Visuals/index.ts +8 -4
  227. package/src/Visuals/lyne.css +374 -9
  228. package/src/Visuals/osu.css +393 -11
  229. package/src/index.ts +178 -8
  230. package/dist/index.d.mts +0 -4612
  231. package/dist/index.d.ts +0 -4612
  232. package/src/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.ts +0 -135
  233. package/src/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.ts +0 -84
  234. package/src/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.ts +0 -99
  235. package/src/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.ts +0 -119
  236. package/src/Analysis/Passes/Decision/__tests__/DefaultDecision.test.ts +0 -179
  237. package/src/Analysis/__tests__/Integration.test.ts +0 -162
  238. package/src/Analysis/__tests__/Pipeline.test.ts +0 -133
  239. package/src/Diff/__tests__/TreeDiffer.test.ts +0 -65
  240. package/src/Incremental/__tests__/IncrementalParser.test.ts +0 -164
  241. package/src/Syntax/__tests__/GreenNode.test.ts +0 -33
  242. package/src/Syntax/__tests__/RedNode.test.ts +0 -81
  243. package/src/Syntax/__tests__/RedNodeStore.test.ts +0 -104
  244. package/src/Tests/ASTOptimizerIdempotence.test.ts +0 -77
  245. package/src/Tests/BlockPatcher.test.ts +0 -437
  246. package/src/Tests/BlockPatcherWindowed.test.ts +0 -364
  247. package/src/Tests/BoxDrawer.test.ts +0 -217
  248. package/src/Tests/BoxRichTitle.test.ts +0 -105
  249. package/src/Tests/Chars500kBenchmark.test.ts +0 -151
  250. package/src/Tests/Chars500kEdits.test.ts +0 -321
  251. package/src/Tests/CollabPositions.test.ts +0 -146
  252. package/src/Tests/CompilerPathProfiling.test.ts +0 -186
  253. package/src/Tests/DOMMorpher.test.ts +0 -142
  254. package/src/Tests/DomPatchPerf.test.ts +0 -60
  255. package/src/Tests/EffectSegments.snapshot.json +0 -616
  256. package/src/Tests/EffectSegments.test.ts +0 -68
  257. package/src/Tests/FindNodeAtOffset.test.ts +0 -65
  258. package/src/Tests/Fuzzer.test.ts +0 -166
  259. package/src/Tests/GreenNodePool.test.ts +0 -153
  260. package/src/Tests/Lexer.test.ts +0 -238
  261. package/src/Tests/LyneMode.test.ts +0 -291
  262. package/src/Tests/ModelCoherence.test.ts +0 -180
  263. package/src/Tests/Partition.test.ts +0 -238
  264. package/src/Tests/PluginTags.test.ts +0 -150
  265. package/src/Tests/ProblematicSection.test.ts +0 -46
  266. package/src/Tests/ProblematicSectionHTML.test.ts +0 -58
  267. package/src/Tests/RedReuse.test.ts +0 -134
  268. package/src/Tests/ReproDelete20k.test.ts +0 -62
  269. package/src/Tests/SemanticValidators.test.ts +0 -136
  270. package/src/Tests/StableNodeIds.test.ts +0 -210
  271. package/src/Tests/StudioColorBloat.test.ts +0 -25
  272. package/src/Tests/StudioDebugText.test.ts +0 -27
  273. package/src/Tests/StudioTrailingChar.test.ts +0 -25
  274. package/src/Tests/StudioValidText.test.ts +0 -25
  275. package/src/Tests/UrlImgBug.test.ts +0 -23
  276. package/src/Tests/VisualBuilderFidelity.test.ts +0 -105
  277. package/src/Tests/referenceDocument.ts +0 -119
  278. package/src/Utils/dom-to-svg.test.ts +0 -86
@@ -0,0 +1,643 @@
1
+ import { type ColorStop } from './ColorMath';
2
+ /** FNV-1a over a string → 32-bit unsigned seed. */
3
+ export declare function hashSeed(input: string): number;
4
+ /**
5
+ * Stateless hash → [0,1) for one (seed, index) pair.
6
+ *
7
+ * Stateless matters: layers are evaluated per text node and per range, in
8
+ * an order the user can change by dragging. A stateful generator would
9
+ * hand character #7 a different number depending on how the document was
10
+ * split into nodes. Addressing by index makes the value a pure function
11
+ * of the character's position.
12
+ */
13
+ export declare function randAt(seed: number, index: number): number;
14
+ /** Smooth (cosine-interpolated) value noise over a 1-D axis. */
15
+ export declare function valueNoise(x: number, seed: number): number;
16
+ /** Fractal Brownian motion: octaves of value noise at halving amplitude. */
17
+ export declare function fbm(x: number, seed: number, octaves?: number): number;
18
+ /**
19
+ * Variables an `expr(...)` waveform can read.
20
+ *
21
+ * `u` is the raw axis position, `t` its alias, `i`/`n` the character's
22
+ * index and the unit count, `line`/`col` its 2-D address, and `rnd` a
23
+ * deterministic per-character random draw.
24
+ */
25
+ export interface ExpressionVars {
26
+ u: number;
27
+ t: number;
28
+ x: number;
29
+ i: number;
30
+ n: number;
31
+ line: number;
32
+ lines: number;
33
+ col: number;
34
+ cols: number;
35
+ word: number;
36
+ words: number;
37
+ rnd: number;
38
+ }
39
+ export declare const EXPRESSION_VARS: readonly (keyof ExpressionVars)[];
40
+ export type CompiledExpression = (vars: ExpressionVars) => number;
41
+ /**
42
+ * Validate that `src` is pure arithmetic over the allowed vocabulary.
43
+ *
44
+ * The check is allowlist-based in both directions: every identifier must
45
+ * be a known variable or `Math` member, and every remaining character
46
+ * must be an operator or a digit. That rejects property access
47
+ * (`constructor`, `__proto__`), string and template literals, array and
48
+ * object syntax, and statement separators — the whole surface an
49
+ * injected payload would need — without trying to enumerate attacks.
50
+ */
51
+ export declare function validateExpression(src: string): {
52
+ ok: true;
53
+ } | {
54
+ ok: false;
55
+ reason: string;
56
+ };
57
+ /** Compile a validated expression, or return null if it is rejected. */
58
+ export declare function compileExpression(src: string): CompiledExpression | null;
59
+ export type WaveKind = 'none' | 'sine' | 'cosine' | 'triangle' | 'sawtooth' | 'square' | 'bounce' | 'elastic' | 'exponential' | 'pulse' | 'edges' | 'alternate' | 'noise' | 'fbm' | 'steps' | 'bezier' | 'expr';
60
+ export declare const WAVE_KINDS: readonly WaveKind[];
61
+ export interface WaveOptions {
62
+ /** How many times the waveform repeats across the axis. */
63
+ cycles: number;
64
+ /** Shifts the waveform along the axis, in cycles. */
65
+ phase: number;
66
+ /** Control points for `bezier`. */
67
+ bezier: readonly [number, number, number, number];
68
+ /** Source for `expr`. */
69
+ expression?: string;
70
+ /** Octaves for `fbm`. */
71
+ octaves: number;
72
+ /** Quantisation levels for `steps`, and post-quantisation for any wave. */
73
+ steps: number;
74
+ /** Seed for `noise` / `fbm`. */
75
+ seed: number;
76
+ /** Index used to address deterministic noise and index-parity waves. */
77
+ index: number;
78
+ /** Unit count in the scope, for index-based waves. */
79
+ count: number;
80
+ /** Full variable bag, for `expr`. */
81
+ vars?: ExpressionVars;
82
+ }
83
+ export declare const DEFAULT_WAVE_OPTIONS: WaveOptions;
84
+ /**
85
+ * Evaluate a waveform at axis position `u`, returning [0,1].
86
+ *
87
+ * `cycles`/`phase` are applied first so every periodic wave shares one
88
+ * notion of frequency, and the non-periodic ones (`bezier`, `steps`,
89
+ * `edges`) read the wrapped position too so a cycles slider still does
90
+ * something sensible for them.
91
+ */
92
+ export declare function waveform(kind: WaveKind, u: number, opts?: Partial<WaveOptions>): number;
93
+ export declare function clamp01(v: number): number;
94
+ export type BlendMode = 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'colorDodge' | 'colorBurn' | 'hardLight' | 'softLight' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
95
+ export declare const BLEND_MODES: readonly BlendMode[];
96
+ /**
97
+ * Composite `layer` over `base` with a blend mode and opacity.
98
+ *
99
+ * Follows the W3C compositing spec (the same maths Photoshop uses), so
100
+ * the separable modes match what a designer expects and the four
101
+ * non-separable ones (hue/saturation/color/luminosity) transplant one
102
+ * property while preserving the rest.
103
+ */
104
+ export declare function blendHex(base: string, layer: string, mode: BlendMode, opacity?: number): string;
105
+ export declare function rgbToHex(r: number, g: number, b: number): string;
106
+ /** Shift or set a colour's HSL components. Amounts are absolute. */
107
+ export declare function adjustHsl(hex: string, opts: {
108
+ hue?: number;
109
+ sat?: number;
110
+ light?: number;
111
+ absolute?: boolean;
112
+ }): string;
113
+ /** Snap each channel to `levels` evenly spaced values. */
114
+ export declare function posterizeHex(hex: string, levels: number): string;
115
+ export declare function clampRange(v: number, min: number, max: number): number;
116
+ /** One character's address within the document. */
117
+ export interface CharSample {
118
+ /** Code-point offset in the plain text. */
119
+ offset: number;
120
+ /** True for whitespace, which carries no visual index. */
121
+ isSpace: boolean;
122
+ /** Running index among non-whitespace characters, document-wide. -1 for spaces. */
123
+ index: number;
124
+ /** Zero-based line number. */
125
+ line: number;
126
+ /** Running index among non-whitespace characters within the line. -1 for spaces. */
127
+ col: number;
128
+ /**
129
+ * Visual column: every character on the line counted, spaces included.
130
+ *
131
+ * `col` deliberately skips whitespace so a gradient does not spend a
132
+ * step of its ramp on a space — the right rule for a ramp, and the
133
+ * wrong one for a picture. In ASCII art the spaces ARE the layout, so
134
+ * `" \u2588\u2588"` has its blocks at visual columns 2 and 3 while `col`
135
+ * calls them 0 and 1. A spatial effect that read `col` would shear
136
+ * every line left by its own indentation.
137
+ *
138
+ * Both coordinates therefore exist side by side: `col` for ramps,
139
+ * `rawCol` for geometry.
140
+ */
141
+ rawCol: number;
142
+ /** Zero-based word number, document-wide. -1 for spaces. */
143
+ word: number;
144
+ }
145
+ /** The whole document's coordinate table. */
146
+ export interface SampleTable {
147
+ /** One entry per code point of the plain text. */
148
+ samples: CharSample[];
149
+ /** Non-whitespace character count. */
150
+ count: number;
151
+ lineCount: number;
152
+ /** Non-whitespace character count per line. */
153
+ lineLengths: number[];
154
+ /** Every-character length per line, for geometry. */
155
+ rawLineLengths: number[];
156
+ /** The widest line, in visual columns. The grid's width. */
157
+ maxCols: number;
158
+ wordCount: number;
159
+ }
160
+ /**
161
+ * Build the coordinate table for a plain-text document.
162
+ *
163
+ * Whitespace is addressed but never indexed: it keeps its offset and line
164
+ * so ranges can span it, but gets `index = -1` so it does not consume a
165
+ * step of a gradient. That is what stops "a b" from spending a third of
166
+ * its colour ramp on the space.
167
+ */
168
+ export declare function buildSampleTable(plainText: string): SampleTable;
169
+ /**
170
+ * A character range with its own local coordinate system.
171
+ *
172
+ * Local matters: a gradient applied to characters 40–60 should run its
173
+ * full ramp across those twenty characters, not show the slice of a
174
+ * document-wide ramp that happens to fall there. Every layer reads local
175
+ * coordinates; only `sample` keeps the document-wide ones, for effects
176
+ * that deliberately want the global picture.
177
+ */
178
+ export interface RangeScope {
179
+ start: number;
180
+ end: number;
181
+ /** Non-whitespace count inside the range. */
182
+ count: number;
183
+ /** Local index per offset, `-1` for whitespace and out-of-range. */
184
+ localIndex: Int32Array;
185
+ /** Local line number per offset, `-1` out of range. */
186
+ localLine: Int32Array;
187
+ /** Local column per offset, `-1` for whitespace and out-of-range. */
188
+ localCol: Int32Array;
189
+ /** Local word number per offset, `-1` for whitespace and out-of-range. */
190
+ localWord: Int32Array;
191
+ /**
192
+ * Visual column per offset, spaces counted, `-1` out of range.
193
+ *
194
+ * Unlike `localCol` this is NOT re-based per line: it keeps the
195
+ * document's own column so a range starting mid-line still sits where
196
+ * the reader sees it. `rawColMin`/`rawColMax` carry the bounding box
197
+ * that turns it into a [0,1] coordinate.
198
+ */
199
+ localRawCol: Int32Array;
200
+ /** Left edge of the range's painted bounding box, in visual columns. */
201
+ rawColMin: number;
202
+ /** Right edge of that box. Equal to `rawColMin` for a single column. */
203
+ rawColMax: number;
204
+ lineCount: number;
205
+ lineLengths: number[];
206
+ wordCount: number;
207
+ }
208
+ /**
209
+ * Derive a range's local coordinate system from the document table.
210
+ *
211
+ * Cost is O(range length) and it is computed once per compile per range,
212
+ * which is what lets `applyLayer` be a straight indexed lookup no matter
213
+ * how many layers the range stacks.
214
+ */
215
+ export declare function buildRangeScope(table: SampleTable, start: number, end: number): RangeScope;
216
+ /** A scope covering the whole document. */
217
+ export declare function documentScope(table: SampleTable): RangeScope;
218
+ /**
219
+ * How a character's address collapses into the single number `u ∈ [0,1]`
220
+ * that drives a layer.
221
+ */
222
+ export type Axis = 'index' | 'word' | 'line' | 'column' | 'diagonal' | 'radial' | 'angular' | 'random' | 'wave' | 'spot' | 'sweep' | 'linear';
223
+ export declare const AXES: readonly Axis[];
224
+ /** Axes that read an origin, an angle and a radius. */
225
+ export declare const SPATIAL_AXES: ReadonlySet<Axis>;
226
+ /** Everything a layer needs to place one character. */
227
+ export interface SampleContext {
228
+ sample: CharSample;
229
+ scope: RangeScope;
230
+ table: SampleTable;
231
+ /** Local index within the scope, `-1` for whitespace. */
232
+ local: number;
233
+ }
234
+ /**
235
+ * Width ÷ height of one character cell.
236
+ *
237
+ * Monospace faces cluster around 0.5–0.6; this is the middle of that
238
+ * range and the value every shape assumes unless the document says
239
+ * otherwise.
240
+ */
241
+ export declare const DEFAULT_CELL_ASPECT = 0.55;
242
+ /** Where a placeable effect sits and how far it reaches. */
243
+ export interface SpatialOptions {
244
+ /** Origin across the box, 0 = left edge, 1 = right edge. */
245
+ originX: number;
246
+ /** Origin down the box, 0 = top, 1 = bottom. */
247
+ originY: number;
248
+ /** Rotation of `linear` and `sweep`, in degrees, clockwise from east. */
249
+ angle: number;
250
+ /** Reach of `spot` and `linear`, in units of the box's longer side. */
251
+ radius: number;
252
+ /** Width ÷ height of a character cell. */
253
+ aspect: number;
254
+ }
255
+ export declare const DEFAULT_SPATIAL: SpatialOptions;
256
+ /**
257
+ * A character's place on the page, in a square-ish coordinate system.
258
+ *
259
+ * `x`/`y` are the plain [0,1] fractions across the range's painted
260
+ * bounding box. `w`/`h` are that box's physical proportions, normalised
261
+ * so the longer side is 1 — multiplying the fractions by them is what
262
+ * makes a circle round instead of an oval.
263
+ *
264
+ * A single-line range has no vertical extent, so every character reports
265
+ * `y = 0.5`: the text is one line tall and sits at its own middle. The
266
+ * same holds for `x` in a single-column range.
267
+ */
268
+ export interface SpatialPoint {
269
+ x: number;
270
+ y: number;
271
+ w: number;
272
+ h: number;
273
+ }
274
+ export declare function spatialPoint(ctx: SampleContext, cellAspect?: number): SpatialPoint;
275
+ /**
276
+ * Project a character onto the [0,1] axis a layer reads.
277
+ *
278
+ * `radial` and `angular` treat the range as a rectangle of lines by
279
+ * columns, which is what makes a multi-line block behave like a canvas
280
+ * rather than a single ribbon of text. They are centred and uncorrected,
281
+ * and stay that way: documents written against them must keep rendering
282
+ * identically. `spot`, `sweep` and `linear` are their placeable,
283
+ * aspect-corrected successors — same idea, with an origin the author
284
+ * chooses and a circle that comes out round.
285
+ */
286
+ export declare function axisValue(axis: Axis, ctx: SampleContext, seed?: number, geo?: Partial<SpatialOptions>): number;
287
+ export type MaskShape = 'none' | 'circle' | 'ellipse' | 'square' | 'rect' | 'diamond' | 'triangle' | 'star' | 'ring' | 'half';
288
+ export declare const MASK_SHAPES: readonly MaskShape[];
289
+ /** Placement and form of one layer's mask. */
290
+ export interface MaskOptions {
291
+ shape: MaskShape;
292
+ /** Centre across the box, 0 = left edge, 1 = right edge. */
293
+ x: number;
294
+ /** Centre down the box, 0 = top, 1 = bottom. */
295
+ y: number;
296
+ /** Half-width, in units of the box's longer side. */
297
+ width: number;
298
+ /** Half-height. Read only by `ellipse` and `rect`. */
299
+ height: number;
300
+ /** Rotation in degrees, clockwise. */
301
+ rotate: number;
302
+ /**
303
+ * Width of the soft edge, in the same units as `width`.
304
+ *
305
+ * Zero gives a hard cut — the right choice for block art, where a
306
+ * half-lit character reads as a mistake. Anything above it fades, which
307
+ * is what stops a circle over prose from looking stamped on.
308
+ */
309
+ feather: number;
310
+ /** Keep what falls OUTSIDE the shape instead of inside. */
311
+ invert: boolean;
312
+ /** Points, for `star`. */
313
+ points: number;
314
+ /** Spike depth for `star` (0 = thin, 1 = polygon); thickness for `ring`. */
315
+ inner: number;
316
+ /** Width ÷ height of a character cell. */
317
+ aspect: number;
318
+ }
319
+ export declare const DEFAULT_MASK: MaskOptions;
320
+ /**
321
+ * Signed distance from a character to a shape's edge, negative inside.
322
+ *
323
+ * Exported so a preview can draw the outline from the same maths that
324
+ * decides which characters the shape covers. Two implementations of a
325
+ * shape is two shapes.
326
+ */
327
+ export declare function maskDistance(ctx: SampleContext, opts?: Partial<MaskOptions>): number;
328
+ /**
329
+ * How strongly a mask covers one character, in [0,1].
330
+ *
331
+ * 1 is fully inside, 0 fully outside. A layer multiplies its opacity by
332
+ * this, so a masked layer composites exactly like an unmasked one at
333
+ * reduced strength — no separate code path, and stacking three masked
334
+ * layers is the same operation as stacking three plain ones.
335
+ */
336
+ export declare function maskValue(ctx: SampleContext, opts?: Partial<MaskOptions>): number;
337
+ /** Build the variable bag an `expr()` waveform sees for one character. */
338
+ export declare function expressionVars(ctx: SampleContext, u: number, seed: number): {
339
+ u: number;
340
+ t: number;
341
+ x: number;
342
+ i: number;
343
+ n: number;
344
+ line: number;
345
+ lines: number;
346
+ col: number;
347
+ cols: number;
348
+ word: number;
349
+ words: number;
350
+ rnd: number;
351
+ };
352
+ /** Palette entries a grid can name, the transparent slot excluded. */
353
+ export declare const PAINT_MAX_COLORS: number;
354
+ /** An image reduced to something a tag can carry. */
355
+ export interface PaintGrid {
356
+ cols: number;
357
+ rows: number;
358
+ /** Hex colours, `#RRGGBB`. At most `PAINT_MAX_COLORS` of them. */
359
+ palette: string[];
360
+ /** `rows * cols` indices into `palette`; `-1` paints nothing. */
361
+ cells: Int16Array;
362
+ }
363
+ /** Serialise a grid's cells to the alphabet. */
364
+ export declare function stringifyPaintCells(grid: PaintGrid): string;
365
+ /**
366
+ * Read a grid back from its parts.
367
+ *
368
+ * Returns `null` rather than a partial grid when the cell count does not
369
+ * match `cols * rows`: a grid off by one cell is sheared diagonally
370
+ * across the whole paragraph, which is far worse than not painting.
371
+ */
372
+ export declare function parsePaintGrid(cols: number, rows: number, paletteStr: string, cellsStr: string): PaintGrid | null;
373
+ /** Serialise a palette to the attribute form, `#` stripped. */
374
+ export declare function stringifyPaintPalette(palette: readonly string[]): string;
375
+ /**
376
+ * The colour a grid paints at a point of the box, or `undefined` for a
377
+ * hole.
378
+ *
379
+ * `smooth` interpolates between the four surrounding cells, which is what
380
+ * you want over prose — the grid is coarser than the text and hard cells
381
+ * read as banding. It is the wrong choice for block art, where the grid
382
+ * and the characters line up one to one and any interpolation invents
383
+ * colours that belong to neither neighbour, so it defaults off.
384
+ */
385
+ export declare function samplePaintGrid(grid: PaintGrid, x: number, y: number, smooth?: boolean, perceptual?: boolean): string | undefined;
386
+ /** Everything an effect tag can carry, after parsing. */
387
+ export interface EffectParams {
388
+ /** Colour list for gradient / rainbow ramps. */
389
+ colors?: string[];
390
+ /** Raw stop list, positions included. */
391
+ stops?: ColorStop[];
392
+ axis?: Axis;
393
+ wave?: WaveKind;
394
+ cycles?: number;
395
+ phase?: number;
396
+ easing?: string;
397
+ bezier?: [number, number, number, number];
398
+ parabolaCenter?: number;
399
+ parabolaPower?: number;
400
+ invert?: boolean;
401
+ steps?: number;
402
+ octaves?: number;
403
+ expression?: string;
404
+ seed?: number;
405
+ unit?: EffectUnit;
406
+ opacity?: number;
407
+ perceptual?: boolean;
408
+ saturation?: number;
409
+ lightness?: number;
410
+ spread?: number;
411
+ offset?: number;
412
+ preserveSL?: boolean;
413
+ min?: number;
414
+ max?: number;
415
+ freq?: number;
416
+ step?: 'char' | 'word';
417
+ originX?: number;
418
+ originY?: number;
419
+ /** Degrees, clockwise from east. */
420
+ angle?: number;
421
+ /** Reach, in units of the box's longer side. */
422
+ radius?: number;
423
+ /** Width \u00f7 height of a character cell. */
424
+ aspect?: number;
425
+ maskShape?: MaskShape;
426
+ maskX?: number;
427
+ maskY?: number;
428
+ maskWidth?: number;
429
+ maskHeight?: number;
430
+ maskRotate?: number;
431
+ maskFeather?: number;
432
+ maskInvert?: boolean;
433
+ maskPoints?: number;
434
+ maskInner?: number;
435
+ gridCols?: number;
436
+ gridRows?: number;
437
+ /** Comma-separated hex colours, `#` stripped. */
438
+ palette?: string;
439
+ /** One character per cell, in the paint alphabet. */
440
+ cells?: string;
441
+ /** Interpolate between cells instead of snapping to the nearest. */
442
+ smooth?: boolean;
443
+ /**
444
+ * The colour underneath, so a partial weight has something to fade to.
445
+ *
446
+ * A colour tag paints; unlike a studio layer it has nothing to
447
+ * composite against, which is why `opacity` was never expressible
448
+ * natively. A mask makes the weight vary per character, so the question
449
+ * stops being avoidable: carrying the base colour is what lets a
450
+ * feathered edge and a partial opacity survive as one tag instead of
451
+ * expanding to one `[color]` per letter.
452
+ *
453
+ * Absent, a partial weight falls back to a hard cut at half strength.
454
+ */
455
+ baseColor?: string;
456
+ /**
457
+ * Position of this tag's text inside a longer effect, in visible
458
+ * characters. Set when one logical effect is split across several tags
459
+ * — a gradient down a multi-paragraph block — so each tag continues the
460
+ * ramp instead of restarting it.
461
+ */
462
+ globalOffset?: number;
463
+ /** Total visible characters of that longer effect. */
464
+ documentLength?: number;
465
+ }
466
+ export type EffectUnit = 'character' | 'word' | 'line';
467
+ /**
468
+ * The stepping units, as data.
469
+ *
470
+ * The type alone cannot be enumerated at runtime, so every UI that offered
471
+ * these had to retype them — and a tool that wants to *validate* `unit=`
472
+ * had nothing to validate against at all.
473
+ */
474
+ export declare const EFFECT_UNITS: readonly EffectUnit[];
475
+ /**
476
+ * The axis a layer actually reads, given its stepping unit.
477
+ *
478
+ * Stepping per word while measuring per character is almost never what
479
+ * someone means: a word-unit gradient over "one two three" would give
480
+ * every word the colour of its first letter, so the ramp reached 60% of
481
+ * the way to its end colour and stopped. `unit` therefore promotes the
482
+ * default `index` axis to the matching coordinate. An axis the user
483
+ * chose deliberately — radial, line, random — is left alone.
484
+ */
485
+ export declare function effectiveAxis(axis: Axis, unit: EffectUnit | undefined): Axis;
486
+ /** Short attribute keys, so a tag stays readable in a document. */
487
+ /**
488
+ * The attribute key each parameter is written as, and the only place that
489
+ * mapping exists.
490
+ *
491
+ * Exported because it is the answer to "what can be spelled inside
492
+ * `[gradient=…]`" — the same question `TagVocabulary` answers for the tags
493
+ * whose attribute is a plain enum. A consumer that retyped `pc`, `oct` or
494
+ * `mrat` would be a second transcription of a grammar that already has
495
+ * exactly one, which is the drift this module was written to end.
496
+ *
497
+ * Note this says how a parameter is SPELLED, not which effect kinds read
498
+ * it: `sat` is rainbow's and `min` is grow's, and a caller that offers
499
+ * every key on every tag would be promising things the evaluator ignores.
500
+ */
501
+ export declare const EFFECT_PARAM_KEYS: {
502
+ readonly axis: 'axis';
503
+ readonly wave: 'wave';
504
+ readonly cycles: 'cycles';
505
+ readonly phase: 'phase';
506
+ readonly easing: 'easing';
507
+ readonly bezier: 'bezier';
508
+ readonly parabolaCenter: 'pc';
509
+ readonly parabolaPower: 'pp';
510
+ readonly invert: 'invert';
511
+ readonly steps: 'steps';
512
+ readonly octaves: 'oct';
513
+ readonly expression: 'expr';
514
+ readonly seed: 'seed';
515
+ readonly unit: 'unit';
516
+ readonly opacity: 'opacity';
517
+ readonly perceptual: 'oklab';
518
+ readonly saturation: 'sat';
519
+ readonly lightness: 'light';
520
+ readonly spread: 'spread';
521
+ readonly offset: 'offset';
522
+ readonly preserveSL: 'keepsl';
523
+ readonly min: 'min';
524
+ readonly max: 'max';
525
+ readonly freq: 'freq';
526
+ readonly step: 'step';
527
+ readonly originX: 'ox';
528
+ readonly originY: 'oy';
529
+ readonly angle: 'ang';
530
+ readonly radius: 'rad';
531
+ readonly aspect: 'asp';
532
+ readonly maskShape: 'mask';
533
+ readonly maskX: 'mx';
534
+ readonly maskY: 'my';
535
+ readonly maskWidth: 'mw';
536
+ readonly maskHeight: 'mh';
537
+ readonly maskRotate: 'mrot';
538
+ readonly maskFeather: 'mfea';
539
+ readonly maskInvert: 'minv';
540
+ readonly maskPoints: 'mpts';
541
+ readonly maskInner: 'mrat';
542
+ readonly gridCols: 'cols';
543
+ readonly gridRows: 'rows';
544
+ readonly palette: 'pal';
545
+ readonly cells: 'map';
546
+ readonly smooth: 'smooth';
547
+ readonly baseColor: 'base';
548
+ readonly globalOffset: 'at';
549
+ readonly documentLength: 'of';
550
+ };
551
+ /**
552
+ * Parse a stop list, `"#hex 0%, #hex 50%, #hex"`.
553
+ *
554
+ * Unpositioned stops are spread evenly between their positioned
555
+ * neighbours, matching CSS gradient semantics.
556
+ *
557
+ * Cached because a gradient layer asks for the same string once per
558
+ * character; the result is treated as immutable by every caller.
559
+ */
560
+ export declare function parseColorStops(colorsStr: string): ColorStop[];
561
+ /** Serialise stops to the canonical `"#hex 0.0%, …"` form. */
562
+ export declare function stringifyColorStops(stops: readonly ColorStop[]): string;
563
+ /** Parse an effect tag's attribute value into parameters. */
564
+ export declare function parseEffectParams(value: string): EffectParams;
565
+ /**
566
+ * Serialise parameters back to an attribute value.
567
+ *
568
+ * Only what differs from `defaults` is written, so a plain gradient stays
569
+ * `[gradient=#a,#b]` and only a configured one grows an attribute tail.
570
+ */
571
+ export declare function stringifyEffectParams(params: EffectParams, defaults?: Partial<EffectParams>): string;
572
+ /** A run of text with the style its effect computed. */
573
+ export interface StyledSegment {
574
+ text: string;
575
+ color?: string;
576
+ size?: number;
577
+ }
578
+ /** Which effect a set of parameters describes. */
579
+ export type EffectKind = 'gradient' | 'rainbow' | 'grow' | 'sinewave' | 'paint';
580
+ /** The size a character has with no size effect on it, in percent. */
581
+ export declare const NEUTRAL_SIZE = 100;
582
+ /** Where a node sits in a larger logical effect that spans several nodes. */
583
+ export interface EffectSpan {
584
+ globalOffset?: number;
585
+ documentLength?: number;
586
+ }
587
+ export declare const GRADIENT_DEFAULTS: Partial<EffectParams>;
588
+ export declare const RAINBOW_DEFAULTS: Partial<EffectParams>;
589
+ export declare const GROW_DEFAULTS: Partial<EffectParams>;
590
+ export declare const PAINT_DEFAULTS: Partial<EffectParams>;
591
+ /**
592
+ * The placement and mask subset of the shared defaults.
593
+ *
594
+ * Every effect kind already carries these; this names them separately so
595
+ * a UI can reset just the placement without touching the modulation.
596
+ */
597
+ export declare const SPATIAL_DEFAULTS: Partial<EffectParams>;
598
+ /** Read a tag's placement parameters, filling in the defaults. */
599
+ export declare function spatialFromParams(p: EffectParams): SpatialOptions;
600
+ /** Read a tag's mask parameters, filling in the defaults. */
601
+ export declare function maskFromParams(p: EffectParams): MaskOptions;
602
+ /** Read a tag's paint grid, or `null` when it carries none. */
603
+ export declare function gridFromParams(p: EffectParams): PaintGrid | null;
604
+ /**
605
+ * Evaluate an effect over a plain string, one styled run per unit.
606
+ *
607
+ * This is the single implementation the tag registry's BBCode export, the
608
+ * HTML renderer's preview and the studio's own compiler all call, so a
609
+ * document cannot render one way and export another.
610
+ *
611
+ * `span` carries the document-wide position when one logical effect is
612
+ * split across several nodes — without it, a gradient interrupted by a
613
+ * `[b]` would restart at its first colour on the other side.
614
+ */
615
+ export declare function evaluateEffect(text: string, kind: EffectKind, params: EffectParams, span?: EffectSpan): StyledSegment[];
616
+ /**
617
+ * Collapse neighbouring runs that resolved to the same style.
618
+ *
619
+ * Every consumer wins: the export writes `[color=#f00]ab[/color]` instead
620
+ * of two tags, and the preview builds one span instead of two. It matters
621
+ * most exactly where the output is largest — a quantised gradient, a
622
+ * word- or line-stepped effect, a long flat tail — which is where the
623
+ * 60 000-character budget actually gets spent.
624
+ *
625
+ * A whitespace run between two identical styles is absorbed rather than
626
+ * splitting them; between different ones it stays unstyled, so a space
627
+ * never picks up a colour it would have to pay a tag for.
628
+ */
629
+ export declare function mergeStyledSegments(segments: StyledSegment[]): StyledSegment[];
630
+ /**
631
+ * Upper-case an emitted hex colour.
632
+ *
633
+ * @remarks Exported so the studio's own compiler can apply the same rule;
634
+ * the two must agree byte for byte or the same document exports
635
+ * differently depending on which path produced it.
636
+ *
637
+ * Interpolated colours come back lower-case while a stop copied straight
638
+ * from the attribute keeps whatever the author typed, so a single
639
+ * gradient used to export `#FF0000` next to `#bf4000`. Normalising here
640
+ * — the one place every effect colour passes through — keeps the output
641
+ * uniform without touching the colour maths.
642
+ */
643
+ export declare function normalizeHex(hex: string): string;