Skip to content

Commit 1279917

Browse files
authored
feat: allow custom components that modify the tutorial state (#64)
1 parent 7cd8170 commit 1279917

File tree

11 files changed

+114
-2
lines changed

11 files changed

+114
-2
lines changed

packages/astro/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"types": "./dist/index.d.ts",
1010
"exports": {
1111
".": "./dist/index.js",
12+
"./types": "./types.d.ts",
1213
"./default/pages/index.astro": "./dist/default/pages/index.astro",
1314
"./default/pages/[...slug].astro": "./dist/default/pages/[...slug].astro"
1415
},

packages/astro/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { fileURLToPath } from 'node:url';
33
import { extraIntegrations } from './integrations.js';
44
import { updateMarkdownConfig } from './remark/index.js';
55
import { WebContainerFiles } from './webcontainer-files.js';
6-
import { userlandCSS, watchUserlandCSS } from './css.js';
6+
import { userlandCSS, watchUserlandCSS } from './vite-plugins/css.js';
7+
import { tutorialkitStore } from './vite-plugins/store.js';
8+
import { tutorialkitCore } from './vite-plugins/core.js';
79

810
export { theme } from './theme.js';
911

@@ -84,6 +86,8 @@ export default function createPlugin({ defaultRoutes = true, isolation, enterpri
8486
},
8587
plugins: [
8688
userlandCSS,
89+
tutorialkitStore,
90+
tutorialkitCore,
8791
process.env.TUTORIALKIT_DEV ? (await import('vite-plugin-inspect')).default() : null,
8892
],
8993
},

packages/astro/src/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ export function withResolvers<T>(): PromiseWithResolvers<T> {
1313
promise,
1414
};
1515
}
16+
17+
export function normalizeImportPath(importPath: string): string {
18+
// this is a fix for windows where import path should still use forward slashes
19+
return importPath.replaceAll('\\', '/');
20+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* A plugin that let users write components that can access the internals
3+
* of TutorialKit
4+
*
5+
* The virtual module can be imported as:
6+
*
7+
* ```ts
8+
* import { webcontainer } from 'tutorialkit:core';
9+
*
10+
* export const MyComponent = () => {
11+
* useEffect(() => {
12+
* (async () => {
13+
* const webcontainerInstance = await webcontainer;
14+
* await webcontainerInstance.fs.writeFile('foo.js', 'console.log("hello world")');
15+
* })();
16+
* }, []);
17+
*
18+
* return null;
19+
* };
20+
* ```
21+
*/
22+
import path from 'node:path';
23+
import { fileURLToPath } from 'node:url';
24+
import type { VitePlugin } from '../types.js';
25+
import { normalizeImportPath } from '../utils.js';
26+
27+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
28+
const virtualModuleId = 'tutorialkit:core';
29+
const resolvedVirtualModuleId = `${virtualModuleId}`;
30+
31+
export const tutorialkitCore: VitePlugin = {
32+
name: 'tutorialkit-core-virtual-mod-plugin',
33+
resolveId(id) {
34+
if (id === virtualModuleId) {
35+
return resolvedVirtualModuleId;
36+
}
37+
},
38+
async load(id) {
39+
if (id === resolvedVirtualModuleId) {
40+
const pathToInit = normalizeImportPath(path.join(__dirname, 'default/components/webcontainer.ts'));
41+
42+
return `
43+
export { webcontainer } from '${pathToInit}';
44+
`;
45+
}
46+
},
47+
};

packages/astro/src/css.ts renamed to packages/astro/src/vite-plugins/css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import { watch } from 'chokidar';
1010
import fs from 'fs/promises';
1111
import path from 'path';
12-
import type { ViteDevServer, VitePlugin } from './types.js';
12+
import type { ViteDevServer, VitePlugin } from '../types.js';
1313
import type { AstroIntegrationLogger } from 'astro';
1414

1515
const CUSTOM_PATHS = ['theme.css', 'theme/index.css'];
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* A plugin that let users write components that can interact with the tutorial
3+
* state, indirectly acting on the editor and WebContainer.
4+
*
5+
* The virtual module can be imported as:
6+
*
7+
* ```ts
8+
* import tutorialStore from 'tutorialkit:store';
9+
*
10+
* export const MyComponent = () => (
11+
* <button onClick={() => tutorialStore.reset()}>Reset</button>
12+
* );
13+
* ```
14+
*/
15+
import path from 'node:path';
16+
import { fileURLToPath } from 'node:url';
17+
import type { VitePlugin } from '../types.js';
18+
import { normalizeImportPath } from '../utils.js';
19+
20+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
21+
const virtualModuleId = 'tutorialkit:store';
22+
const resolvedVirtualModuleId = `${virtualModuleId}`;
23+
24+
export const tutorialkitStore: VitePlugin = {
25+
name: 'tutorialkit-store-virtual-mod-plugin',
26+
resolveId(id) {
27+
if (id === virtualModuleId) {
28+
return resolvedVirtualModuleId;
29+
}
30+
},
31+
async load(id) {
32+
if (id === resolvedVirtualModuleId) {
33+
const pathToInit = normalizeImportPath(path.join(__dirname, 'default/components/webcontainer.ts'));
34+
35+
return `
36+
import { tutorialStore } from '${pathToInit}';
37+
export default tutorialStore;
38+
`;
39+
}
40+
},
41+
};

packages/astro/types.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
declare module 'tutorialkit:store' {
2+
const tutorialStore: import('@tutorialkit/runtime').TutorialStore;
3+
4+
export default tutorialStore;
5+
}
6+
7+
declare module 'tutorialkit:core' {
8+
export const webcontainer: import('@webcontainer/api').WebContainer;
9+
}

packages/template/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"react-dom": "^18.2.0"
1717
},
1818
"devDependencies": {
19+
"@types/react": "^18.2.75",
1920
"@astrojs/check": "^0.6.0",
2021
"@astrojs/react": "^3.3.4",
2122
"@iconify-json/ph": "^1.1.12",

packages/template/src/env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/// <reference path="../.astro/types.d.ts" />
2+
/// <reference types="@tutorialkit/astro/types" />
23
/// <reference types="astro/client" />

0 commit comments

Comments
 (0)