Skip to content

feat: make the logo link configurable #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"useTabs": false,
"tabWidth": 2,
"semi": true,
"bracketSpacing": true
"bracketSpacing": true,
"plugins": ["prettier-plugin-astro"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"husky": "^9.0.11",
"is-ci": "^3.0.1",
"prettier": "^3.3.1",
"prettier-plugin-astro": "^0.13.0",
"tempfile": "^5.0.0"
},
"lint-staged": {},
Expand Down
33 changes: 5 additions & 28 deletions packages/astro/src/default/components/Header.astro
Original file line number Diff line number Diff line change
@@ -1,44 +1,21 @@
---
import fs from 'node:fs';
import path from 'node:path';
import Logo from './Logo.astro';
import { LoginButton } from './LoginButton';
import { ThemeSwitch } from './ThemeSwitch';
import { useAuth } from './setup';

const LOGO_EXTENSIONS = [
'svg',
'png',
'jpeg',
'jpg',
];

let logo;

for (const logoExt of LOGO_EXTENSIONS) {
const logoFilename = `logo.${logoExt}`;
const exists = fs.existsSync(path.join('public', logoFilename));

if (exists) {
logo = `/${logoFilename}`;
break;
}
interface Props {
logoLink: string;
}

if (!logo) {
console.warn(`No logo found in public/. Supported filenames are: logo.(${LOGO_EXTENSIONS.join('|')})`);
}
const { logoLink } = Astro.props;
---

<nav
class="bg-tk-elements-topBar-backgroundColor border-b border-tk-elements-app-borderColor flex max-w-full items-center p-3 px-4 min-h-[56px]"
>
<div class="flex flex-1">
<a
href="/"
class="flex items-center text-tk-elements-topBar-logo-color hover:text-tk-elements-topBar-logo-colorHover"
>
{logo && <img class="h-5 w-auto" src={logo} />}
</a>
<Logo logoLink={logoLink} />
</div>
<div>
<ThemeSwitch client:load transition:persist />
Expand Down
48 changes: 48 additions & 0 deletions packages/astro/src/default/components/Logo.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
import fs from 'node:fs';
import path from 'node:path';

const LOGO_EXTENSIONS = ['svg', 'png', 'jpeg', 'jpg'];

interface Props {
logoLink: string;
}

function readLogoFile(logoPrefix: string) {
let logo;

for (const logoExt of LOGO_EXTENSIONS) {
const logoFilename = `${logoPrefix}.${logoExt}`;
const exists = fs.existsSync(path.join('public', logoFilename));

if (exists) {
logo = `/${logoFilename}`;
break;
}
}

return logo;
}

const { logoLink } = Astro.props;

const logo = readLogoFile('logo');
const logoDark = readLogoFile('logo-dark') ?? logo;

if (!logo) {
console.warn(
[
`No logo found in public/. Supported filenames are: logo.(${LOGO_EXTENSIONS.join('|')}). `,
`You can overwrite the logo for dark mode by providing a logo-dark.(${LOGO_EXTENSIONS.join('|')}).`,
].join(''),
);
}
---

<a
href={logoLink}
class="flex items-center text-tk-elements-topBar-logo-color hover:text-tk-elements-topBar-logo-colorHover"
>
{logo && <img class="h-5 w-auto dark:hidden" src={logo} />}
{logo && <img class="h-5 w-auto hidden dark:inline-block" src={logoDark} />}
</a>
9 changes: 5 additions & 4 deletions packages/astro/src/default/components/ResizablePanel.astro
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ if (!hasSidePanel) {
<slot name="a" />
</div>
{
hasSidePanel &&
(
hasSidePanel && (
<>
<div class="panel">
<slot name="b" />
</div>
<div class="divider"></div>
)
<div class="divider" />
</>
)
}
</div>
</resizable-panel>
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/default/pages/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ export async function getStaticPaths() {

type Props = InferGetStaticPropsType<typeof getStaticPaths>;

const { lesson, navList, title } = Astro.props as Props;
const { lesson, logoLink, navList, title } = Astro.props as Props;

const showWorkspacePanel = hasWorkspace(lesson);
---

<Layout title={title}>
<div id="previews-container"></div>
<main class="max-w-full flex flex-col h-screen overflow-hidden" data-swap-root>
<Header />
<Header logoLink={logoLink ?? '/'} />
<ResizablePanel
classList="h-full overflow-hidden"
id={RESIZABLE_PANELS.Main}
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/default/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getTutorial } from '../utils/content';

const tutorial = await getTutorial();

const parts = Object.values(tutorial);
const parts = Object.values(tutorial.parts);
const part = parts[0];
const chapter = part.chapters[1];
const lesson = chapter.lessons[1];
Expand Down
34 changes: 19 additions & 15 deletions packages/astro/src/default/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ const CONTENT_DIR = path.join(process.cwd(), 'src/content/tutorial');
export async function getTutorial(): Promise<Tutorial> {
const collection = sortCollection(await getCollection('tutorial'));

const _tutorial: Tutorial = {};
const _tutorial: Tutorial = {
parts: {},
};

let tutorialMetaData: TutorialSchema | undefined;

Expand All @@ -34,30 +36,32 @@ export async function getTutorial(): Promise<Tutorial> {

// default template if not specified
tutorialMetaData.template ??= 'default';

_tutorial.logoLink = data.logoLink;
} else if (type === 'part') {
_tutorial[partId] = {
_tutorial.parts[partId] = {
id: partId,
data,
slug: getSlug(entry),
chapters: {},
};
} else if (type === 'chapter') {
if (!_tutorial[partId]) {
if (!_tutorial.parts[partId]) {
throw new Error(`Could not find part '${partId}'`);
}

_tutorial[partId].chapters[chapterId] = {
_tutorial.parts[partId].chapters[chapterId] = {
id: chapterId,
data,
slug: getSlug(entry),
lessons: {},
};
} else if (type === 'lesson') {
if (!_tutorial[partId]) {
if (!_tutorial.parts[partId]) {
throw new Error(`Could not find part '${partId}'`);
}

if (!_tutorial[partId].chapters[chapterId]) {
if (!_tutorial.parts[partId].chapters[chapterId]) {
throw new Error(`Could not find chapter '${partId}'`);
}

Expand All @@ -75,11 +79,11 @@ export async function getTutorial(): Promise<Tutorial> {
id: lessonId,
part: {
id: partId,
title: _tutorial[partId].data.title,
title: _tutorial.parts[partId].data.title,
},
chapter: {
id: chapterId,
title: _tutorial[partId].chapters[chapterId].data.title,
title: _tutorial.parts[partId].chapters[chapterId].data.title,
},
Markdown: Content,
slug: getSlug(entry),
Expand All @@ -89,7 +93,7 @@ export async function getTutorial(): Promise<Tutorial> {

lessons.push(lesson);

_tutorial[partId].chapters[chapterId].lessons[lessonId] = lesson;
_tutorial.parts[partId].chapters[chapterId].lessons[lessonId] = lesson;
}
}

Expand All @@ -111,8 +115,8 @@ export async function getTutorial(): Promise<Tutorial> {
const prevLesson = i > 0 ? lessons.at(i - 1) : undefined;
const nextLesson = lessons.at(i + 1);

const partMetadata = _tutorial[lesson.part.id].data;
const chapterMetadata = _tutorial[lesson.part.id].chapters[lesson.chapter.id].data;
const partMetadata = _tutorial.parts[lesson.part.id].data;
const chapterMetadata = _tutorial.parts[lesson.part.id].chapters[lesson.chapter.id].data;

lesson.data = {
...pick(
Expand All @@ -123,8 +127,8 @@ export async function getTutorial(): Promise<Tutorial> {
};

if (prevLesson) {
const partSlug = _tutorial[prevLesson.part.id].slug;
const chapterSlug = _tutorial[prevLesson.part.id].chapters[prevLesson.chapter.id].slug;
const partSlug = _tutorial.parts[prevLesson.part.id].slug;
const chapterSlug = _tutorial.parts[prevLesson.part.id].chapters[prevLesson.chapter.id].slug;

lesson.prev = {
title: prevLesson.data.title,
Expand All @@ -133,8 +137,8 @@ export async function getTutorial(): Promise<Tutorial> {
}

if (nextLesson) {
const partSlug = _tutorial[nextLesson.part.id].slug;
const chapterSlug = _tutorial[nextLesson.part.id].chapters[nextLesson.chapter.id].slug;
const partSlug = _tutorial.parts[nextLesson.part.id].slug;
const chapterSlug = _tutorial.parts[nextLesson.part.id].chapters[nextLesson.chapter.id].slug;

lesson.next = {
title: nextLesson.data.title,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/default/utils/nav.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Tutorial, NavList } from '@tutorialkit/types';

export function generateNavigationList(tutorial: Tutorial): NavList {
return objectToSortedArray(tutorial).map((part) => {
return objectToSortedArray(tutorial.parts).map((part) => {
return {
id: part.id,
title: part.data.title,
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/default/utils/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export async function generateStaticRoutes() {

const routes = [];

const parts = Object.values(tutorial);
const parts = Object.values(tutorial.parts);

for (const part of parts) {
const chapters = Object.values(part.chapters);
Expand All @@ -23,6 +23,7 @@ export async function generateStaticRoutes() {
slug: `/${part.slug}/${chapter.slug}/${lesson.slug}`,
},
props: {
logoLink: tutorial.logoLink,
navList: generateNavigationList(tutorial),
title: `${part.data.title} / ${chapter.data.title} / ${lesson.data.title}`,
lesson: lesson as Lesson<AstroComponentFactory>,
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/tests/__snapshots__/create-tutorial.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exports[`create a project 1`] = `
"package.json",
"public",
"public/favicon.svg",
"public/logo-dark.svg",
"public/logo.svg",
"src",
"src/content",
Expand Down Expand Up @@ -110,6 +111,7 @@ exports[`create and build a project 1`] = `
"2-advanced/1-unicorn/1-welcome/index.html",
"favicon.svg",
"index.html",
"logo-dark.svg",
"logo.svg",
"template-default.json",
"template-vite-app.json",
Expand Down
4 changes: 4 additions & 0 deletions packages/template/public/logo-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading