Skip to content
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
7 changes: 5 additions & 2 deletions .stackblitzrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"installDependencies": true,
"startCommand": "yarn run start",
"startCommand": "yarn run docusaurus start",
"env": {
"NODE_ENV": "development",
"OFFLINE_API": "indexedDB",
"STACKBLITZ": "true"
"STACKBLITZ": "true",
"YARN_IGNORE_ENGINES": "true",
"PACKAGE_SRC": "packages",
"PACKAGE_DEST": "docs/Packages"
}
}
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"recommendations": [
"pomdtr.excalidraw-editor",
"zhuangtongfa.Material-theme",
"betterplace.betterplace-vscode-vitest-runner",
"mhutchie.git-graph",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Website
# Teaching Dev

This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/GBSL-Informatik/teaching-dev)

> [!NOTE]
> Compatible with @docusaurus/faster (rspack and swc).
Diese Seite basiert auf [Docusaurus](https://docusaurus.io/), einem modernen statischen Website-Generator. Sie fügt viele hilfreiche Funktionalität für den Einsatz im Unterricht hinzu.

## TDEV-Website

Expand Down
2 changes: 2 additions & 0 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { withSiteConfig } from './src/siteConfig/withSiteConfig';
import {
sassPluginConfig,
dynamicRouterPluginConfig,
stackblitzRspackTargetPluginConfig,
rsDoctorPluginConfig,
sentryPluginConfig,
socketIoNoDepWarningsPluginConfig,
Expand Down Expand Up @@ -381,6 +382,7 @@ const docusaurusConfig = withSiteConfig().then(async (siteConfig) => {
plugins: [
sassPluginConfig,
dynamicRouterPluginConfig(siteConfig),
stackblitzRspackTargetPluginConfig(),
rsDoctorPluginConfig,
[
aliasConfigurationPlugin,
Expand Down
62 changes: 42 additions & 20 deletions packages/tdev/page-index/remark-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,55 @@ import type { Plugin, Transformer } from 'unified';
import type { Code, Root } from 'mdast';
import type { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx';
import path from 'path';
import db from '../utils/db';
import { exportDB } from '../utils/exportDb';
import { debounce } from 'es-toolkit/function';
import { tdevRoot } from '../utils/options';
import { TypeModelMapping } from '@tdev-api/document';
import type { Statement } from 'better-sqlite3';

const TdevRoot = `${tdevRoot === '' ? '' : '/'}${tdevRoot}`;
const TdevRootRegex = new RegExp(`^${TdevRoot}`);
const projectRoot = process.cwd();
const isDev = process.env.NODE_ENV !== 'production';

const insertDocRoot = db.prepare(
`INSERT INTO document_roots (
id,
type,
page_id,
path,
position
) VALUES (
@id,
@type,
@page_id,
@path,
@position
) ON CONFLICT(id, path) DO NOTHING`
);
const _cachedImport: Partial<{
insertDocRoot: Statement;
cleanupPage: Statement;
}> = {};

const cleanupPage = db.prepare(
`DELETE FROM document_roots
WHERE path = ? AND page_id = ?;`
);
const requireDb = async (): Promise<typeof _cachedImport> => {
if (process.env.STACKBLITZ === 'true') {
return Promise.resolve({});
}
if (_cachedImport.cleanupPage && _cachedImport.insertDocRoot) {
return Promise.resolve(_cachedImport);
}
const db = (await import('../utils/db')).default;

const insertDocRoot = db.prepare(
`INSERT INTO document_roots (
id,
type,
page_id,
path,
position
) VALUES (
@id,
@type,
@page_id,
@path,
@position
) ON CONFLICT(id, path) DO NOTHING`
);

const cleanupPage = db.prepare(
`DELETE FROM document_roots
WHERE path = ? AND page_id = ?;`
);
_cachedImport.insertDocRoot = insertDocRoot;
_cachedImport.cleanupPage = cleanupPage;
return _cachedImport;
};

interface JsxConfig {
/**
Expand Down Expand Up @@ -67,6 +85,10 @@ const remarkPlugin: Plugin<PluginOptions[], Root> = function plugin(
const { components } = options;
const mdxJsxComponents = new Map<string, JsxConfig>(components.map((c) => [c.name, c]));
return async (root, file) => {
const { insertDocRoot, cleanupPage } = await requireDb();
if (!insertDocRoot || !cleanupPage) {
return;
}
const { page_id } = (file.data?.frontMatter || {}) as { page_id?: string };
if (components.length < 1 || !page_id) {
return;
Expand Down
22 changes: 19 additions & 3 deletions packages/tdev/page-index/utils/exportDb.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
import db from './db';
import { promises as fs } from 'fs';
import { pageIndexPath } from './options';
import { PageIndex } from '..';
import type { Statement } from 'better-sqlite3';

const getDocumentRoots = db.prepare('SELECT * FROM document_roots ORDER BY path ASC, position ASC');
const _cachedImport = {
getDocumentRoots: null as Statement | null
};
const requireDb = async () => {
if (process.env.STACKBLITZ === 'true') {
// Stackblitz does not support better-sqlite3, so we skip the database export
return Promise.resolve();
}
const db = (await import('./db')).default;
const getDocumentRoots = db.prepare('SELECT * FROM document_roots ORDER BY path ASC, position ASC');
_cachedImport.getDocumentRoots = getDocumentRoots;
};

export const getContent = () => {
const getContent = () => {
const { getDocumentRoots } = _cachedImport;
if (!getDocumentRoots) {
return { documentRoots: [] as PageIndex[] };
}
const documentRoots = getDocumentRoots.all() as PageIndex[];
return { documentRoots };
};

export const exportDB = async () => {
await requireDb();
await fs.writeFile(pageIndexPath, JSON.stringify(getContent(), null, 2));
};
17 changes: 17 additions & 0 deletions src/plugins/plugin-stackblitz-rspack-target/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { PluginModule } from '@docusaurus/types';

const stackblitzRspackTarget: PluginModule = (context, options) => {
if (process.env.STACKBLITZ === 'true') {
return {
name: 'webpack-target-fix-plugin',
configureWebpack() {
return {
target: 'web' // bypass rspack's browserslist-based target inference
};
}
};
}
return null;
};

export default stackblitzRspackTarget;
3 changes: 3 additions & 0 deletions src/siteConfig/pluginConfigs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dynamicRouterPlugin, { Config as DynamicRouteConfig } from '../plugins/plugin-dynamic-routes';
import stackblitzRspackTarget from '../plugins/plugin-stackblitz-rspack-target';
import aliasConfigurationPlugin from '../plugins/plugin-alias-configuration';
import type { PluginConfig } from '@docusaurus/types';
import { sentryWebpackPlugin } from '@sentry/webpack-plugin';
Expand All @@ -21,6 +22,8 @@ export const dynamicRouterPluginConfig: (siteConfig: SiteConfig) => PluginConfig
} satisfies DynamicRouteConfig
];

export const stackblitzRspackTargetPluginConfig: () => PluginConfig = () => stackblitzRspackTarget;

export const rsDoctorPluginConfig: PluginConfig = process.env.RSDOCTOR === 'true' && [
'rsdoctor',
{
Expand Down