diff --git a/docs/1-trial-session/04-javascript/index.mdx b/docs/1-trial-session/04-javascript/index.mdx
index 8ba17a21..d0d104aa 100644
--- a/docs/1-trial-session/04-javascript/index.mdx
+++ b/docs/1-trial-session/04-javascript/index.mdx
@@ -4,16 +4,15 @@ title: JavaScriptことはじめ
import helloWorldByJavascriptVideo from "./hello-world-by-javascript.mp4";
-## JavaScript
+## JavaScript
-{/* prettier-ignore */}
-HTMLがウェブサイトの構造を表す言語だとすれば、**JavaScript**はウェブサイトに振る舞いを与える言語といえます。ブラウザさえあれば環境に関係なく同じように実行可能な、強力なプログラミング言語です。
+[[HTML]]がウェブサイトの構造を表す言語だとすれば、[[**JavaScript**]]はウェブサイトに振る舞いを与える言語といえます。ブラウザさえあれば環境に関係なく同じように実行可能な、強力なプログラミング言語です。

-## JavaScriptでHello World!
+## JavaScriptでHello World!
-プログラミングの世界では、まず画面に`Hello World!`と表示させることが慣例になっています。JavaScriptを用いて画面に`Hello World!`を表示してみましょう。
+プログラミングの世界では、まず画面に`Hello World!`と表示させることが慣例になっています。[[JavaScript]]を用いて画面に`Hello World!`を表示してみましょう。
まずは、`index.html`を次のように書き換えます。
@@ -40,26 +39,25 @@ document.write("Hello World!");
-## JavaScriptが動く仕組み
+## JavaScriptが動く仕組み
-HTMLファイルの中に、以下のような記述があります。
+[[HTML]]ファイルの中に、以下のような記述があります。
```html title="index.html"
```
-まず、この記述によって、`script.js`ファイルがブラウザによって読み込まれます。この`script.js`に記述されているのがJavaScriptです。
+まず、この記述によって、`script.js`ファイルがブラウザによって読み込まれます。この`script.js`に記述されているのが[[JavaScript]]です。
:::info
-この講座の中では、`script`要素を常に **`body`要素の末尾** に記述するようにします。これは、JavaScriptが読み込まれるタイミングで他のすべてのHTML要素がすでに表示されていることを保証するためです。
+この講座の中では、`script`[[要素]]を常に **`body`[[要素]]の末尾** に記述するようにします。これは、[[JavaScript]]が読み込まれるタイミングで他のすべての[[HTML要素]]がすでに表示されていることを保証するためです。
:::
-## JavaScriptの基本文法
+## JavaScriptの基本文法
-{/* prettier-ignore */}
-JavaScriptのプログラムで、セミコロンで区切られた部分を文と呼びます。JavaScriptの実行環境は、プログラム中に含まれる文を上から下に向けて順番に実行していきます。
+[[JavaScript]]のプログラムで、セミコロンで区切られた部分を[[文]]と呼びます。[[JavaScript]]の実行環境は、プログラム中に含まれる[[文]]を上から下に向けて順番に実行していきます。
`document.write`はブラウザの画面に出力するための命令です。
```javascript title="script.js"
diff --git a/docs/4-advanced/05-integration-and-deployment/index.mdx b/docs/4-advanced/05-integration-and-deployment/index.mdx
index 1092d35a..af670346 100644
--- a/docs/4-advanced/05-integration-and-deployment/index.mdx
+++ b/docs/4-advanced/05-integration-and-deployment/index.mdx
@@ -38,7 +38,7 @@ Viteを用いて構築されたフロントエンドと、Node.jsを用いて構
1. `backend`ディレクトリに移動し、`npm init`コマンドを実行して`package.json`ファイルを作成します。`type`と尋ねられた時には`module`を指定します。
1. `npm install -D typescript`コマンドを実行してTypeScriptをインストールし、`npx tsc --init`コマンドを実行してTypeScriptの設定を記述するための`tsconfig.json`ファイルを作成します。
-1. ここでは、事前にTypeScriptをJavaScriptにトランスパイルせずにTypeScriptファイルを実行するために、次のコマンドを実行して[`tsx`パッケージ](https://tsx.is/)をインストールします。`npx tsx 実行するファイルのパス`とすることで、TypeScriptファイルを実行できます。
+1. ここでは、事前にTypeScriptをJavaScriptにトランスパイルせずにTypeScriptファイルを実行するために、次のコマンドを実行して[[[`tsx`パッケージ](https://tsx.is/)]]をインストールします。`npx tsx 実行するファイルのパス`とすることで、TypeScriptファイルを実行できます。
```shell
npm install -D tsx
@@ -113,20 +113,19 @@ Viteを用いて構築されたフロントエンドと、Node.jsを用いて構
#### CORSに関する設定をする
-**CORS**に関する設定を行います。
+[[**CORS**]]に関する設定を行います。
:::tip[CORS(Cross-Origin Resource Sharing)]
-ブラウザはセキュリティ上の理由から、異なるオリジンのリソースへのアクセスを制限することがあります。なお、**オリジン**は、プロトコル、ドメイン、ポートの組み合わせによって定義されます。
+ブラウザはセキュリティ上の理由から、異なる[[オリジン]]のリソースへのアクセスを制限することがあります。なお、[[**オリジン**]]は、プロトコル、ドメイン、ポートの組み合わせによって定義されます。
-例えば、フロントエンドの開発用サーバーのオリジンが`http://localhost:5173`でバックエンドのWebサーバーのオリジンが`http://localhost:3000`である場合には、これらは異なるオリジンになります。そのため、Fetch APIを使用してフロントエンドのアプリケーションからバックエンドのアプリケーションのリソースへアクセスすることはブラウザによって制限されます。
+例えば、フロントエンドの開発用サーバーの[[オリジン]]が`http://localhost:5173`でバックエンドのWebサーバーの[[オリジン]]が`http://localhost:3000`である場合には、これらは異なる[[オリジン]]になります。そのため、Fetch APIを使用してフロントエンドのアプリケーションからバックエンドのアプリケーションのリソースへアクセスすることはブラウザによって制限されます。
-{/* prettier-ignore */}
-**CORS**は、このような場合でも必要に応じてリソースへのアクセスを可能にする仕組みです。クライアントからのリクエストに対して、サーバーがHTTPレスポンスヘッダにリソースへのアクセスを許可するオリジンを示す[`Access-Control-Allow-Origin`ヘッダ](https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin)を含めることで、ブラウザはそこで指定されたオリジンからリソースへアクセスすることを許可します。
+[[**CORS**]]は、このような場合でも必要に応じてリソースへのアクセスを可能にする仕組みです。クライアントからのリクエストに対して、サーバーがHTTPレスポンスヘッダにリソースへのアクセスを許可する[[オリジン]]を示す[`Access-Control-Allow-Origin`ヘッダ](https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin)を含めることで、ブラウザはそこで指定された[[オリジン]]からリソースへアクセスすることを許可します。
Expressを用いる場合には、[`cors`パッケージ](https://www.npmjs.com/package/cors)を使用することで、HTTPレスポンスヘッダに`Access-Control-Allow-Origin`ヘッダなどを適切に設定することができます。
@@ -139,8 +138,8 @@ Expressを用いる場合には、[`cors`パッケージ](https://www.npmjs.com/
$ npm install cors
$ npm install -D @types/cors
```
-1. `.env`ファイルを編集し、環境変数`WEB_ORIGIN`の値にViteの開発用サーバーのオリジンである`http://localhost:5173`を指定します。
-1. `main.ts`ファイルを編集し、CORSに関する設定を行います。14行目の`app.use(cors({ origin: process.env.WEB_ORIGIN }));`により、環境変数`WEB_ORIGIN`に指定したオリジンからアクセスできるようにします。
+1. `.env`ファイルを編集し、[[環境変数]]`WEB_ORIGIN`の値にViteの開発用サーバーの[[オリジン]]である`http://localhost:5173`を指定します。
+1. `main.ts`ファイルを編集し、[[CORS]]に関する設定を行います。14行目の`app.use(cors({ origin: process.env.WEB_ORIGIN }));`により、[[環境変数]]`WEB_ORIGIN`に指定した[[オリジン]]からアクセスできるようにします。
```ts title="backend/main.ts" showLineNumbers
import express from "express";
@@ -177,7 +176,7 @@ Expressを用いる場合には、[`cors`パッケージ](https://www.npmjs.com/
-`package.json`の`scripts`プロパティに開発によく使うコマンドを登録します。次のように記載して、`npm run dev`コマンドを実行することでWebサーバーを起動できるようにしましょう。`tsx`パッケージでは、[Node.jsと同様のオプションが利用](https://tsx.is/node-enhancement#swap-node-for-tsx)できます。
+`package.json`の`scripts`プロパティに開発によく使うコマンドを登録します。次のように記載して、`npm run dev`コマンドを実行することでWebサーバーを起動できるようにしましょう。[[`tsx`パッケージ]]では、[Node.jsと同様のオプションが利用](https://tsx.is/node-enhancement#swap-node-for-tsx)できます。
```json title="backend/package.jsonの抜粋"
{
@@ -205,11 +204,11 @@ Expressを用いる場合には、[`cors`パッケージ](https://www.npmjs.com/
#### バックエンドのURLを環境変数で指定する
-`.env`ファイルを作成し、環境変数`VITE_API_ENDPOINT`の値にバックエンドのURLである`http://localhost:3000`を指定します。
+`.env`ファイルを作成し、[[環境変数]]`VITE_API_ENDPOINT`の値にバックエンドのURLである`http://localhost:3000`を指定します。
#### アプリケーションのコードを記述する
-`App.tsx`ファイルを編集し、次のように記述します。掲示板の投稿の取得や、新しい投稿の送信には、`fetch`関数を使用します。`fetch`関数の第1引数は今までは`/posts`のように指定していましたが、ここでは`${import.meta.env.VITE_API_ENDPOINT}/posts`と指定します。`import.meta.env.VITE_API_ENDPOINT`で環境変数`VITE_API_ENDPOINT`に指定されたバックエンドのURLを利用しています。
+`App.tsx`ファイルを編集し、次のように記述します。掲示板の投稿の取得や、新しい投稿の送信には、`fetch`関数を使用します。`fetch`関数の第1引数は今までは`/posts`のように指定していましたが、ここでは`${import.meta.env.VITE_API_ENDPOINT}/posts`と指定します。`import.meta.env.VITE_API_ENDPOINT`で[[環境変数]]`VITE_API_ENDPOINT`に指定されたバックエンドのURLを利用しています。
```tsx title="frontend/src/App.tsx"
import { useEffect, useState } from "react";
@@ -264,7 +263,7 @@ export default App;
:::tip[Viteでの環境変数の利用]
-Viteは、[`VITE_`で始まる環境変数を、アプリケーション内で`import.meta.env`オブジェクトのプロパティとして利用](https://ja.vite.dev/guide/env-and-mode.html#env-variables)できるようにします。例えば、`VITE_API_ENDPOINT`という環境変数の値は、`import.meta.env.VITE_API_ENDPOINT`と記述することで利用できます。
+Viteは、[`VITE_`で始まる[[環境変数]]を、アプリケーション内で`import.meta.env`オブジェクトのプロパティとして利用](https://ja.vite.dev/guide/env-and-mode.html#env-variables)できるようにします。例えば、`VITE_API_ENDPOINT`という[[環境変数]]の値は、`import.meta.env.VITE_API_ENDPOINT`と記述することで利用できます。
なお、Viteは起動時に`.env`ファイルに記述された環境変数を読み込みます。
@@ -278,16 +277,16 @@ Viteは、[`VITE_`で始まる環境変数を、アプリケーシ
今までの開発環境では、`npm run dev`コマンドを実行することで、バックエンドとフロントエンドのサーバーを起動していました。
-しかし、本番環境では、これとは異なる方法を用います。バックエンドでは、ビルド済みのJavaScriptファイルを実行してWebサーバーを起動します。フロントエンドでは、Viteによるビルド結果をRenderで配信します。
+しかし、本番環境では、これとは異なる方法を用います。バックエンドでは、[[ビルド]]済みのJavaScriptファイルを実行してWebサーバーを起動します。フロントエンドでは、Viteによる[[ビルド]]結果をRenderで配信します。
-| 環境 | バックエンド | フロントエンド |
-| -------- | --------------------------------------------------------------------------- | ----------------------------------------------- |
-| 開発環境 | `tsx`パッケージでTypeScriptファイルを実行してWebサーバーを起動 | Viteの開発用サーバーを起動 |
-| 本番環境 | ビルド済みのJavaScriptファイルを実行してWebサーバーを起動 | Viteによるビルド結果をRenderで配信 |
+| 環境 | バックエンド | フロントエンド |
+| -------- | ------------------------------------------------------------------ | -------------------------------------- |
+| 開発環境 | [[`tsx`パッケージ]]でTypeScriptファイルを実行してWebサーバーを起動 | Viteの開発用サーバーを起動 |
+| 本番環境 | [[ビルド]]済みのJavaScriptファイルを実行してWebサーバーを起動 | Viteによる[[ビルド]]結果をRenderで配信 |
### ビルドの設定をする
-[「トランスパイラとモジュールバンドラ」の節](/docs/advanced/bundler/)で述べたように、フロントエンドのビルドのための設定は、`npm create vite@latest`コマンドを実行することで自動的に生成される`package.json`ファイルに含まれています。`npm run build`コマンドを実行することで、ビルド結果が`dist`ディレクトリに出力されます。本番環境では、この`dist`ディレクトリをRenderで配信します。
+[「トランスパイラとモジュールバンドラ」の節](/docs/advanced/bundler/)で述べたように、フロントエンドの[[ビルド]]のための設定は、`npm create vite@latest`コマンドを実行することで自動的に生成される`package.json`ファイルに含まれています。`npm run build`コマンドを実行することで、[[ビルド]]結果が`dist`ディレクトリに出力されます。本番環境では、この`dist`ディレクトリをRenderで配信します。
```json title="frontend/package.jsonの抜粋"
{
@@ -297,12 +296,12 @@ Viteは、[`VITE_`で始まる環境変数を、アプリケーシ
}
```
-次に、バックエンドのビルドのための設定を行いましょう。
+次に、バックエンドの[[ビルド]]のための設定を行いましょう。
-1. `tsconfig.json`の[`outDir`オプション](https://www.typescriptlang.org/tsconfig/#outDir)の値を`"./dist"`にして、トランスパイル結果が`dist`ディレクトリに入るようにします。また、`.gitignore`ファイルに`/dist`を追加して、`dist`ディレクトリがGitの管理下に入らないようにします。
-1. `package.json`の`scripts`プロパティに次のように記載して、`npm run build`コマンドと`npm start`コマンドが使えるようにしましょう。`npm run build`コマンドでビルド結果を`dist`ディレクトリに出力し、`npm start`コマンドでビルド済みのJavaScriptファイルを実行できるようになります。
+1. `tsconfig.json`の[`outDir`オプション](https://www.typescriptlang.org/tsconfig/#outDir)の値を`"./dist"`にして、[[トランスパイル]]結果が`dist`ディレクトリに入るようにします。また、`.gitignore`ファイルに`/dist`を追加して、`dist`ディレクトリがGitの管理下に入らないようにします。
+1. `package.json`の`scripts`プロパティに次のように記載して、`npm run build`コマンドと`npm start`コマンドが使えるようにしましょう。`npm run build`コマンドで[[ビルド]]結果を`dist`ディレクトリに出力し、`npm start`コマンドで[[ビルド]]済みのJavaScriptファイルを実行できるようになります。
```json title="backend/package.jsonの抜粋"
{
@@ -316,23 +315,23 @@ Viteは、[`VITE_`で始まる環境変数を、アプリケーシ
### Renderにデプロイする
-次の手順に従って、作成したアプリケーションをRenderにデプロイしましょう。Renderにデプロイするには、作成したアプリケーションをGitHubのリポジトリに保存しておく必要があります。
+次の手順に従って、作成したアプリケーションをRenderに[[デプロイ]]しましょう。Renderに[[デプロイ]]するには、作成したアプリケーションをGitHubのリポジトリに保存しておく必要があります。
-1. バックエンドをデプロイするため、Renderにログインした直後の画面から`Web Service`を作成します。
+1. バックエンドを[[デプロイ]]するため、Renderにログインした直後の画面から`Web Service`を作成します。

-1. {/* */}デプロイするアプリケーションのコードを含むGitHubのリポジトリを選択した後、次のように設定します。
+1. [[デプロイ]]するアプリケーションのコードを含むGitHubのリポジトリを選択した後、次のように設定します。

-1. {/* */}環境変数`DATABASE_URL`でデータベースへの接続情報を設定します。環境変数`WEB_ORIGIN`は、ひとまず空のままにしておきます。
+1. [[環境変数]]`DATABASE_URL`でデータベースへの接続情報を設定します。[[環境変数]]`WEB_ORIGIN`は、ひとまず空のままにしておきます。

-1. フロントエンドをデプロイするため、`Static Site`を作成します。
+1. フロントエンドを[[デプロイ]]するため、`Static Site`を作成します。

@@ -340,11 +339,11 @@ Viteは、[`VITE_`で始まる環境変数を、アプリケーシ

-1. {/* */}環境変数`VITE_API_ENDPOINT`に先ほどデプロイしたバックエンドのURLを設定します。
+1. [[環境変数]]`VITE_API_ENDPOINT`に先ほど[[デプロイ]]したバックエンドのURLを設定します。

-1. バックエンドの環境変数の設定を再度開き、環境変数`WEB_ORIGIN`に先ほどデプロイしたフロントエンドのオリジンを設定します。
+1. バックエンドの[[環境変数]]の設定を再度開き、[[環境変数]]`WEB_ORIGIN`に先ほど[[デプロイ]]したフロントエンドの[[オリジン]]を設定します。

diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index cd4ad463..490aa0fe 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -4,6 +4,7 @@ import type * as Preset from "@docusaurus/preset-classic";
import { execSync } from "node:child_process";
import math from "remark-math";
import katex from "rehype-katex";
+import remarkTerm from "./src/remark/remark-term";
const config: Config = {
title: "ut.code(); Learn",
@@ -46,7 +47,7 @@ const config: Config = {
showLastUpdateTime: true,
sidebarPath: "./sidebars.ts",
editUrl: "https://github.com/ut-code/utcode-learn/blob/main/",
- remarkPlugins: [math],
+ remarkPlugins: [math, remarkTerm],
rehypePlugins: [katex],
},
theme: {
diff --git a/package-lock.json b/package-lock.json
index dd4fffe2..ccf9fa5d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,8 @@
"@tippyjs/react": "^4.2.6",
"clsx": "^2.1.1",
"hast-util-is-element": "^3.0.0",
+ "mdast-util-mdx-jsx": "^3.2.0",
+ "mdast-util-phrasing": "^4.1.0",
"outdent": "^0.8.0",
"prism-react-renderer": "^2.4.1",
"react": "^19.2.4",
@@ -26,18 +28,20 @@
"react-slick": "^0.31.0",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
- "slick-carousel": "^1.8.1"
+ "slick-carousel": "^1.8.1",
+ "unified": "^11.0.5"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.9.2",
"@docusaurus/tsconfig": "^3.9.2",
"@docusaurus/types": "^3.9.2",
+ "@types/mdast": "^4.0.4",
"@types/react-slick": "^0.23.13",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
},
"engines": {
- "node": ">=18.0"
+ "node": ">=24.0"
}
},
"node_modules/@algolia/abtesting": {
diff --git a/package.json b/package.json
index c4e8faf4..d7d0bc9c 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,8 @@
"@tippyjs/react": "^4.2.6",
"clsx": "^2.1.1",
"hast-util-is-element": "^3.0.0",
+ "mdast-util-mdx-jsx": "^3.2.0",
+ "mdast-util-phrasing": "^4.1.0",
"outdent": "^0.8.0",
"prism-react-renderer": "^2.4.1",
"react": "^19.2.4",
@@ -31,7 +33,8 @@
"react-slick": "^0.31.0",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
- "slick-carousel": "^1.8.1"
+ "slick-carousel": "^1.8.1",
+ "unified": "^11.0.5"
},
"browserslist": {
"production": [
@@ -52,6 +55,7 @@
"@docusaurus/module-type-aliases": "^3.9.2",
"@docusaurus/tsconfig": "^3.9.2",
"@docusaurus/types": "^3.9.2",
+ "@types/mdast": "^4.0.4",
"@types/react-slick": "^0.23.13",
"prettier": "^3.8.1",
"typescript": "^5.9.3"
diff --git a/src/remark/remark-term.ts b/src/remark/remark-term.ts
new file mode 100644
index 00000000..76cf4e43
--- /dev/null
+++ b/src/remark/remark-term.ts
@@ -0,0 +1,88 @@
+import type { Plugin } from "unified";
+import type { Nodes, PhrasingContent, Root, RootContent } from "mdast";
+import { phrasing } from "mdast-util-phrasing";
+
+/**
+ * `[[用語]]`を`用語`に変換するプラグイン。
+ *
+ * @example
+ * // returns "**HTML**とCSS、そしてJavaScriptです。"
+ * String(
+ * await remark()
+ * .use(remarkMdx)
+ * .use(remarkTerm)
+ * .process("[[**HTML**]]と[[CSS]]、そして[[JavaScript]]です。"),
+ * );
+ */
+const remarkTerm: Plugin<[], Root> = () => (tree) => transform(tree);
+
+export default remarkTerm;
+
+function isParent(node: Nodes) {
+ return "children" in node;
+}
+
+function transform(node: Nodes) {
+ if (!isParent(node)) return;
+
+ for (const child of node.children) {
+ transform(child);
+ }
+
+ node.children = wrapDelimitedPhrasingContentsAsTerm(
+ node.children.flatMap((child) => isolateTermDelimiters(child)),
+ );
+}
+
+function isolateTermDelimiters(node: RootContent): RootContent[] {
+ if (node.type !== "text") return [node];
+
+ return node.value
+ .split(/(\[\[|\]\])/)
+ .filter((segment) => segment !== "")
+ .map((segment) => ({
+ type: "text",
+ value: segment,
+ }));
+}
+
+function wrapDelimitedPhrasingContentsAsTerm(
+ children: RootContent[],
+): RootContent[] {
+ const result: RootContent[] = [];
+ const buffer: PhrasingContent[] = [];
+
+ for (const child of children) {
+ if (buffer.length === 0) {
+ if (child.type === "text" && child.value === "[[") {
+ buffer.push(child);
+ continue;
+ }
+ result.push(child);
+ continue;
+ }
+
+ if (child.type === "text" && child.value === "]]") {
+ result.push({
+ type: "mdxJsxTextElement",
+ name: "Term",
+ attributes: [],
+ children: buffer.slice(1),
+ });
+ buffer.length = 0;
+ continue;
+ }
+
+ if (phrasing(child)) {
+ buffer.push(child);
+ continue;
+ }
+
+ result.push(...buffer, child);
+ buffer.length = 0;
+ }
+
+ result.push(...buffer);
+
+ return result;
+}
diff --git a/src/types/mdast-mdx-jsx.d.ts b/src/types/mdast-mdx-jsx.d.ts
new file mode 100644
index 00000000..d1718bb0
--- /dev/null
+++ b/src/types/mdast-mdx-jsx.d.ts
@@ -0,0 +1,2 @@
+// mdastのノードにMDX JSXのノードを追加
+import "mdast-util-mdx-jsx";