@gpichot/spectacle-deck 1.2.1 → 1.2.3

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 (76) hide show
  1. package/{dist/index.cjs → index.cjs} +2 -1
  2. package/{dist/index.mjs → index.mjs} +2 -1
  3. package/package.json +16 -21
  4. package/.turbo/turbo-build.log +0 -4
  5. package/.turbo/turbo-dev.log +0 -4
  6. package/publish.sh +0 -7
  7. package/scripts/bundle.ts +0 -84
  8. package/src/SlideWrapper.tsx +0 -25
  9. package/src/colors.ts +0 -42
  10. package/src/components/CodeStepper/CodeStepper.tsx +0 -228
  11. package/src/components/CodeStepper/code-directives.test.ts +0 -58
  12. package/src/components/CodeStepper/code-directives.ts +0 -129
  13. package/src/components/DocumentationItem.tsx +0 -85
  14. package/src/components/FilePane.tsx +0 -18
  15. package/src/components/HorizontalList.tsx +0 -141
  16. package/src/components/IconBox.tsx +0 -31
  17. package/src/components/Image.tsx +0 -39
  18. package/src/components/ItemsColumn.tsx +0 -60
  19. package/src/components/QRCode.tsx +0 -55
  20. package/src/components/Timeline.styled.tsx +0 -24
  21. package/src/components/Timeline.tsx +0 -159
  22. package/src/components/map.tsx +0 -128
  23. package/src/components/styled.tsx +0 -73
  24. package/src/context.tsx +0 -33
  25. package/src/front.png +0 -0
  26. package/src/index.tsx +0 -127
  27. package/src/layouts/BaseLayout.tsx +0 -52
  28. package/src/layouts/CenteredLayout.tsx +0 -40
  29. package/src/layouts/Default3Layout.tsx +0 -159
  30. package/src/layouts/MainSectionLayout.tsx +0 -31
  31. package/src/layouts/QuoteLayout.tsx +0 -107
  32. package/src/layouts/SectionLayout.tsx +0 -14
  33. package/src/layouts/SideCodeLayout.tsx +0 -44
  34. package/src/layouts/SideImageLayout.tsx +0 -82
  35. package/src/layouts/SideLayout.tsx +0 -31
  36. package/src/layouts/columns.tsx +0 -56
  37. package/src/layouts/index.tsx +0 -19
  38. package/src/layouts/styled.ts +0 -7
  39. package/src/layouts/utils.ts +0 -66
  40. package/src/node.d.ts +0 -5
  41. package/src/style.d.ts +0 -10
  42. package/src/template.tsx +0 -25
  43. package/src/theme.ts +0 -28
  44. package/tsconfig.json +0 -29
  45. /package/{dist/SlideWrapper.d.ts → SlideWrapper.d.ts} +0 -0
  46. /package/{dist/colors.d.ts → colors.d.ts} +0 -0
  47. /package/{dist/components → components}/CodeStepper/CodeStepper.d.ts +0 -0
  48. /package/{dist/components → components}/CodeStepper/code-directives.d.ts +0 -0
  49. /package/{dist/components → components}/DocumentationItem.d.ts +0 -0
  50. /package/{dist/components → components}/FilePane.d.ts +0 -0
  51. /package/{dist/components → components}/HorizontalList.d.ts +0 -0
  52. /package/{dist/components → components}/IconBox.d.ts +0 -0
  53. /package/{dist/components → components}/Image.d.ts +0 -0
  54. /package/{dist/components → components}/ItemsColumn.d.ts +0 -0
  55. /package/{dist/components → components}/QRCode.d.ts +0 -0
  56. /package/{dist/components → components}/Timeline.d.ts +0 -0
  57. /package/{dist/components → components}/Timeline.styled.d.ts +0 -0
  58. /package/{dist/components → components}/map.d.ts +0 -0
  59. /package/{dist/components → components}/styled.d.ts +0 -0
  60. /package/{dist/context.d.ts → context.d.ts} +0 -0
  61. /package/{dist/index.d.ts → index.d.ts} +0 -0
  62. /package/{dist/layouts → layouts}/BaseLayout.d.ts +0 -0
  63. /package/{dist/layouts → layouts}/CenteredLayout.d.ts +0 -0
  64. /package/{dist/layouts → layouts}/Default3Layout.d.ts +0 -0
  65. /package/{dist/layouts → layouts}/MainSectionLayout.d.ts +0 -0
  66. /package/{dist/layouts → layouts}/QuoteLayout.d.ts +0 -0
  67. /package/{dist/layouts → layouts}/SectionLayout.d.ts +0 -0
  68. /package/{dist/layouts → layouts}/SideCodeLayout.d.ts +0 -0
  69. /package/{dist/layouts → layouts}/SideImageLayout.d.ts +0 -0
  70. /package/{dist/layouts → layouts}/SideLayout.d.ts +0 -0
  71. /package/{dist/layouts → layouts}/columns.d.ts +0 -0
  72. /package/{dist/layouts → layouts}/index.d.ts +0 -0
  73. /package/{dist/layouts → layouts}/styled.d.ts +0 -0
  74. /package/{dist/layouts → layouts}/utils.d.ts +0 -0
  75. /package/{dist/template.d.ts → template.d.ts} +0 -0
  76. /package/{dist/theme.d.ts → theme.d.ts} +0 -0
@@ -1152,7 +1152,8 @@ function QRCode({ url, size = "md" }) {
1152
1152
  style: {
1153
1153
  padding: "1rem 1rem 0.6rem 1rem",
1154
1154
  borderRadius: "1rem",
1155
- backgroundColor
1155
+ backgroundColor,
1156
+ maxWidth: "calc(${width}px + 2rem)"
1156
1157
  }
1157
1158
  }
1158
1159
  );
@@ -1105,7 +1105,8 @@ function QRCode({ url, size = "md" }) {
1105
1105
  style: {
1106
1106
  padding: "1rem 1rem 0.6rem 1rem",
1107
1107
  borderRadius: "1rem",
1108
- backgroundColor
1108
+ backgroundColor,
1109
+ maxWidth: "calc(${width}px + 2rem)"
1109
1110
  }
1110
1111
  }
1111
1112
  );
package/package.json CHANGED
@@ -1,12 +1,21 @@
1
1
  {
2
2
  "name": "@gpichot/spectacle-deck",
3
- "version": "1.2.1",
4
- "description": "",
5
- "module": "src/index.tsx",
6
- "types": "src/index.d.ts",
7
- "keywords": [],
8
- "author": "",
9
- "license": "ISC",
3
+ "version": "1.2.3",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "index.cjs",
7
+ "types": "index.d.ts",
8
+ "module": "index.mjs",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "require": "./index.cjs",
13
+ "import": "./index.mjs"
14
+ }
15
+ },
16
+ "keywords": [
17
+ "spectacle"
18
+ ],
10
19
  "dependencies": {
11
20
  "@fontsource/bitter": "^5.0.18",
12
21
  "@mdx-js/react": "^3.0.1",
@@ -18,19 +27,5 @@
18
27
  "react-syntax-highlighter": "^15.5.0",
19
28
  "spectacle": "^10.1.8",
20
29
  "styled-components": "^6.1.11"
21
- },
22
- "devDependencies": {
23
- "@arnaud-barre/tnode": "^0.19.2",
24
- "@types/react": "^18.3.2",
25
- "@types/react-dom": "^18.3.0",
26
- "@types/react-is": "^18.3.0",
27
- "@types/react-syntax-highlighter": "^15.5.13",
28
- "esbuild": "^0.21.3",
29
- "typescript": "^5.4.5"
30
- },
31
- "scripts": {
32
- "test": "echo \"Error: no test specified\" && exit 1",
33
- "dev": "tnode scripts/bundle.ts",
34
- "build": "tnode scripts/bundle.ts"
35
30
  }
36
31
  }
@@ -1,4 +0,0 @@
1
-
2
- > @gpichot/spectacle-deck@1.1.7 build /Users/gabriel/Dev/CraftValue/Formations/presentations-next/packages/spectacle-deck
3
- > tnode scripts/bundle.ts
4
-
@@ -1,4 +0,0 @@
1
-
2
- > @gpichot/spectacle-deck@1.1.7 dev /Users/gabriel/Dev/CraftValue/Formations/presentations-next/packages/spectacle-deck
3
- > tnode scripts/bundle.ts
4
-
package/publish.sh DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/sh
2
-
3
- pnpm run build
4
-
5
- cd dist
6
-
7
- pnpm publish --no-git-checks
package/scripts/bundle.ts DELETED
@@ -1,84 +0,0 @@
1
- import { rmSync, writeFileSync, copyFileSync } from "node:fs";
2
- import { execSync } from "node:child_process";
3
- import { build, BuildOptions, context } from "esbuild";
4
-
5
- import packageJSON from "../package.json";
6
-
7
- const dev = process.argv.includes("--dev");
8
-
9
- rmSync("dist", { force: true, recursive: true });
10
-
11
- const serverOptions: BuildOptions = {
12
- bundle: true,
13
- platform: "node",
14
- target: "node14",
15
- legalComments: "inline",
16
- loader: {
17
- ".png": "dataurl",
18
- },
19
- external: Object.keys(packageJSON.peerDependencies || {}).concat(
20
- Object.keys(packageJSON.dependencies || {}),
21
- ),
22
- };
23
-
24
- const buildOrWatch = async (options: BuildOptions) => {
25
- if (!dev) return build(options);
26
- const ctx = await context(options);
27
- await ctx.watch();
28
- await ctx.rebuild();
29
- };
30
-
31
- Promise.all([
32
- buildOrWatch({
33
- ...serverOptions,
34
- stdin: {
35
- contents: `import * as mod from "./src";
36
- module.exports = mod;
37
- `,
38
- resolveDir: ".",
39
- },
40
- outfile: "dist/index.cjs",
41
- logOverride: { "empty-import-meta": "silent" },
42
- }),
43
- buildOrWatch({
44
- ...serverOptions,
45
- entryPoints: ["src/index.tsx"],
46
- format: "esm",
47
- outfile: "dist/index.mjs",
48
- }),
49
- ]).then(() => {
50
- // copyFileSync("LICENSE", "dist/LICENSE");
51
- // copyFileSync("README.md", "dist/README.md");
52
-
53
- execSync(
54
- "tsc src/index.tsx --declaration --jsx react --emitDeclarationOnly --outDir dist --module preserve --target es2020 --allowSyntheticDefaultImports --skipLibCheck --moduleResolution bundler --types ./src/node.d.ts,./src/style.d.ts",
55
- { stdio: "inherit" },
56
- );
57
-
58
- writeFileSync(
59
- "dist/package.json",
60
- JSON.stringify(
61
- {
62
- name: "@gpichot/spectacle-deck",
63
- version: packageJSON.version,
64
- license: "MIT",
65
- type: "module",
66
- main: "index.cjs",
67
- types: "index.d.ts",
68
- module: "index.mjs",
69
- exports: {
70
- ".": {
71
- types: "./index.d.ts",
72
- require: "./index.cjs",
73
- import: "./index.mjs",
74
- },
75
- },
76
- keywords: ["spectacle"],
77
- peerDependencies: packageJSON.peerDependencies,
78
- dependencies: packageJSON.dependencies,
79
- },
80
- null,
81
- 2,
82
- ),
83
- );
84
- });
@@ -1,25 +0,0 @@
1
- import React from "react";
2
- import { usePestacle } from "./context";
3
-
4
- export function SlideWrapper({
5
- children,
6
- frontmatter,
7
- }: {
8
- children: React.ReactNode;
9
- frontmatter: { layout?: string };
10
- }) {
11
- const { layouts } = usePestacle();
12
- const layout = frontmatter?.layout || "default";
13
- console.log(layouts, layout);
14
- const Layout = layout in layouts ? layouts[layout] : null;
15
-
16
- if (layout && !Layout) {
17
- console.warn(`Layout ${layout} not found`);
18
- }
19
-
20
- if (Layout) {
21
- return <Layout {...frontmatter}>{children}</Layout>;
22
- }
23
-
24
- return <>{children}</>;
25
- }
package/src/colors.ts DELETED
@@ -1,42 +0,0 @@
1
- /**
2
- * Extract colors from `rgb(...) or rgba(...)` string or #hex string
3
- */
4
- export function extractColors(color: string): {
5
- r: number;
6
- g: number;
7
- b: number;
8
- } {
9
- if (color.startsWith("rgb")) {
10
- const [r, g, b] = color
11
- .replace("rgb(", "")
12
- .replace("rgba(", "")
13
- .replace(")", "")
14
- .split(",")
15
- .map((c) => parseInt(c.trim(), 10));
16
- return { r, g, b };
17
- } else if (color.startsWith("#")) {
18
- const hex = color.replace("#", "");
19
- const r = parseInt(hex.substring(0, 2), 16);
20
- const g = parseInt(hex.substring(2, 4), 16);
21
- const b = parseInt(hex.substring(4, 6), 16);
22
- return { r, g, b };
23
- }
24
- throw new Error(`Invalid color format: ${color}`);
25
- }
26
-
27
- /**
28
- * Create vars for css colors
29
- */
30
- export function createCssVariables(colors: { [key: string]: string }) {
31
- const base = Object.entries(colors)
32
- .map(([key, value]) => `--color-${key}: ${value};`)
33
- .join("\n");
34
- const rgbs = Object.entries(colors)
35
- .map(([key, value]) => {
36
- const { r, g, b } = extractColors(value);
37
- return `--color-${key}-rgb: ${r}, ${g}, ${b};`;
38
- })
39
- .join("\n");
40
-
41
- return `${base}\n${rgbs}`;
42
- }
@@ -1,228 +0,0 @@
1
- import React from "react";
2
- import ReactIs from "react-is";
3
- import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
4
- import { gruvboxDark } from "react-syntax-highlighter/dist/esm/styles/prism";
5
- import { Stepper } from "spectacle";
6
- import styled from "styled-components";
7
-
8
- import { parseStepDirectives, Step } from "./code-directives";
9
-
10
- const Highlighter = SyntaxHighlighter as unknown as React.ElementType;
11
-
12
- const CodeContainer = styled.div`
13
- pre {
14
- padding: 1rem 0rem !important;
15
- background-color: transparent !important;
16
- }
17
- .linenumber {
18
- min-width: 2rem !important;
19
- }
20
- [data-highlight-line="true"] {
21
- &:before {
22
- content: " ";
23
- position: absolute;
24
- background-color: rgba(var(--color-primary-rgb), 0.5);
25
- }
26
-
27
- &[data-step-active="true"]:before {
28
- background-color: var(--color-secondary);
29
- }
30
- }
31
- `;
32
-
33
- function useCodeSteps(code: string) {
34
- return React.useMemo(() => {
35
- const prefixes = code.match(/(?:\/\/|<!--) @.*\n/g) || ([] as string[]);
36
- const prefixesLength = prefixes.reduce(
37
- (acc, prefix) => acc + prefix.length,
38
- 0,
39
- );
40
-
41
- const codeWithoutPrefixes = code.slice(prefixesLength);
42
-
43
- const hasDirectives = prefixes.length > 0;
44
- const allDirectives = hasDirectives ? [...prefixes] : [];
45
- const steps = parseStepDirectives(allDirectives);
46
-
47
- return {
48
- steps,
49
- code: codeWithoutPrefixes,
50
- prefixes,
51
- hasSteps: Boolean(steps.length),
52
- hasName: steps.some((step) => step.name),
53
- };
54
- }, [code]);
55
- }
56
-
57
- function getCodeDetails(children: React.ReactNode) {
58
- const child = React.Children.toArray(children)[0];
59
-
60
- if (!React.isValidElement(child)) {
61
- return {
62
- language: "",
63
- code: ReactIs.isFragment(child) ? "" : String(child || ""),
64
- };
65
- }
66
-
67
- const result = {
68
- language: (String(child.props.className) || "").replace("language-", ""),
69
- code: (child.props.children as string).trim(),
70
- };
71
-
72
- return result;
73
- }
74
-
75
- function CodeWrapper({
76
- name,
77
- stepName,
78
- hasName,
79
- children,
80
- }: {
81
- name?: string;
82
- stepName?: string;
83
- hasName?: boolean;
84
- children: React.ReactNode;
85
- }) {
86
- return (
87
- <div
88
- style={{
89
- boxSizing: "border-box",
90
- margin: "0.5rem 1rem",
91
- backgroundColor: "rgb(38,39,40)",
92
- borderRadius: "4px",
93
- }}
94
- >
95
- {name && (
96
- <span
97
- style={{
98
- fontFamily: 'Consolas, Monaco, "Andale Mono", monospace',
99
- fontSize: "1rem",
100
- color: "#ffffffbb",
101
- backgroundColor: "#33333388",
102
- display: "inline-block",
103
- padding: "8px 8px",
104
- width: "100%",
105
- boxSizing: "border-box",
106
- }}
107
- >
108
- {name}
109
- </span>
110
- )}
111
- {children}
112
- {hasName && (
113
- <span
114
- style={{
115
- fontFamily: 'Consolas, Monaco, "Andale Mono", monospace',
116
- fontSize: "0.8rem",
117
- color: "#ffffffaa",
118
- backgroundColor: "#33333388",
119
- display: "inline-block",
120
- padding: "4px 8px",
121
- width: "100%",
122
- boxSizing: "border-box",
123
- fontStyle: "italic",
124
- }}
125
- >
126
- {stepName || <span style={{ visibility: "hidden" }}>Step</span>}
127
- </span>
128
- )}
129
- </div>
130
- );
131
- }
132
-
133
- export default function CodeStepper({
134
- priority,
135
- name,
136
- ...props
137
- }: React.ComponentProps<"pre"> & {
138
- priority?: number;
139
- name?: string;
140
- }) {
141
- const { language, code } = React.useMemo(() => {
142
- return getCodeDetails(props.children);
143
- }, [props.children]);
144
-
145
- const {
146
- steps,
147
- code: codeNormalized,
148
- prefixes,
149
- hasSteps,
150
- hasName,
151
- } = useCodeSteps(code);
152
- return (
153
- <CodeContainer>
154
- {import.meta.env.DEV && false && Boolean(prefixes?.length) && (
155
- <div style={{ position: "absolute", top: 0, opacity: 0.5, left: 0 }}>
156
- <Highlighter language={language} style={gruvboxDark}>
157
- {prefixes.join("")}
158
- </Highlighter>
159
- </div>
160
- )}
161
- <Stepper
162
- values={steps}
163
- alwaysVisible={!hasSteps}
164
- priority={priority ? priority + 1 : undefined}
165
- >
166
- {(step, _, isActive) => {
167
- console.log({ step, isActive });
168
- return (
169
- <CodeWrapper
170
- name={name}
171
- stepName={(step as Step | null)?.name}
172
- hasName={hasName}
173
- >
174
- <Highlighter
175
- language={language}
176
- wrapLines
177
- showLineNumbers
178
- style={gruvboxDark}
179
- lineNumberStyle={(lineNumber: number) => {
180
- const { highlight = [] } = (step as Step) || {};
181
- const isHighlighted = highlight.includes(lineNumber);
182
-
183
- return {
184
- fontWeight: isHighlighted ? "bold" : "normal",
185
- };
186
- }}
187
- lineProps={(lineNumber: number) => {
188
- const { hiddenLines = [], highlight = [] } =
189
- (step as Step) || {};
190
- const isVisible =
191
- hasSteps && isActive
192
- ? !hiddenLines.includes(lineNumber)
193
- : isActive || !hasSteps;
194
- const isHighlighted = highlight.includes(lineNumber);
195
- const getOpacity = () => {
196
- if (!isVisible) return 0;
197
- if (isHighlighted || !highlight.length) return 1;
198
- return 0.8;
199
- };
200
-
201
- return {
202
- ...(isHighlighted && {
203
- "data-highlight-line": isHighlighted,
204
- "data-step-active": isActive,
205
- }),
206
- style: {
207
- opacity: getOpacity(),
208
- transition: "all 0.3s ease",
209
- display: "block",
210
- width: "100%",
211
- backgroundColor: isHighlighted
212
- ? "rgba(var(--color-secondary-rgb), 0.13)"
213
- : "",
214
- },
215
- };
216
- }}
217
- >
218
- {codeNormalized}
219
- </Highlighter>
220
- </CodeWrapper>
221
- );
222
- }}
223
- </Stepper>
224
- </CodeContainer>
225
- );
226
- }
227
-
228
- CodeStepper.mdxType = "CodeStepper";
@@ -1,58 +0,0 @@
1
- import { parseStepDirectives } from './code-directives';
2
-
3
- function splitDirectives(str: string): string[] {
4
- return str.trim().split('\n');
5
- }
6
-
7
- describe('parseStepDirectives', () => {
8
- it('should reduce properly with showLines', () => {
9
- const directives = splitDirectives(`
10
- // @step showLines(1-3) highlight(1-3)
11
- // @step showLines(4-6) highlight(4-6)
12
- `);
13
-
14
- const result = parseStepDirectives(directives);
15
- expect(result[0]).toEqual({ hiddenLines: [4, 5, 6], highlight: [1, 2, 3] });
16
- expect(result[1]).toEqual({ hiddenLines: [], highlight: [4, 5, 6] });
17
- });
18
-
19
- it('should reduce properly with highlight', () => {
20
- const directives = splitDirectives(`
21
- // @step highlight(3)
22
- // @step showLines(4) highlight(4)
23
- `);
24
-
25
- const result = parseStepDirectives(directives);
26
- expect(result).toHaveLength(2);
27
- expect(result[0]).toEqual({ hiddenLines: [4], highlight: [3] });
28
- expect(result[1]).toEqual({ hiddenLines: [], highlight: [4] });
29
- });
30
-
31
- it('parse only highlights', () => {
32
- const directives = splitDirectives(`
33
- // @step highlight(6)
34
- // @step highlight(7-9)
35
- // @step highlight(10)
36
- `);
37
-
38
- const result = parseStepDirectives(directives);
39
- expect(result).toHaveLength(3);
40
- expect(result[0]).toEqual({ hiddenLines: [], highlight: [6] });
41
- expect(result[1]).toEqual({ hiddenLines: [], highlight: [7, 8, 9] });
42
- expect(result[2]).toEqual({ hiddenLines: [], highlight: [10] });
43
- });
44
-
45
- it('parses typescript lines', () => {
46
- const directives = splitDirectives(`
47
- // @step highlight(3) name("(string|number)[]")
48
- `);
49
-
50
- const result = parseStepDirectives(directives);
51
- expect(result).toHaveLength(1);
52
- expect(result[0]).toEqual({
53
- hiddenLines: [],
54
- highlight: [3],
55
- name: '(string|number)[]',
56
- });
57
- });
58
- });
@@ -1,129 +0,0 @@
1
- /**
2
- * The Code Stepper component is a component that allows you to step through
3
- * the code using familiar directives.
4
- *
5
- * @example "@step showLines(1-3)" will show lines 1-3
6
- * @example "@step highlight(1-3)" will highlight lines 1-3
7
- *
8
- */
9
-
10
- function range(start: number, end: number) {
11
- return Array.from({ length: end - start + 1 }, (_, i) => i + start);
12
- }
13
-
14
- /**
15
- * Function parse ranges list
16
- */
17
- function parseRangeList(str: string): number[] {
18
- return str.split(',').reduce((acc, line) => {
19
- if (!line.includes('-')) return [...acc, parseInt(line, 10)];
20
-
21
- const [start, end] = line.split('-').map(Number);
22
- return [...acc, ...range(start, end)];
23
- }, [] as number[]);
24
- }
25
-
26
- /**
27
- * Parse showLines fn
28
- *
29
- * "showLines(1-3)" => [1, 2, 3]
30
- * "showLines(1,3)" => [1,3]
31
- * "showLines(1-2,4-5)" => [1,2,4,5]
32
- */
33
- function parseShowLines(directive: string): { showLines: number[] } | null {
34
- const match = directive.match(/showLines\((.*)\)/);
35
- if (!match) return null;
36
-
37
- const lines = parseRangeList(match[1]);
38
-
39
- return { showLines: lines };
40
- }
41
-
42
- /**
43
- * Parse highlight fn
44
- *
45
- * "highlight(1-3)" => [1,2,3]
46
- * etc.
47
- */
48
- function parseHighlight(directive: string): { highlight: number[] } | null {
49
- const match = directive.match(/highlight\((.*)\)/);
50
- if (!match) return null;
51
-
52
- const lines = parseRangeList(match[1]);
53
-
54
- return { highlight: lines };
55
- }
56
-
57
- type StepDirective = {
58
- showLines?: number[];
59
- highlight?: number[];
60
- name?: string;
61
- };
62
-
63
- /**
64
- * Parse name fn
65
- *
66
- * "name("my name")" => "my name"
67
- */
68
- function parseName(directive: string): { name: string } | null {
69
- const match = directive.match(/name\("(.*)"\)/);
70
- if (!match) return null;
71
-
72
- return { name: match[1] };
73
- }
74
-
75
- /**
76
- * Parse step directive
77
- *
78
- * @example "@step showLines(1-3) highlight(1-3)"
79
- * @example "@step showLines(1-3)"
80
- * @example "@step highlight(1-3)"
81
- */
82
- function parseStepDirective(directive: string): StepDirective {
83
- // Should match a showLines(1-3) or highlight(1-3) directive
84
- // Should match name("(string)")
85
- const regex = /showLines\([^)]+\)|highlight\([^)]+\)|name\("(.*)"\)/g;
86
-
87
- const directives = directive.match(regex) || [];
88
-
89
- const name = directives.map(parseName).find(Boolean);
90
- const showLines = directives.map(parseShowLines).find(Boolean);
91
- const highlight = directives.map(parseHighlight).find(Boolean);
92
-
93
- return { ...showLines, ...highlight, ...name };
94
- }
95
-
96
- export type Step = {
97
- hiddenLines: number[];
98
- highlight: number[];
99
- name?: string;
100
- };
101
-
102
- /**
103
- * Reduce steps directives
104
- */
105
- export function combineStepDirectives(directives: StepDirective[]): Step[] {
106
- let hiddenLines = directives.reduce((acc, { showLines }) => {
107
- if (!showLines) return acc;
108
-
109
- return [...acc, ...showLines];
110
- }, [] as number[]);
111
-
112
- return directives.map(({ highlight, showLines, name }) => {
113
- hiddenLines = hiddenLines.filter((line) => !showLines?.includes(line));
114
- return {
115
- highlight: highlight || [],
116
- hiddenLines,
117
- name,
118
- };
119
- });
120
- }
121
-
122
- /**
123
- * Parse step directives
124
- */
125
- export function parseStepDirectives(directives: string[]): Step[] {
126
- const parsedDirectives = directives.map(parseStepDirective);
127
-
128
- return combineStepDirectives(parsedDirectives);
129
- }