Skip to content

Commit dc4eef9

Browse files
committed
feat: add "Edit this page" link
1 parent f85e8eb commit dc4eef9

File tree

10 files changed

+101
-5
lines changed

10 files changed

+101
-5
lines changed

docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,30 @@ Navigating to a lesson that specifies `autoReload` will always reload the previe
170170
Specified which folder from the `src/templates/` directory should be used as the basis for the code. See the "[Code templates](/guides/creating-content/#code-templates)" guide for a detailed explainer.
171171
<PropertyTable inherited type="string" />
172172

173+
#### `editPageLink`
174+
Display a link in lesson for editing the page content.
175+
The value is a URL pattern where `:path` is replaced with the lesson's location relative to the `src/content/tutorial`.
176+
177+
<PropertyTable inherited type="string|false" />
178+
179+
```yaml
180+
editPageLink: https://github.com/stackblitz/tutorialkit/blob/main/packages/template/src/content/tutorial/:path
181+
```
182+
183+
The inherited value can be disabled in specific parts using `false`.
184+
185+
```yaml
186+
editPageLink: false
187+
```
188+
189+
:::tip
190+
Note that Github will try to automatically render the `.md` files when linked to.
191+
You can instruct Github to show the source code instead by adding `plain=1` query parameter.
192+
193+
```diff
194+
-editPageLink: https://github.com/stackblitz/tutorialkit/blob/main/packages/template/src/content/tutorial/:path
195+
+editPageLink: https://github.com/stackblitz/tutorialkit/blob/main/packages/template/src/content/tutorial/:path?plain=1
196+
```
197+
198+
:::
199+
Loading

docs/tutorialkit.dev/src/content/docs/reference/theming.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,20 @@ The navigation cards are the cards at the bottom of a lesson to navigate to the
316316
| `--tk-elements-navCard-iconColor` | The icon color of the navigation card. |
317317
| `--tk-elements-navCard-iconColorHover` | The icon color of the navigation card when hovering. |
318318

319+
### Edit Page Link
320+
321+
The edit page link is shown above the navigation cards when configured by [`editPageLink` option](../configuration/#editpagelink).
322+
323+
![Edit Page Link](./images/theming-editpagelink.png)
324+
325+
| Token | Description |
326+
| ------------------------------------------- | --------------------------------------------------- |
327+
| `--tk-elements-editPageLink-textColor` | The text color of the edit page link |
328+
| `--tk-elements-editPageLink-textColorHover` | The text color of the edit page link when hovering. |
329+
| `--tk-elements-editPageLink-iconColor` | The icon color of the edit page link |
330+
| `--tk-elements-editPageLink-iconColorHover` | The icon color of the edit page link when hovering |
331+
| `--tk-elements-editPageLink-borderColor` | The border color of the edit page link |
332+
319333
### Breadcrumbs
320334

321335
The breadcrumbs are the navigation elements that show the path of the current lesson. The breadcrumbs are divided into multiple parts.

packages/astro/src/default/components/TutorialContent.astro

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,28 @@ interface Props {
88
}
99
1010
const { lesson } = Astro.props;
11-
const { Markdown, prev, next } = lesson;
11+
const { Markdown, editPageLink, prev, next } = lesson;
1212
---
1313

1414
<div class="h-full overflow-auto scrollbar-transparent p-6 sm:p-8">
1515
<div class="markdown-content text-tk-elements-content-textColor">
1616
<Markdown />
1717
</div>
18+
19+
{
20+
editPageLink && (
21+
<div class="pb-4 mt-8 border-b border-tk-elements-editPageLink-borderColor">
22+
<a
23+
href={editPageLink}
24+
class="inline-flex flex-items-center text-tk-elements-editPageLink-textColor hover:text-tk-elements-editPageLink-textColorHover hover:underline"
25+
>
26+
<span class="icon i-ph-note-pencil pointer-events-none h-5 w-5 mr-2 text-tk-elements-editPageLink-iconColor group-hover:text-tk-elements-editPageLink-iconColorHover" />
27+
<span>Edit this page</span>
28+
</a>
29+
</div>
30+
)
31+
}
32+
1833
<div class="grid grid-cols-[1fr_1fr] gap-4 mt-8">
1934
<div class="flex">
2035
{prev && <NavCard lesson={prev} type="prev" />}

packages/astro/src/default/styles/variables.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@
245245
--tk-elements-navCard-iconColor: var(--tk-elements-app-textColor);
246246
--tk-elements-navCard-iconColorHover: var(--tk-text-accent);
247247

248+
/* Edit Page Link */
249+
--tk-elements-editPageLink-textColor: var(--tk-elements-app-textColor);
250+
--tk-elements-editPageLink-textColorHover: var(--tk-text-active);
251+
--tk-elements-editPageLink-iconColor: var(--tk-elements-app-textColor);
252+
--tk-elements-editPageLink-iconColorHover: var(--tk-text-accent);
253+
--tk-elements-editPageLink-borderColor: var(--tk-border-secondary);
254+
248255
/* Breadcrumb > Nav Button */
249256
--tk-elements-breadcrumbs-navButton-iconColor: var(--tk-text-secondary);
250257
--tk-elements-breadcrumbs-navButton-iconColorHover: var(--tk-text-active);

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export async function getTutorial(): Promise<Tutorial> {
9090
const lesson: Lesson = {
9191
data,
9292
id: lessonId,
93+
filepath: id,
9394
order: -1,
9495
part: {
9596
id: partId,
@@ -251,7 +252,18 @@ export async function getTutorial(): Promise<Tutorial> {
251252
...lesson.data,
252253
...squash(
253254
[lesson.data, chapterMetadata, partMetadata, tutorialMetaData],
254-
['mainCommand', 'prepareCommands', 'previews', 'autoReload', 'template', 'terminal', 'editor', 'focus', 'i18n'],
255+
[
256+
'mainCommand',
257+
'prepareCommands',
258+
'previews',
259+
'autoReload',
260+
'template',
261+
'terminal',
262+
'editor',
263+
'focus',
264+
'i18n',
265+
'editPageLink',
266+
],
255267
),
256268
};
257269

@@ -274,9 +286,11 @@ export async function getTutorial(): Promise<Tutorial> {
274286
href: joinPaths(baseURL, `/${partSlug}/${chapterSlug}/${nextLesson.slug}`),
275287
};
276288
}
277-
}
278289

279-
// console.log(inspect(_tutorial, undefined, Infinity, true));
290+
if (lesson.data.editPageLink && typeof lesson.data.editPageLink === 'string') {
291+
lesson.editPageLink = lesson.data.editPageLink.replace(':path', lesson.filepath);
292+
}
293+
}
280294

281295
return _tutorial;
282296
}

packages/theme/src/theme.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ export const theme = {
252252
iconColor: 'var(--tk-elements-navCard-iconColor)',
253253
iconColorHover: 'var(--tk-elements-navCard-iconColorHover)',
254254
},
255+
editPageLink: {
256+
textColor: 'var(--tk-elements-editPageLink-textColor)',
257+
textColorHover: 'var(--tk-elements-editPageLink-textColorHover)',
258+
iconColor: 'var(--tk-elements-editPageLink-iconColor)',
259+
iconColorHover: 'var(--tk-elements-editPageLink-iconColorHover)',
260+
borderColor: 'var(--tk-elements-editPageLink-borderColor)',
261+
},
255262
breadcrumbs: {
256263
navButton: {
257264
iconColor: 'var(--tk-elements-breadcrumbs-navButton-iconColor)',

packages/types/src/entities/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export interface Lesson<T = unknown> {
4040
part: { id: string; title: string };
4141
chapter: { id: string; title: string };
4242
slug: string;
43+
filepath: string;
44+
editPageLink?: string;
4345
files: FilesRefList;
4446
solution: FilesRefList;
4547
next?: LessonLink;

packages/types/src/schemas/common.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,18 @@ export const webcontainerSchema = commandsSchema.extend({
153153
i18n: i18nSchema.optional(),
154154
});
155155

156+
export const editPageLinkSchema = z.union([
157+
// pattern for creating the URL
158+
z.string(),
159+
160+
// `false` for disabling the edit link
161+
z.boolean(),
162+
]);
163+
156164
export const baseSchema = webcontainerSchema.extend({
157165
title: z.string(),
158166
slug: z.string().optional(),
167+
editPageLink: editPageLinkSchema.optional(),
159168
});
160169

161170
export type BaseSchema = z.infer<typeof baseSchema>;

packages/types/src/schemas/tutorial.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { z } from 'zod';
2-
import { webcontainerSchema } from './common.js';
2+
import { webcontainerSchema, editPageLinkSchema } from './common.js';
33

44
export const tutorialSchema = webcontainerSchema.extend({
55
type: z.literal('tutorial'),
66
logoLink: z.string().optional(),
7+
editPageLink: editPageLinkSchema.optional(),
78
parts: z.array(z.string()).optional(),
89
});
910

0 commit comments

Comments
 (0)