Skip to content

Commit 780d7d0

Browse files
committed
feat: add template.visibleFiles option
1 parent 85e6fc1 commit 780d7d0

File tree

7 files changed

+51
-3
lines changed

7 files changed

+51
-3
lines changed

packages/astro/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"kleur": "4.1.5",
5151
"mdast-util-directive": "^3.0.0",
5252
"mdast-util-to-markdown": "^2.1.0",
53+
"micromatch": "^4.0.7",
5354
"nanostores": "^0.10.3",
5455
"react": "^18.3.1",
5556
"react-dom": "^18.3.1",
@@ -62,6 +63,7 @@
6263
"devDependencies": {
6364
"@tutorialkit/types": "workspace:*",
6465
"@types/mdast": "^4.0.4",
66+
"@types/micromatch": "^4.0.9",
6567
"esbuild": "^0.20.2",
6668
"esbuild-node-externals": "^1.13.1",
6769
"execa": "^9.2.0",

packages/astro/src/default/utils/content.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
import { folderPathToFilesRef, interpolateString } from '@tutorialkit/types';
1111
import { getCollection } from 'astro:content';
1212
import glob from 'fast-glob';
13+
import mm from 'micromatch';
1314
import path from 'node:path';
1415
import { IGNORED_FILES } from './constants';
1516
import { DEFAULT_LOCALIZATION } from './content/default-localization';
@@ -18,6 +19,7 @@ import { logger } from './logger';
1819
import { joinPaths } from './url';
1920

2021
const CONTENT_DIR = path.join(process.cwd(), 'src/content/tutorial');
22+
const TEMPLATES_DIR = path.join(process.cwd(), 'src/templates');
2123

2224
export async function getTutorial(): Promise<Tutorial> {
2325
const collection = sortCollection(await getCollection('tutorial'));
@@ -262,6 +264,18 @@ export async function getTutorial(): Promise<Tutorial> {
262264
),
263265
};
264266

267+
if (lesson.data.template) {
268+
const template = typeof lesson.data.template === 'string' ? { name: lesson.data.template } : lesson.data.template;
269+
270+
const allTemplateFiles = template.visibleFiles?.length
271+
? (await getFilesRefList(template.name, TEMPLATES_DIR))[1]
272+
: [];
273+
274+
const templateFiles = mm(allTemplateFiles, template.visibleFiles || []);
275+
276+
lesson.files[1] = [...lesson.files[1], ...templateFiles].filter(filterUnique).sort();
277+
}
278+
265279
if (prevLesson) {
266280
const partSlug = _tutorial.parts[prevLesson.part.id].slug;
267281
const chapterSlug = _tutorial.parts[prevLesson.part.id].chapters[prevLesson.chapter.id].slug;
@@ -330,8 +344,8 @@ function getSlug(entry: CollectionEntryTutorial) {
330344
return slug;
331345
}
332346

333-
async function getFilesRefList(pathToFolder: string): Promise<FilesRefList> {
334-
const root = path.join(CONTENT_DIR, pathToFolder);
347+
async function getFilesRefList(pathToFolder: string, base = CONTENT_DIR): Promise<FilesRefList> {
348+
const root = path.join(base, pathToFolder);
335349

336350
const filePaths = (
337351
await glob(`${glob.convertPathToPattern(root)}/**/*`, {
@@ -348,6 +362,10 @@ async function getFilesRefList(pathToFolder: string): Promise<FilesRefList> {
348362
return [filesRef, filePaths];
349363
}
350364

365+
function filterUnique<T>(item: T, index: number, array: T[]) {
366+
return array.indexOf(item) === index;
367+
}
368+
351369
interface CollectionEntryTutorial {
352370
id: string;
353371
slug: string;

packages/runtime/src/store/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,14 @@ export class TutorialStore {
169169
this._lessonFiles = files;
170170
this._lessonSolution = solution;
171171

172-
this._editorStore.setDocuments(files);
172+
this._editorStore.setDocuments(
173+
Object.fromEntries(
174+
Object.entries({
175+
...template,
176+
...files,
177+
}).filter(([filename]) => lesson.files[1].includes(filename)),
178+
),
179+
);
173180

174181
if (lesson.data.focus === undefined) {
175182
this._editorStore.setSelectedFile(undefined);

packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ terminal:
1313
panels: ['terminal', 'output']
1414
template:
1515
name: default
16+
visibleFiles: ['/src/template-only-file.js']
1617
---
1718

1819
# Kitchen Sink [Heading 1]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'This file is only present in template';

packages/types/src/schemas/common.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ export const webcontainerSchema = commandsSchema.extend({
145145
z.strictObject({
146146
// name of the template
147147
name: z.string(),
148+
149+
// list of globs of files that should be visible
150+
visibleFiles: z.array(z.string()).optional(),
148151
}),
149152
]),
150153
terminal: terminalSchema.optional(),

pnpm-lock.yaml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)