svelte-streamdown 2.4.5 → 2.5.1

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 (46) hide show
  1. package/README.md +98 -4
  2. package/dist/Block.svelte +4 -4
  3. package/dist/Block.svelte.d.ts +0 -1
  4. package/dist/Elements/Alert.svelte +4 -1
  5. package/dist/Elements/Alert.svelte.d.ts +1 -0
  6. package/dist/Elements/Citation.svelte +260 -0
  7. package/dist/Elements/Citation.svelte.d.ts +7 -0
  8. package/dist/Elements/Code.svelte +13 -41
  9. package/dist/Elements/Code.svelte.d.ts +1 -0
  10. package/dist/Elements/Element.svelte +65 -33
  11. package/dist/Elements/FootnoteRef.svelte +41 -89
  12. package/dist/Elements/Image.svelte +5 -1
  13. package/dist/Elements/Image.svelte.d.ts +1 -0
  14. package/dist/Elements/Link.svelte +5 -1
  15. package/dist/Elements/Link.svelte.d.ts +1 -0
  16. package/dist/Elements/Math.svelte +10 -2
  17. package/dist/Elements/Math.svelte.d.ts +1 -0
  18. package/dist/Elements/Mermaid.svelte +87 -175
  19. package/dist/Elements/Mermaid.svelte.d.ts +1 -0
  20. package/dist/Elements/TableDownload.svelte +216 -0
  21. package/dist/Elements/TableDownload.svelte.d.ts +8 -0
  22. package/dist/Elements/icons.d.ts +9 -0
  23. package/dist/Elements/icons.js +175 -0
  24. package/dist/Elements/popover.svelte.d.ts +8 -0
  25. package/dist/Elements/popover.svelte.js +40 -0
  26. package/dist/Elements/stepperState.svelte.d.ts +35 -0
  27. package/dist/Elements/stepperState.svelte.js +98 -0
  28. package/dist/Streamdown.svelte +13 -4
  29. package/dist/Streamdown.svelte.d.ts +23 -2
  30. package/dist/context.svelte.d.ts +28 -11
  31. package/dist/context.svelte.js +14 -6
  32. package/dist/marked/index.d.ts +4 -2
  33. package/dist/marked/index.js +4 -2
  34. package/dist/marked/marked-align.d.ts +10 -0
  35. package/dist/marked/marked-align.js +36 -0
  36. package/dist/marked/marked-citations.d.ts +8 -0
  37. package/dist/marked/marked-citations.js +49 -0
  38. package/dist/marked/marked-table.js +36 -13
  39. package/dist/theme.d.ts +66 -21
  40. package/dist/theme.js +47 -17
  41. package/dist/utils/get.d.ts +1 -0
  42. package/dist/utils/get.js +25 -0
  43. package/dist/utils/panzoom.svelte.d.ts +1 -2
  44. package/dist/utils/panzoom.svelte.js +87 -43
  45. package/dist/utils/parse-incomplete-markdown.js +70 -1
  46. package/package.json +1 -1
@@ -0,0 +1,175 @@
1
+ import { createRawSnippet } from 'svelte';
2
+ export const copyIcon = createRawSnippet(() => {
3
+ return {
4
+ render: () => {
5
+ return `
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="100%"
9
+ height="100%"
10
+ viewBox="0 0 24 24"
11
+ fill="none"
12
+ stroke="currentColor"
13
+ stroke-width="2"
14
+ stroke-linecap="round"
15
+ stroke-linejoin="round"
16
+ ><rect width="8" height="4" x="8" y="2" rx="1" ry="1" /><path
17
+ d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"
18
+ /></svg>
19
+ `;
20
+ }
21
+ };
22
+ });
23
+ export const downloadIcon = createRawSnippet(() => {
24
+ return {
25
+ render: () => {
26
+ return `<svg
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ width="100%"
29
+ height="100%"
30
+ viewBox="0 0 24 24"
31
+ fill="none"
32
+ stroke="currentColor"
33
+ stroke-width="2"
34
+ stroke-linecap="round"
35
+ stroke-linejoin="round"
36
+ ><path d="M12 15V3" /><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><path
37
+ d="m7 10 5 5 5-5"
38
+ /></svg
39
+ >`;
40
+ }
41
+ };
42
+ });
43
+ export const checkIcon = createRawSnippet(() => {
44
+ return {
45
+ render: () => {
46
+ return `
47
+ <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
48
+ `;
49
+ }
50
+ };
51
+ });
52
+ export const zoomInIcon = createRawSnippet(() => {
53
+ return {
54
+ render: () => `
55
+ <svg
56
+ width="100%"
57
+ height="100%"
58
+ viewBox="0 0 24 24"
59
+ fill="none"
60
+ stroke="currentColor"
61
+ stroke-width="2"
62
+ stroke-linecap="round"
63
+ stroke-linejoin="round"
64
+ xmlns="http://www.w3.org/2000/svg"
65
+ >
66
+ <circle cx="11" cy="11" r="8" />
67
+ <line x1="21" x2="16.65" y1="21" y2="16.65" />
68
+ <line x1="11" x2="11" y1="8" y2="14" />
69
+ <line x1="8" x2="14" y1="11" y2="11" />
70
+ </svg>
71
+ `
72
+ };
73
+ });
74
+ export const zoomOutIcon = createRawSnippet(() => {
75
+ return {
76
+ render: () => `
77
+ <svg
78
+ width="100%"
79
+ height="100%"
80
+ viewBox="0 0 24 24"
81
+ fill="none"
82
+ stroke="currentColor"
83
+ stroke-width="2"
84
+ stroke-linecap="round"
85
+ stroke-linejoin="round"
86
+ xmlns="http://www.w3.org/2000/svg"
87
+ >
88
+ <circle cx="11" cy="11" r="8" />
89
+ <line x1="21" x2="16.65" y1="21" y2="16.65" />
90
+ <line x1="8" x2="14" y1="11" y2="11" />
91
+ </svg>
92
+ `
93
+ };
94
+ });
95
+ export const fitViewIcon = createRawSnippet(() => {
96
+ return {
97
+ render: () => `
98
+ <svg
99
+ width="100%"
100
+ height="100%"
101
+ viewBox="0 0 24 24"
102
+ fill="none"
103
+ stroke="currentColor"
104
+ stroke-width="2"
105
+ stroke-linecap="round"
106
+ stroke-linejoin="round"
107
+ xmlns="http://www.w3.org/2000/svg"
108
+ >
109
+ <path d="M3 7V5a2 2 0 0 1 2-2h2" />
110
+ <path d="M17 3h2a2 2 0 0 1 2 2v2" />
111
+ <path d="M21 17v2a2 2 0 0 1-2 2h-2" />
112
+ <path d="M7 21H5a2 2 0 0 1-2-2v-2" />
113
+ <rect width="10" height="8" x="7" y="8" rx="1" />
114
+ </svg>
115
+ `
116
+ };
117
+ });
118
+ export const fullscreenIcon = createRawSnippet(() => {
119
+ return {
120
+ render: () => `
121
+ <svg
122
+ width="100%"
123
+ height="100%"
124
+ viewBox="0 0 24 24"
125
+ fill="none"
126
+ stroke="currentColor"
127
+ stroke-width="2"
128
+ stroke-linecap="round"
129
+ stroke-linejoin="round"
130
+ xmlns="http://www.w3.org/2000/svg"
131
+ >
132
+ <path d="m15 15 6 6" /><path d="m15 9 6-6" /><path d="M21 16v5h-5" /><path d="M21 8V3h-5" />
133
+ <path d="M3 16v5h5" /><path d="m3 21 6-6" /><path d="M3 8V3h5" /><path d="M9 9 3 3" />
134
+ </svg>
135
+ `
136
+ };
137
+ });
138
+ export const chevronRight = createRawSnippet(() => {
139
+ return {
140
+ render: () => `
141
+ <svg
142
+ xmlns="http://www.w3.org/2000/svg"
143
+ width="100%"
144
+ height="100%"
145
+ viewBox="0 0 24 24"
146
+ fill="none"
147
+ stroke="currentColor"
148
+ stroke-width="2"
149
+ stroke-linecap="round"
150
+ stroke-linejoin="round"
151
+ >
152
+ <path d="m9 18 6-6-6-6" />
153
+ </svg>
154
+ `
155
+ };
156
+ });
157
+ export const chevronLeft = createRawSnippet(() => {
158
+ return {
159
+ render: () => `
160
+ <svg
161
+ xmlns="http://www.w3.org/2000/svg"
162
+ width="100%"
163
+ height="100%"
164
+ viewBox="0 0 24 24"
165
+ fill="none"
166
+ stroke="currentColor"
167
+ stroke-width="2"
168
+ stroke-linecap="round"
169
+ stroke-linejoin="round"
170
+ >
171
+ <path d="m15 18-6-6 6-6" />
172
+ </svg>
173
+ `
174
+ };
175
+ });
@@ -0,0 +1,8 @@
1
+ export declare class Popover {
2
+ isOpen: boolean;
3
+ content: HTMLDialogElement | undefined;
4
+ reference: HTMLButtonElement | undefined;
5
+ constructor();
6
+ place: (node: HTMLElement) => Promise<void>;
7
+ popoverAttachment: (node: HTMLDialogElement) => () => void;
8
+ }
@@ -0,0 +1,40 @@
1
+ import { useClickOutside } from '../utils/useClickOutside.svelte.js';
2
+ import { autoPlacement, computePosition, autoUpdate, hide, offset, shift } from '@floating-ui/dom';
3
+ import { setContext } from 'svelte';
4
+ export class Popover {
5
+ isOpen = $state(false);
6
+ content = $state();
7
+ reference = $state();
8
+ constructor() {
9
+ setContext('POPOVER', true);
10
+ }
11
+ place = async (node) => {
12
+ const middleware = [
13
+ hide(),
14
+ offset(10),
15
+ shift({
16
+ mainAxis: true
17
+ }),
18
+ autoPlacement({
19
+ allowedPlacements: ['top', 'top-end', 'top-start', 'bottom', 'bottom-end', 'bottom-start']
20
+ })
21
+ ];
22
+ const { x, y, strategy, placement, middlewareData } = await computePosition(this.reference, node, {
23
+ strategy: 'fixed',
24
+ middleware
25
+ });
26
+ Object.assign(node.style, {
27
+ position: strategy,
28
+ left: `${x}px`,
29
+ top: `${y}px`
30
+ });
31
+ };
32
+ popoverAttachment = (node) => {
33
+ this.content = node;
34
+ void this.place(node);
35
+ const off = autoUpdate(this.reference, node, () => this.place(node));
36
+ return () => {
37
+ off();
38
+ };
39
+ };
40
+ }
@@ -0,0 +1,35 @@
1
+ type KeyFramesOptions = {
2
+ duration: number;
3
+ easing: string;
4
+ fill: 'auto' | 'backwards' | 'both' | 'forwards' | 'none';
5
+ };
6
+ export declare const bind: (ref: Record<string, any>, props: Record<string, any>) => void;
7
+ export interface StepperState<Item> {
8
+ items: Item[];
9
+ keyFramesOptions: KeyFramesOptions;
10
+ }
11
+ export declare class StepperState<Item> {
12
+ activeStep: number;
13
+ destinationOffset: number;
14
+ stepAnimation: Animation | undefined;
15
+ offsets: number[];
16
+ stepHeights: number[];
17
+ stepContainer: HTMLElement | null;
18
+ isAnimating: boolean;
19
+ constructor(props: {
20
+ items: Item[];
21
+ keyFramesOptions: KeyFramesOptions;
22
+ });
23
+ translate: () => void;
24
+ setActiveStep: (i: number) => () => void;
25
+ scroller: (node: HTMLElement) => {
26
+ destroy: () => void;
27
+ };
28
+ next: () => void;
29
+ previous: () => void;
30
+ goTo: (i: number) => void;
31
+ get canGoNext(): boolean;
32
+ get canGoPrevious(): boolean;
33
+ canGoToStep: (targetStep: number) => boolean;
34
+ }
35
+ export {};
@@ -0,0 +1,98 @@
1
+ import { tick } from 'svelte';
2
+ export const bind = (ref, props) => {
3
+ const descriptors = Object.getOwnPropertyDescriptors(props);
4
+ for (const key in descriptors) {
5
+ Object.defineProperty(ref, key, descriptors[key]);
6
+ }
7
+ };
8
+ export class StepperState {
9
+ activeStep = $state(0);
10
+ destinationOffset = $state(0);
11
+ stepAnimation = $state();
12
+ offsets = $state([]);
13
+ stepHeights = $state([]);
14
+ stepContainer = null;
15
+ isAnimating = $state(false);
16
+ constructor(props) {
17
+ bind(this, props);
18
+ }
19
+ translate = () => {
20
+ if (this.destinationOffset !== this.offsets[this.activeStep] && this.stepContainer) {
21
+ this.destinationOffset = this.offsets[this.activeStep];
22
+ this.stepAnimation?.cancel();
23
+ this.stepAnimation = this.stepContainer.animate({
24
+ transform: `translateX(-${this.offsets[this.activeStep]}px)`
25
+ }, this.keyFramesOptions);
26
+ this.stepAnimation.onfinish = () => {
27
+ this.stepAnimation = undefined;
28
+ };
29
+ }
30
+ };
31
+ setActiveStep = (i) => () => {
32
+ if (!this.canGoToStep(i) || !this.stepContainer)
33
+ return;
34
+ const previousStep = this.stepContainer.children[this.activeStep];
35
+ const nextStep = this.stepContainer.children[i];
36
+ if (!previousStep || !nextStep)
37
+ return;
38
+ this.activeStep = i;
39
+ this.translate();
40
+ previousStep.animate({
41
+ opacity: `0`
42
+ }, this.keyFramesOptions);
43
+ nextStep.animate({
44
+ opacity: `1`
45
+ }, this.keyFramesOptions);
46
+ };
47
+ scroller = (node) => {
48
+ const onScroll = (e) => {
49
+ e.preventDefault();
50
+ node.scrollTo(0, 0);
51
+ };
52
+ node.addEventListener('scroll', onScroll);
53
+ node.scrollTo(0, 0);
54
+ const steps = node.querySelectorAll('[data-step]');
55
+ const setOffsets = () => {
56
+ steps.forEach((step, i) => {
57
+ this.offsets[i] = step.offsetLeft;
58
+ this.translate();
59
+ });
60
+ };
61
+ const resizeObserver = new ResizeObserver(setOffsets);
62
+ resizeObserver.observe(node);
63
+ setOffsets();
64
+ return {
65
+ destroy: () => {
66
+ resizeObserver.unobserve(node);
67
+ node.removeEventListener('scroll', onScroll);
68
+ this.activeStep = 0;
69
+ this.offsets = [];
70
+ this.destinationOffset = 0;
71
+ }
72
+ };
73
+ };
74
+ next = () => {
75
+ if (this.activeStep < this.items.length - 1) {
76
+ this.setActiveStep(this.activeStep + 1)();
77
+ }
78
+ };
79
+ previous = () => {
80
+ if (this.activeStep > 0) {
81
+ this.setActiveStep(this.activeStep - 1)();
82
+ }
83
+ };
84
+ goTo = (i) => {
85
+ if (this.canGoToStep(i)) {
86
+ this.setActiveStep(i)();
87
+ }
88
+ };
89
+ get canGoNext() {
90
+ return this.activeStep < this.items.length - 1;
91
+ }
92
+ get canGoPrevious() {
93
+ return this.activeStep > 0;
94
+ }
95
+ canGoToStep = (targetStep) => {
96
+ return targetStep >= 0 && targetStep < this.items.length;
97
+ };
98
+ }
@@ -1,4 +1,4 @@
1
- <script lang="ts">
1
+ <script lang="ts" generics="Source extends Record<string, any> = Record<string, any>">
2
2
  import Block from './Block.svelte';
3
3
  import { StreamdownContext, type StreamdownProps } from './context.svelte.js';
4
4
  import { mergeTheme, shadcnTheme } from './theme.js';
@@ -27,8 +27,10 @@
27
27
  icons,
28
28
  children,
29
29
  extensions,
30
+ sources,
31
+ inlineCitationsMode = 'carousel',
30
32
  ...snippets
31
- }: StreamdownProps = $props();
33
+ }: StreamdownProps<Source> = $props();
32
34
 
33
35
  streamdown = new StreamdownContext({
34
36
  get element() {
@@ -78,7 +80,12 @@
78
80
  get shikiPreloadThemes() {
79
81
  return shikiPreloadThemes;
80
82
  },
81
-
83
+ get sources() {
84
+ return sources;
85
+ },
86
+ get inlineCitationsMode() {
87
+ return inlineCitationsMode;
88
+ },
82
89
  get animation() {
83
90
  if (!animation?.enabled)
84
91
  return {
@@ -96,9 +103,11 @@
96
103
  get controls() {
97
104
  const codeControls = controls?.code ?? true;
98
105
  const mermaidControls = controls?.mermaid ?? true;
106
+ const tableControls = controls?.table ?? true;
99
107
  return {
100
108
  code: codeControls,
101
- mermaid: mermaidControls
109
+ mermaid: mermaidControls,
110
+ table: tableControls
102
111
  };
103
112
  },
104
113
  get children() {
@@ -1,4 +1,25 @@
1
1
  import { type StreamdownProps } from './context.svelte.js';
2
- declare const Streamdown: import("svelte").Component<StreamdownProps, {}, "streamdown" | "element">;
3
- type Streamdown = ReturnType<typeof Streamdown>;
2
+ declare function $$render<Source extends Record<string, any> = Record<string, any>>(): {
3
+ props: StreamdownProps<Source>;
4
+ exports: {};
5
+ bindings: "streamdown" | "element";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<Source extends Record<string, any> = Record<string, any>> {
10
+ props(): ReturnType<typeof $$render<Source>>['props'];
11
+ events(): ReturnType<typeof $$render<Source>>['events'];
12
+ slots(): ReturnType<typeof $$render<Source>>['slots'];
13
+ bindings(): "streamdown" | "element";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <Source extends Record<string, any> = Record<string, any>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Source>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Source>['props']>, ReturnType<__sveltets_Render<Source>['events']>, ReturnType<__sveltets_Render<Source>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<Source>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<Source>['exports']>;
20
+ <Source extends Record<string, any> = Record<string, any>>(internal: unknown, props: ReturnType<__sveltets_Render<Source>['props']> & {}): ReturnType<__sveltets_Render<Source>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ declare const Streamdown: $$IsomorphicComponent;
24
+ type Streamdown<Source extends Record<string, any> = Record<string, any>> = InstanceType<typeof Streamdown<Source>>;
4
25
  export default Streamdown;
@@ -3,32 +3,34 @@ import type { DeepPartialTheme, Theme } from './theme.js';
3
3
  import type { MermaidConfig } from 'mermaid';
4
4
  import type { KatexOptions } from 'katex';
5
5
  import type { BundledTheme } from 'shiki';
6
- export interface StreamdownContext extends Omit<StreamdownProps, keyof Snippets | 'class' | 'theme' | 'shikiTheme'> {
6
+ export interface StreamdownContext extends Omit<StreamdownProps, keyof Snippets | 'class' | 'theme' | 'shikiTheme' | 'inlineCitationsMode'> {
7
7
  snippets: Snippets;
8
8
  shikiTheme: BundledTheme;
9
9
  theme: Theme;
10
10
  controls: {
11
11
  code: boolean;
12
12
  mermaid: boolean;
13
+ table: boolean;
13
14
  };
15
+ inlineCitationsMode: 'list' | 'carousel';
14
16
  animation: {
15
17
  enabled: boolean;
16
18
  } & StreamdownProps['animation'];
17
19
  }
18
- export declare class StreamdownContext {
20
+ export declare class StreamdownContext<Source extends Record<string, any> = Record<string, any>> {
19
21
  footnotes: {
20
22
  refs: Map<string, FootnoteRef>;
21
23
  footnotes: Map<string, Footnote>;
22
24
  };
23
25
  isMounted: boolean;
24
- animationTextStyle: string | undefined;
25
- animationBlockStyle: string | undefined;
26
+ get animationTextStyle(): string | undefined;
27
+ get animationBlockStyle(): string | undefined;
26
28
  constructor(props: Omit<StreamdownProps, keyof Snippets | 'class'> & {
27
- snippets: Snippets;
29
+ snippets: Snippets<Source>;
28
30
  });
29
31
  }
30
- export declare const useStreamdown: () => StreamdownContext;
31
- import type { AlertToken, MathToken, SubSupToken, TableToken, THead, TBody, TFoot, THeadRow, TRow, TD, TH, Extension, GenericToken } from './marked/index.js';
32
+ export declare const useStreamdown: () => StreamdownContext<Record<string, any>>;
33
+ import type { AlertToken, MathToken, SubSupToken, TableToken, THead, TBody, TFoot, THeadRow, TRow, TD, TH, Extension, GenericToken, CitationToken } from './marked/index.js';
32
34
  import type { Tokens } from 'marked';
33
35
  import type { ListItemToken, ListToken } from './marked/marked-list.js';
34
36
  import type { Footnote, FootnoteRef, FootnoteToken } from './marked/marked-footnotes.js';
@@ -67,18 +69,29 @@ type TokenSnippet = {
67
69
  description: DescriptionToken;
68
70
  descriptionTerm: DescriptionTermToken;
69
71
  descriptionDetail: DescriptionDetailToken;
72
+ inlineCitation: CitationToken;
73
+ inlineCitationPopover: CitationToken;
74
+ inlineCitationContent: CitationToken;
75
+ inlineCitationPreview: CitationToken;
70
76
  };
71
77
  type PredefinedElements = keyof TokenSnippet;
72
- export type Snippets = {
78
+ export type Snippets<Source extends Record<string, any> = Record<string, any>> = {
73
79
  [K in PredefinedElements]?: Snippet<[
74
80
  {
75
81
  children: Snippet;
76
82
  token: TokenSnippet[K];
77
- }
83
+ } & (K extends 'inlineCitationContent' ? {
84
+ source: Source;
85
+ key: string;
86
+ } : {})
78
87
  ]>;
79
88
  };
80
- export type StreamdownProps = {
89
+ export type StreamdownProps<Source extends Record<string, any> = Record<string, any>> = {
81
90
  streamdown?: StreamdownContext;
91
+ sources?: {
92
+ [key: string]: Source;
93
+ };
94
+ inlineCitationsMode?: 'list' | 'carousel';
82
95
  element?: HTMLElement;
83
96
  content: string;
84
97
  class?: string;
@@ -105,6 +118,7 @@ export type StreamdownProps = {
105
118
  controls?: {
106
119
  code?: boolean;
107
120
  mermaid?: boolean;
121
+ table?: boolean;
108
122
  };
109
123
  renderHtml?: boolean | ((token: Tokens.HTML | Tokens.Tag) => string);
110
124
  animation?: {
@@ -127,6 +141,9 @@ export type StreamdownProps = {
127
141
  warning?: Snippet;
128
142
  caution?: Snippet;
129
143
  important?: Snippet;
144
+ chevronLeft?: Snippet;
145
+ chevronRight?: Snippet;
146
+ check?: Snippet;
130
147
  };
131
148
  extensions?: Extension[];
132
149
  children?: Snippet<[{
@@ -134,5 +151,5 @@ export type StreamdownProps = {
134
151
  token: GenericToken;
135
152
  children: Snippet;
136
153
  }]>;
137
- } & Partial<Snippets>;
154
+ } & Partial<Snippets<Source>>;
138
155
  export {};
@@ -5,8 +5,11 @@ export class StreamdownContext {
5
5
  footnotes: new Map()
6
6
  };
7
7
  isMounted = false;
8
- animationTextStyle = $derived(this.animation.enabled
9
- ? `animation-name: sd-${this.animation.type};
8
+ get animationTextStyle() {
9
+ return getContext('POPOVER')
10
+ ? undefined
11
+ : this.animation.enabled
12
+ ? `animation-name: sd-${this.animation.type};
10
13
  animation-duration: ${this.animation.duration}ms;
11
14
  animation-timing-function: ${this.animation.timingFunction};
12
15
  animation-iteration-count: 1;
@@ -14,14 +17,19 @@ animation-fill-mode: forwards;
14
17
  white-space: pre-wrap;
15
18
  display: inline-block;
16
19
  text-decoration: inherit;`
17
- : undefined);
18
- animationBlockStyle = $derived(this.animation.enabled
19
- ? `animation-name: sd-${this.animation.type};
20
+ : undefined;
21
+ }
22
+ get animationBlockStyle() {
23
+ return getContext('POPOVER')
24
+ ? undefined
25
+ : this.animation.enabled
26
+ ? `animation-name: sd-${this.animation.type};
20
27
  animation-duration: ${this.animation.duration}ms;
21
28
  animation-timing-function: ${this.animation.timingFunction};
22
29
  animation-iteration-count: 1;
23
30
  animation-fill-mode: forwards;`
24
- : undefined);
31
+ : undefined;
32
+ }
25
33
  constructor(props) {
26
34
  bind(this, props);
27
35
  setContext('streamdown', this);
@@ -8,6 +8,8 @@ import { type BrToken } from './marked-br.js';
8
8
  import { type HrToken } from './marked-hr.js';
9
9
  import { type TableToken, type THead, type TBody, type TFoot, type THeadRow, type TRow, type TH, type TD } from './marked-table.js';
10
10
  import { type DescriptionDetailToken, type DescriptionListToken, type DescriptionTermToken, type DescriptionToken } from './marked-dl.js';
11
+ import { type AlignToken } from './marked-align.js';
12
+ import { type CitationToken } from './marked-citations.js';
11
13
  export type GenericToken = {
12
14
  type: string;
13
15
  raw: string;
@@ -20,8 +22,8 @@ export type Extension = {
20
22
  start?: TokenizerStartFunction;
21
23
  applyInBlockParsing?: boolean;
22
24
  };
23
- export type StreamdownToken = Exclude<MarkedToken, Tokens.List | Tokens.ListItem> | ListToken | ListItemToken | MathToken | AlertToken | FootnoteToken | SubSupToken | BrToken | HrToken | TableToken | THead | TBody | TFoot | THeadRow | TRow | TH | TD | DescriptionListToken | DescriptionToken | DescriptionDetailToken | DescriptionTermToken;
25
+ export type StreamdownToken = Exclude<MarkedToken, Tokens.List | Tokens.ListItem | Tokens.Table> | ListToken | ListItemToken | MathToken | AlertToken | FootnoteToken | SubSupToken | BrToken | HrToken | TableToken | THead | TBody | TFoot | THeadRow | TRow | TH | TD | DescriptionListToken | DescriptionToken | DescriptionDetailToken | DescriptionTermToken | AlignToken | CitationToken;
24
26
  export type { TableToken, THead, TBody, TFoot, THeadRow, TRow, TH, TD } from './marked-table.js';
25
27
  export declare const lex: (markdown: string, extensions?: Extension[]) => StreamdownToken[];
26
28
  export declare const parseBlocks: (markdown: string, extensions?: Extension[]) => string[];
27
- export type { MathToken, AlertToken, FootnoteToken, SubSupToken, BrToken, HrToken };
29
+ export type { MathToken, AlertToken, FootnoteToken, SubSupToken, BrToken, HrToken, AlignToken, CitationToken };
@@ -8,6 +8,8 @@ import { markedBr } from './marked-br.js';
8
8
  import { markedHr } from './marked-hr.js';
9
9
  import { markedTable } from './marked-table.js';
10
10
  import { markedDl } from './marked-dl.js';
11
+ import { markedAlign } from './marked-align.js';
12
+ import { markedCitations } from './marked-citations.js';
11
13
  const parseExtensions = (...extensions) => {
12
14
  const options = {
13
15
  gfm: true,
@@ -41,12 +43,12 @@ const parseExtensions = (...extensions) => {
41
43
  return options;
42
44
  };
43
45
  export const lex = (markdown, extensions = []) => {
44
- return new Lexer(parseExtensions(markedHr, markedTable, ...markedFootnote(), markedAlert, ...markedMath, markedSub, markedSup, markedList, markedBr, markedDl, ...extensions))
46
+ return new Lexer(parseExtensions(markedHr, markedTable, ...markedFootnote(), markedAlert, ...markedMath, markedSub, markedSup, markedList, markedBr, markedDl, markedAlign, markedCitations, ...extensions))
45
47
  .lex(markdown)
46
48
  .filter((token) => token.type !== 'space' && token.type !== 'footnote');
47
49
  };
48
50
  export const parseBlocks = (markdown, extensions = []) => {
49
- const blockLexer = new Lexer(parseExtensions(markedHr, ...markedFootnote(), markedDl, markedTable, ...extensions.filter(({ level, applyInBlockParsing }) => level === 'block' && applyInBlockParsing)));
51
+ const blockLexer = new Lexer(parseExtensions(markedHr, ...markedFootnote(), markedDl, markedTable, markedAlign, ...extensions.filter(({ level, applyInBlockParsing }) => level === 'block' && applyInBlockParsing)));
50
52
  return blockLexer.blockTokens(markdown, []).reduce((acc, block) => {
51
53
  if (block.type === 'space' || block.type === 'footnote') {
52
54
  return acc;
@@ -0,0 +1,10 @@
1
+ import type { Extension } from './index.js';
2
+ import type { Token } from 'marked';
3
+ export declare const markedAlign: Extension;
4
+ export type AlignToken = {
5
+ type: 'align';
6
+ align: 'center' | 'right';
7
+ raw: string;
8
+ text: string;
9
+ tokens: Token[];
10
+ };
@@ -0,0 +1,36 @@
1
+ export const markedAlign = {
2
+ name: 'align',
3
+ level: 'block',
4
+ tokenizer(src) {
5
+ // Check if the source starts with [center] or [right] blocks
6
+ const centerMatch = src.match(/^\[center\]\n([\s\S]*?)\n\[\/center\]/);
7
+ const rightMatch = src.match(/^\[right\]\n([\s\S]*?)\n\[\/right\]/);
8
+ if (centerMatch) {
9
+ const text = centerMatch[1];
10
+ const raw = centerMatch[0];
11
+ // Tokenize the content inside the alignment block
12
+ const tokens = this.lexer.blockTokens(text, []);
13
+ return {
14
+ type: 'align',
15
+ align: 'center',
16
+ raw,
17
+ text,
18
+ tokens
19
+ };
20
+ }
21
+ if (rightMatch) {
22
+ const text = rightMatch[1];
23
+ const raw = rightMatch[0];
24
+ // Tokenize the content inside the alignment block
25
+ const tokens = this.lexer.blockTokens(text, []);
26
+ return {
27
+ type: 'align',
28
+ align: 'right',
29
+ raw,
30
+ text,
31
+ tokens
32
+ };
33
+ }
34
+ return undefined;
35
+ }
36
+ };
@@ -0,0 +1,8 @@
1
+ import type { Extension } from './index.js';
2
+ export declare const markedCitations: Extension;
3
+ export type CitationToken = {
4
+ type: 'inline-citations';
5
+ keys: string[];
6
+ text: string;
7
+ raw: string;
8
+ };