rapier-markdown-kit 1.2.45 → 1.2.48

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 (52) hide show
  1. package/LICENSE +12 -5
  2. package/README.md +134 -11
  3. package/dist/agent/vendor/BROWSER-ENTITIES.json +36 -0
  4. package/dist/agent/vendor/MARKDOWN-RUNTIME.json +136 -0
  5. package/dist/agent/vendor/MARKDOWNIT.json +582 -0
  6. package/dist/agent/vendor/NOTICE.txt +60 -0
  7. package/dist/agent/vendor/markdown-licenses/entities-LICENSE.txt +11 -0
  8. package/dist/agent/vendor/markdown-licenses/linkify-it-LICENSE.txt +22 -0
  9. package/dist/agent/vendor/markdown-licenses/markdown-it-LICENSE.txt +22 -0
  10. package/dist/agent/vendor/markdown-licenses/mdurl-LICENSE.txt +45 -0
  11. package/dist/agent/vendor/markdown-licenses/punycode.js-LICENSE-MIT.txt +20 -0
  12. package/dist/agent/vendor/markdown-licenses/uc.micro-LICENSE.txt +20 -0
  13. package/dist/agent/vendor/markdown-plugins.json +46 -0
  14. package/dist/agent/vendor/markdown-plugins.mjs +27 -0
  15. package/dist/agent/vendor/markdown-runtime.mjs +13 -0
  16. package/dist/kit/artifact-modules.mjs +19 -0
  17. package/dist/kit/assets.d.mts +106 -0
  18. package/dist/kit/export-fonts.mjs +28 -19
  19. package/dist/kit/index.d.mts +151 -0
  20. package/dist/kit/layout.d.mts +61 -0
  21. package/dist/kit/ledger/carried.d.mts +12 -6
  22. package/dist/kit/ledger/carried.mjs +17 -8
  23. package/dist/kit/ledger/format.mjs +5 -3
  24. package/dist/kit/ledger/source.mjs +31 -2
  25. package/dist/kit/ledger/text-merge.mjs +33 -0
  26. package/dist/kit/ledger/transport.mjs +61 -2
  27. package/dist/kit/ledger.d.mts +137 -31
  28. package/dist/kit/markdown-it.d.mts +2 -2
  29. package/dist/kit/marks.d.mts +241 -0
  30. package/dist/kit/marks.mjs +39 -1
  31. package/dist/kit/model.d.mts +191 -0
  32. package/dist/kit/pdf-source-digest.mjs +10 -0
  33. package/dist/kit/pdf-source.mjs +4 -1
  34. package/dist/kit/pdf-vectors.mjs +3 -2
  35. package/dist/kit/render-entry.d.mts +654 -0
  36. package/dist/kit/render-markdown.mjs +14 -8
  37. package/dist/kit/render-print.mjs +36 -7
  38. package/dist/kit/render.mjs +16 -14
  39. package/dist/kit/typography.d.mts +42 -0
  40. package/dist/kit/will.d.mts +26 -3
  41. package/dist/layout/initial-range.mjs +18 -0
  42. package/dist/layout/typography.mjs +2 -18
  43. package/dist/math/delimiters.mjs +38 -0
  44. package/dist/math/markdown-rules.mjs +103 -0
  45. package/dist/packages/rapier-diff/concerns.mjs +2 -2
  46. package/dist/spec/document-fonts.mjs +62 -16
  47. package/dist/spec/md-assets.mjs +1 -0
  48. package/dist/spec/md-comments.mjs +384 -0
  49. package/dist/spec/md-marks.mjs +9 -0
  50. package/dist/spec/md-parser-config.mjs +463 -0
  51. package/dist/spec/md-parser-runtime.mjs +23 -0
  52. package/package.json +30 -8
@@ -0,0 +1,191 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import type {Layout} from './layout.mjs';
3
+ export {};
4
+
5
+ export interface RichTextItem {
6
+ text: string;
7
+ font: string;
8
+ letterSpacing?: number;
9
+ extraWidth?: number;
10
+ break?: 'normal' | 'never';
11
+ hyphenate?: boolean;
12
+ width?: never;
13
+ }
14
+ export interface RichBoxItem {width: number; text?: never}
15
+ export type RichItem = RichTextItem | RichBoxItem;
16
+ export interface PreparationOptions {
17
+ whiteSpace?: 'normal' | 'pre-wrap';
18
+ wordBreak?: 'normal' | 'keep-all';
19
+ language?: string;
20
+ policy?: 'wrap' | 'paragraph';
21
+ hanging?: boolean;
22
+ paragraphBreaks?: readonly number[] | null;
23
+ }
24
+ declare const preparedInline: unique symbol;
25
+ declare const preparedParagraph: unique symbol;
26
+ /** Opaque measured source. Retain the handle rather than cloning or serializing it. */
27
+ export interface PreparedRichParagraph {readonly [preparedInline]: true}
28
+ /** Paragraph-fit geometry is distinct from the inline engine's handle. */
29
+ export interface ParagraphGeometry {readonly [preparedParagraph]: true}
30
+ export type PreparedHandle = PreparedRichParagraph | ParagraphGeometry;
31
+ type WrapPreparation = PreparationOptions & {policy?: 'wrap'};
32
+ type ParagraphPreparation = PreparationOptions & {policy: 'paragraph'};
33
+ /** Cancellation with return() publishes no handle or plan. */
34
+ export interface PreparationWork<T> extends IterableIterator<void, T | null | undefined, void> {
35
+ return(value?: T | null): IteratorReturnResult<T | null | undefined>;
36
+ }
37
+ export type PreparationSteps = PreparationWork<PreparedHandle>;
38
+ export interface FitWidthRequest {segment: number; word: number; from: number; to: number}
39
+ export type ReadKnownWidth = (request: FitWidthRequest) => number | undefined;
40
+ export type FitWork<P> = Generator<FitWidthRequest | null, P | null, number | undefined>;
41
+ export type FrozenFitPlan<P extends {lines: object[]}> = Readonly<Omit<P, 'lines'>> & {
42
+ readonly lines: readonly Readonly<P['lines'][number]>[];
43
+ };
44
+ export interface PreparationScope {
45
+ prepare(owner: object, items: readonly RichItem[], options: ParagraphPreparation): ParagraphGeometry | null;
46
+ prepare(owner: object, items: readonly RichItem[], options?: WrapPreparation): PreparedRichParagraph | null;
47
+ prepare(owner: object, items: readonly RichItem[], options: PreparationOptions): PreparedHandle | null;
48
+ prepareSteps(owner: object, items: readonly RichItem[], options: ParagraphPreparation): PreparationWork<ParagraphGeometry>;
49
+ prepareSteps(owner: object, items: readonly RichItem[], options?: WrapPreparation): PreparationWork<PreparedRichParagraph>;
50
+ prepareSteps(owner: object, items: readonly RichItem[], options: PreparationOptions): PreparationSteps;
51
+ fit<P extends {lines: object[]}>(owner: object, handle: ParagraphGeometry,
52
+ createWork: (readKnown: ReadKnownWidth) => FitWork<P>): FrozenFitPlan<P> | null;
53
+ fitSteps<P extends {lines: object[]}>(owner: object, handle: ParagraphGeometry,
54
+ createWork: (readKnown: ReadKnownWidth) => FitWork<P>): PreparationWork<FrozenFitPlan<P>>;
55
+ current(handle: PreparedHandle | null | undefined): boolean;
56
+ invalidateFonts(): number;
57
+ forget(owner: object): void;
58
+ retire(options?: {documentChanged?: boolean}): void;
59
+ }
60
+ export function createPreparationScope(document?: Document | null): PreparationScope;
61
+ export function prepareRichParagraph(items: readonly RichItem[], options: ParagraphPreparation): ParagraphGeometry | null;
62
+ export function prepareRichParagraph(items: readonly RichItem[], options?: WrapPreparation): PreparedRichParagraph | null;
63
+ export function prepareRichParagraph(items: readonly RichItem[], options: PreparationOptions): PreparedHandle | null;
64
+ export function captureFontAuthority(document?: Document | null): number;
65
+ export function invalidateRichMetrics(document?: Document | null): number;
66
+ /** Unsupported properties are accepted as input and return false, without changing the source. */
67
+ export interface RichStyle {
68
+ writingMode?: string; direction?: string; unicodeBidi?: string; textTransform?: string;
69
+ fontKerning?: string; fontOpticalSizing?: string; fontStretch?: string; fontSizeAdjust?: string;
70
+ textRendering?: string; verticalAlign?: string; whiteSpace?: string; wordBreak?: string;
71
+ hyphens?: string; lineBreak?: string; hangingPunctuation?: string; tabSize?: string;
72
+ textWrapStyle?: string; fontFeatureSettings?: string; fontVariationSettings?: string;
73
+ fontVariant?: string; fontVariantLigatures?: string; fontVariantCaps?: string;
74
+ fontVariantNumeric?: string; fontVariantEastAsian?: string; fontVariantPosition?: string;
75
+ fontVariantAlternates?: string; fontSynthesis?: string; fontSynthesisWeight?: string;
76
+ fontSynthesisStyle?: string; fontSynthesisSmallCaps?: string; letterSpacing?: string; wordSpacing?: string;
77
+ }
78
+ export function supportsRichStyle(style: RichStyle | null | undefined, contentLanguage?: string): boolean;
79
+
80
+ declare const richCursor: unique symbol;
81
+ declare const fragmentCursor: unique symbol;
82
+ export interface RichInlineCursor {readonly [richCursor]: true}
83
+ export interface RichFragmentCursor {readonly [fragmentCursor]: true}
84
+ export interface RichInlineFragmentRange {
85
+ itemIndex: number;
86
+ gapBefore: number;
87
+ gapItemIndex: number;
88
+ occupiedWidth: number;
89
+ start: RichFragmentCursor;
90
+ end: RichFragmentCursor;
91
+ }
92
+ export interface RichInlineLineRange {
93
+ fragments: RichInlineFragmentRange[];
94
+ width: number;
95
+ end: RichInlineCursor;
96
+ }
97
+ export interface FlowFragment {
98
+ itemIndex: number;
99
+ sourceStart: number;
100
+ sourceEnd: number;
101
+ gapBefore: number;
102
+ gapItemIndex: number;
103
+ occupiedWidth: number;
104
+ }
105
+ export interface MaterializedFragment extends FlowFragment {
106
+ text: string;
107
+ }
108
+ export interface MaterializedLine {
109
+ fragments: MaterializedFragment[];
110
+ width: number;
111
+ end: RichInlineCursor;
112
+ }
113
+ export function layoutNextRichInlineLineRange(prepared: PreparedRichParagraph, maxWidth: number,
114
+ start?: RichInlineCursor): RichInlineLineRange | null;
115
+ export function materializeRichInlineLineRange(prepared: PreparedRichParagraph, line: RichInlineLineRange): MaterializedLine;
116
+ export interface MappedFragment {text: string; offsets: number[]; start: number; end: number}
117
+ export type MappableFragment = {sourceStart: number; sourceEnd: number} & (
118
+ {text: string; derive?: false} | {derive: true; glyph?: string}
119
+ );
120
+ export function mapFragment(run: string | {raw: string; break?: 'normal' | 'never'}, fragment: MappableFragment,
121
+ options?: {whiteSpace?: 'normal' | 'pre-wrap'}): MappedFragment | null;
122
+
123
+ export interface LineMetrics {line: number; cap: number; capTop: number}
124
+ export interface FontMeasurementAuthority {
125
+ captureFontAuthority(document: Document): number;
126
+ fontReady(document: Document, font: string, text: string): boolean;
127
+ }
128
+ export function createLineMeasurer(authority?: FontMeasurementAuthority | null): (element: Element | null | undefined) => LineMetrics | null;
129
+ export function lineMetrics(element: Element | null | undefined): LineMetrics | null;
130
+ export function linesHeight(lines: number, metrics: Pick<LineMetrics, 'line' | 'cap'> | null | undefined): number | null;
131
+ export interface PictureBox {x: number; width: number; height: number}
132
+ export interface Rect extends PictureBox {y: number}
133
+ export function linesSlices<T extends Rect>(slices: readonly T[], layout: Layout | null | undefined,
134
+ metrics: LineMetrics | null | undefined, y: number, height: number): T[] | readonly T[];
135
+ export function linesTop(layout: Layout | null | undefined, metrics: LineMetrics | null | undefined): number;
136
+ export function imageBox(columnWidth: number, naturalWidth: number, naturalHeight: number, layout?: Layout,
137
+ defaultWidth?: number, metrics?: LineMetrics | null): PictureBox | null;
138
+ export interface ReservedRaster {
139
+ fit: PictureBox;
140
+ reserved: PictureBox;
141
+ visualDeltaX: number;
142
+ visualDeltaY: number;
143
+ }
144
+ export function rasterReserved(columnWidth: number, unrotated: PictureBox | null, rad: number): ReservedRaster | null;
145
+ export type ProfileSpan = readonly [number, number];
146
+ export interface SpanProfile {
147
+ spanAt(t: number): ProfileSpan | null;
148
+ runsAt?(t: number): readonly ProfileSpan[] | null;
149
+ }
150
+ export type ShapeProfile = SpanProfile | {runsAt(t: number): readonly ProfileSpan[] | null; spanAt?(t: number): ProfileSpan | null};
151
+ export interface RunProfile extends SpanProfile {runsAt(t: number): readonly ProfileSpan[]}
152
+ export function alphaProfile(image: HTMLImageElement): RunProfile | null;
153
+ export function polygonProfile(corners: readonly ProfileSpan[]): SpanProfile;
154
+ export function rotatedBoundsRad(width: number, height: number, rad: number): {width: number; height: number};
155
+ export function rasterTiltProfile(width: number, height: number, rad: number): SpanProfile;
156
+ export function rotatedRasterAlpha(baseAlpha: RunProfile | null, width: number, height: number, rad: number): RunProfile | null;
157
+ export function bandsProfile(bands: readonly (readonly ProfileSpan[])[]): RunProfile | null;
158
+ export function serializeProfile(profile: ShapeProfile | null | undefined, count?: number): string;
159
+ export function parseProfile(text: string): RunProfile | null;
160
+ export function frameScale(element: Element | null | undefined): number;
161
+ export function pictureSlices(profile: ShapeProfile | null, x: number, y: number, width: number, height: number, scale?: number): Rect[];
162
+ export function besideSlices<T extends Rect>(slices: readonly T[], columnLeft: number, columnRight: number,
163
+ pictureLeft: number, pictureWidth: number): readonly T[];
164
+ export interface BandSlot {x: number; width: number}
165
+ export interface FlowSlot extends BandSlot {y: number; block?: number; channel?: number}
166
+ export type SlotsForBand = (width: number, obstacles: readonly Rect[], top: number, height: number, minWidth?: number) => BandSlot[] | null;
167
+ export const slotsForBand: SlotsForBand;
168
+ export interface SlotSequenceResult {slots: FlowSlot[]; end: number; multiple: boolean}
169
+ export type SlotSequence = (width: number, top: number, obstacles: readonly Rect[], lineHeight: number,
170
+ minWidth: number, slotsForBand: SlotsForBand, direction?: 'ltr' | 'rtl', order?: 'columns' | 'rows') => SlotSequenceResult | null;
171
+ export const slotSequence: SlotSequence;
172
+ export function columnsFilled(slots: readonly FlowSlot[], placed: readonly FlowSlot[]): boolean;
173
+ export type FlowLine<F extends FlowFragment = MaterializedFragment> = FlowSlot & {fragments: F[]} &
174
+ (F extends MaterializedFragment ? {end: RichInlineCursor} : {wordSpacing: number});
175
+ export interface FlowPlan<F extends FlowFragment = MaterializedFragment> {lines: FlowLine<F>[]; height: number}
176
+ export function flowLines(flow: PreparedRichParagraph, width: number, top: number, obstacles: readonly Rect[],
177
+ lineHeight: number, minWidth: number, direction?: 'ltr' | 'rtl', balance?: number,
178
+ align?: 'start' | 'end' | 'left' | 'right' | 'center' | 'justify'): FlowPlan | null;
179
+ export interface WrapShape {boxWidth: number; boxHeight: number; startY: number; points: [number, number][]}
180
+ export function wrapShape(side: 'left' | 'right', obstacles: readonly Rect[], width: number, top: number): WrapShape | null;
181
+ export function boxClearance(obstacles: readonly Rect[], width: number, top: number, height: number,
182
+ floor: number): {left: number; right: number; fits: boolean} | null;
183
+ export interface EdgeLine {block: Element; top: number; bottom: number; start: number; content: number}
184
+ export function edgeLines(root: Element, skip?: (text: Text) => boolean): EdgeLine[];
185
+ export interface EdgeMarks {
186
+ markers: {item: Element; shift: number}[];
187
+ bars: {quote: Element; runs: {shift: number; top: number; bottom: number}[]}[];
188
+ steps: Element[];
189
+ }
190
+ export function edgeMarks(root: Element, before: readonly EdgeLine[], skip?: (text: Text) => boolean): EdgeMarks;
191
+ export function imageOnly(paragraph: Node, image: Node): boolean;
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: MIT
2
+ export const PDF_SOURCE_DIGEST = '/RapierSourceDigest <' + '0'.repeat(64) + '>';
3
+
4
+ export async function pdfSourceDigest(bytes, start, end) {
5
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || start + 64 > end || end > bytes.length)
6
+ throw new Error('Invalid PDF source digest range.');
7
+ const bound = bytes.slice(0, end);
8
+ bound.fill(48, start, start + 64);
9
+ return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', bound)), byte => byte.toString(16).padStart(2, '0')).join('');
10
+ }
@@ -1,4 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
+ import {PDF_SOURCE_DIGEST, pdfSourceDigest} from './pdf-source-digest.mjs';
2
3
  function pdfStructure(input) {
3
4
  const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);
4
5
  const fail = () => { throw Object.assign(new Error('The PDF source could not be attached.'), {code: 'pdf_source_invalid'}); };
@@ -116,10 +117,12 @@ export async function attachPdfSource(input, {source, filename, maxBytes = Infin
116
117
  table += place ? String(place.at).padStart(10, '0') + ' ' + String(place.generation).padStart(5, '0') + ' n \n' : '0000000000 00000 f \n';
117
118
  }
118
119
  const identity = trailer.fields.get('ID');
119
- table += 'trailer\n<< /Size ' + totalSize + ' /Root ' + rootId + ' ' + generation + ' R /Info ' + infoId + ' 0 R' + (identity ? ' /ID ' + identity.value : '') + ' >>\nstartxref\n' + length + '\n%%EOF\n';
120
+ table += 'trailer\n<< /Size ' + totalSize + ' /Root ' + rootId + ' ' + generation + ' R /Info ' + infoId + ' 0 R' + (identity ? ' /ID ' + identity.value : '') + ' ' + PDF_SOURCE_DIGEST + ' >>\nstartxref\n' + length + '\n%%EOF\n';
121
+ const digestAt = length + table.indexOf(PDF_SOURCE_DIGEST) + PDF_SOURCE_DIGEST.indexOf('<') + 1;
120
122
  parts.push(ascii(table)); length += table.length;
121
123
  if (length > maxBytes) throw Object.assign(new Error('The exported file exceeds the file limit.'), {code: 'export_too_large'});
122
124
  const result = new Uint8Array(length); let at = 0;
123
125
  for (const chunk of parts) { result.set(chunk, at); at += chunk.length; }
126
+ result.set(encode.encode(await pdfSourceDigest(result, digestAt, result.length - 1)), digestAt);
124
127
  check(); return result;
125
128
  }
@@ -157,14 +157,15 @@ export async function collectPdfVectors(main, {width, height, count, capture, si
157
157
  const wrap = document.createElement('div');
158
158
  wrap.style.cssText = `position:fixed;left:0;top:0;width:${box.width}px;height:${box.height}px;pointer-events:none;background:transparent`;
159
159
  clone.style.setProperty('width', box.width + 'px', 'important'); clone.style.setProperty('height', box.height + 'px', 'important');
160
- wrap.append(clone); document.body.append(wrap);
160
+ const surface = document.createElement('div'); surface.style.cssText = 'width:100%;height:100%';
161
+ surface.append(clone); wrap.attachShadow({mode: 'open'}).append(surface); document.body.append(wrap);
161
162
  try {
162
163
  const plainText = node.localName === 'text' && window.getComputedStyle(node).filter === 'none' && window.getComputedStyle(node).textShadow === 'none';
163
164
  const bounds = plainText ? node.getBoundingClientRect() : box;
164
165
  const left = Math.max(0, bounds.left - box.left - 2), top = Math.max(0, bounds.top - box.top - 2);
165
166
  const right = Math.min(box.width, bounds.right - box.left + 2), bottom = Math.min(box.height, bounds.bottom - box.top + 2);
166
167
  if (!(right > left && bottom > top)) return;
167
- const result = await capture({root: wrap, clip: {x: left, y: top, width: right - left, height: bottom - top}, transparent: true, scale: 2, signal, current, pixels: true}); check();
168
+ const result = await capture({root: surface, clip: {x: left, y: top, width: right - left, height: bottom - top}, transparent: true, scale: 2, signal, current, pixels: true}); check();
168
169
  if (result?.rgb instanceof Uint8Array && result?.alpha instanceof Uint8Array) {
169
170
  return {image: {rgb: await compress(result.rgb), alpha: await compress(result.alpha), width: result.width, height: result.height}, x: box.left - origin.left + left, y: box.top - origin.top + top, width: right - left, height: bottom - top};
170
171
  }