@gpichot/spectacle-deck 1.1.1 → 1.1.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.
- package/{dist/index.cjs → index.cjs} +200 -148
- package/{dist/index.mjs → index.mjs} +199 -147
- package/layouts/BaseLayout.d.ts +5 -0
- package/package.json +16 -20
- package/dist/package.json +0 -30
- package/scripts/bundle.ts +0 -84
- package/src/components/CodeStepper/CodeStepper.tsx +0 -223
- package/src/components/CodeStepper/code-directives.test.ts +0 -58
- package/src/components/CodeStepper/code-directives.ts +0 -129
- package/src/components/DocumentationItem.tsx +0 -85
- package/src/components/FilePane.tsx +0 -18
- package/src/components/HorizontalList.tsx +0 -140
- package/src/components/IconBox.tsx +0 -31
- package/src/components/Image.tsx +0 -34
- package/src/components/ItemsColumn.tsx +0 -56
- package/src/components/Timeline.styled.tsx +0 -24
- package/src/components/Timeline.tsx +0 -159
- package/src/components/map.tsx +0 -115
- package/src/components/styled.tsx +0 -73
- package/src/front.png +0 -0
- package/src/index.tsx +0 -109
- package/src/layouts/CenteredLayout.tsx +0 -40
- package/src/layouts/Default3Layout.tsx +0 -159
- package/src/layouts/MainSectionLayout.tsx +0 -31
- package/src/layouts/QuoteLayout.tsx +0 -99
- package/src/layouts/SectionLayout.tsx +0 -14
- package/src/layouts/SideCodeLayout.tsx +0 -44
- package/src/layouts/SideImageLayout.tsx +0 -72
- package/src/layouts/SideLayout.tsx +0 -31
- package/src/layouts/columns.tsx +0 -56
- package/src/layouts/index.tsx +0 -19
- package/src/layouts/styled.ts +0 -7
- package/src/layouts/utils.ts +0 -65
- package/src/node.d.ts +0 -5
- package/src/style.d.ts +0 -10
- package/src/template.tsx +0 -25
- package/src/theme.ts +0 -24
- package/test.js +0 -106
- package/tsconfig.json +0 -29
- /package/{dist/components → components}/CodeStepper/CodeStepper.d.ts +0 -0
- /package/{dist/components → components}/CodeStepper/code-directives.d.ts +0 -0
- /package/{dist/components → components}/DocumentationItem.d.ts +0 -0
- /package/{dist/components → components}/FilePane.d.ts +0 -0
- /package/{dist/components → components}/HorizontalList.d.ts +0 -0
- /package/{dist/components → components}/IconBox.d.ts +0 -0
- /package/{dist/components → components}/Image.d.ts +0 -0
- /package/{dist/components → components}/ItemsColumn.d.ts +0 -0
- /package/{dist/components → components}/Timeline.d.ts +0 -0
- /package/{dist/components → components}/Timeline.styled.d.ts +0 -0
- /package/{dist/components → components}/map.d.ts +0 -0
- /package/{dist/components → components}/styled.d.ts +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/layouts → layouts}/CenteredLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/Default3Layout.d.ts +0 -0
- /package/{dist/layouts → layouts}/MainSectionLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/QuoteLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/SectionLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/SideCodeLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/SideImageLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/SideLayout.d.ts +0 -0
- /package/{dist/layouts → layouts}/columns.d.ts +0 -0
- /package/{dist/layouts → layouts}/index.d.ts +0 -0
- /package/{dist/layouts → layouts}/styled.d.ts +0 -0
- /package/{dist/layouts → layouts}/utils.d.ts +0 -0
- /package/{dist/template.d.ts → template.d.ts} +0 -0
- /package/{dist/theme.d.ts → theme.d.ts} +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export declare const BaseLayout: ({ children, title, ...otherProps }: {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
title?: React.ReactNode;
|
|
5
|
+
} & Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "title">) => React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gpichot/spectacle-deck",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
3
|
+
"version": "1.1.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.16",
|
|
12
21
|
"@mdx-js/react": "^3.0.0",
|
|
@@ -17,18 +26,5 @@
|
|
|
17
26
|
"react-syntax-highlighter": "^15.5.0",
|
|
18
27
|
"spectacle": "^10.1.7",
|
|
19
28
|
"styled-components": "^6.1.8"
|
|
20
|
-
},
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"@arnaud-barre/tnode": "^0.19.2",
|
|
23
|
-
"@types/react": "^18.2.47",
|
|
24
|
-
"@types/react-dom": "^18.2.18",
|
|
25
|
-
"@types/react-is": "^18.2.4",
|
|
26
|
-
"@types/react-syntax-highlighter": "^15.5.11",
|
|
27
|
-
"esbuild": "^0.19.11",
|
|
28
|
-
"typescript": "^5.3.3"
|
|
29
|
-
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
32
|
-
"build": "tnode scripts/bundle.ts"
|
|
33
29
|
}
|
|
34
30
|
}
|
package/dist/package.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@gpichot/spectacle-deck",
|
|
3
|
-
"version": "1.1.1",
|
|
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
|
-
],
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"@fontsource/bitter": "^5.0.16",
|
|
21
|
-
"@mdx-js/react": "^3.0.0",
|
|
22
|
-
"react": "^18.2.0",
|
|
23
|
-
"react-dom": "^18.2.0",
|
|
24
|
-
"react-is": "^18.2.0",
|
|
25
|
-
"react-spring": "^9.7.3",
|
|
26
|
-
"react-syntax-highlighter": "^15.5.0",
|
|
27
|
-
"spectacle": "^10.1.7",
|
|
28
|
-
"styled-components": "^6.1.8"
|
|
29
|
-
}
|
|
30
|
-
}
|
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 es2020 --target es2020 --allowSyntheticDefaultImports --skipLibCheck --moduleResolution node --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,223 +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: #f4967688;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
&[data-step-active="true"]:before {
|
|
28
|
-
background-color: #f49676;
|
|
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 && 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
|
-
<CodeWrapper
|
|
168
|
-
name={name}
|
|
169
|
-
stepName={(step as Step | null)?.name}
|
|
170
|
-
hasName={hasName}
|
|
171
|
-
>
|
|
172
|
-
<Highlighter
|
|
173
|
-
language={language}
|
|
174
|
-
wrapLines
|
|
175
|
-
showLineNumbers
|
|
176
|
-
style={gruvboxDark}
|
|
177
|
-
lineNumberStyle={(lineNumber: number) => {
|
|
178
|
-
const { highlight = [] } = (step as Step) || {};
|
|
179
|
-
const isHighlighted = highlight.includes(lineNumber);
|
|
180
|
-
|
|
181
|
-
return {
|
|
182
|
-
fontWeight: isHighlighted ? "bold" : "normal",
|
|
183
|
-
};
|
|
184
|
-
}}
|
|
185
|
-
lineProps={(lineNumber: number) => {
|
|
186
|
-
const { hiddenLines = [], highlight = [] } =
|
|
187
|
-
(step as Step) || {};
|
|
188
|
-
const isVisible =
|
|
189
|
-
hasSteps && isActive
|
|
190
|
-
? !hiddenLines.includes(lineNumber)
|
|
191
|
-
: isActive || !hasSteps;
|
|
192
|
-
const isHighlighted = highlight.includes(lineNumber);
|
|
193
|
-
const getOpacity = () => {
|
|
194
|
-
if (!isVisible) return 0;
|
|
195
|
-
if (isHighlighted || !highlight.length) return 1;
|
|
196
|
-
return 0.8;
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
return {
|
|
200
|
-
...(isHighlighted && {
|
|
201
|
-
"data-highlight-line": isHighlighted,
|
|
202
|
-
"data-step-active": isActive,
|
|
203
|
-
}),
|
|
204
|
-
style: {
|
|
205
|
-
opacity: getOpacity(),
|
|
206
|
-
transition: "all 0.3s ease",
|
|
207
|
-
display: "block",
|
|
208
|
-
width: "100%",
|
|
209
|
-
backgroundColor: isHighlighted ? "#f4967622" : "",
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
}}
|
|
213
|
-
>
|
|
214
|
-
{codeNormalized}
|
|
215
|
-
</Highlighter>
|
|
216
|
-
</CodeWrapper>
|
|
217
|
-
)}
|
|
218
|
-
</Stepper>
|
|
219
|
-
</CodeContainer>
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
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
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
import styled from "styled-components";
|
|
4
|
-
|
|
5
|
-
const DocWrapper = styled.div`
|
|
6
|
-
position: absolute;
|
|
7
|
-
bottom: 0;
|
|
8
|
-
right: 0;
|
|
9
|
-
z-index: 10000;
|
|
10
|
-
|
|
11
|
-
.docContent {
|
|
12
|
-
display: none;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
&:hover .docContent {
|
|
16
|
-
display: flex;
|
|
17
|
-
}
|
|
18
|
-
`;
|
|
19
|
-
|
|
20
|
-
const DocContainer = styled.div`
|
|
21
|
-
margin: 2rem 1rem;
|
|
22
|
-
background-color: #333;
|
|
23
|
-
border: 1px solid #333;
|
|
24
|
-
padding: 0.5rem 1rem;
|
|
25
|
-
border-radius: 1.5rem;
|
|
26
|
-
`;
|
|
27
|
-
|
|
28
|
-
const DocLink = styled.a`
|
|
29
|
-
text-decoration: none;
|
|
30
|
-
font-weight: normal;
|
|
31
|
-
font-family: Bitter, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
32
|
-
color: #f49676;
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
const DocLinkItem = styled(DocLink)`
|
|
36
|
-
width: fit-content;
|
|
37
|
-
display: inline-block;
|
|
38
|
-
background-color: #333;
|
|
39
|
-
border: 1px solid #333;
|
|
40
|
-
padding: 0.5rem 1rem;
|
|
41
|
-
border-radius: 1.5rem;
|
|
42
|
-
margin: 0.25rem 0;
|
|
43
|
-
`;
|
|
44
|
-
|
|
45
|
-
const DocContent = styled.div`
|
|
46
|
-
display: flex;
|
|
47
|
-
flex-flow: column-reverse nowrap;
|
|
48
|
-
position: absolute;
|
|
49
|
-
right: 1rem;
|
|
50
|
-
bottom: 4.5rem;
|
|
51
|
-
text-align: right;
|
|
52
|
-
border-radius: 0.5rem;
|
|
53
|
-
align-items: flex-end;
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
export function Doc({
|
|
57
|
-
label,
|
|
58
|
-
link,
|
|
59
|
-
children,
|
|
60
|
-
}: {
|
|
61
|
-
label: string;
|
|
62
|
-
link: string;
|
|
63
|
-
children: React.ReactNode;
|
|
64
|
-
}) {
|
|
65
|
-
return (
|
|
66
|
-
<DocWrapper>
|
|
67
|
-
<DocContainer>
|
|
68
|
-
{children && <DocContent>{children}</DocContent>}
|
|
69
|
-
<div>
|
|
70
|
-
<DocLink target="_blank" rel="noopener noreferrer" href={link}>
|
|
71
|
-
{label}
|
|
72
|
-
</DocLink>
|
|
73
|
-
</div>
|
|
74
|
-
</DocContainer>
|
|
75
|
-
</DocWrapper>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function DocItem({ label, link }: { label: string; link: string }) {
|
|
80
|
-
return (
|
|
81
|
-
<DocLinkItem target="_blank" rel="noopener noreferrer" href={link}>
|
|
82
|
-
{label}
|
|
83
|
-
</DocLinkItem>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
export default function FilePane({
|
|
4
|
-
name,
|
|
5
|
-
children,
|
|
6
|
-
priority,
|
|
7
|
-
...divProps
|
|
8
|
-
}: React.ComponentProps<"div"> & { name: string; priority?: number }) {
|
|
9
|
-
return React.isValidElement(children)
|
|
10
|
-
? React.cloneElement(children, {
|
|
11
|
-
// @ts-expect-error cloning
|
|
12
|
-
priority,
|
|
13
|
-
name,
|
|
14
|
-
})
|
|
15
|
-
: children;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
FilePane.mdxType = "FilePane";
|