diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d08a1a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore index ab234eb..c1c1f15 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ **/dist **/out **/tests.failed.json +packages/playground/public/assets/locale/* diff --git a/.localerc.json b/.localerc.json new file mode 100644 index 0000000..dfa6dda --- /dev/null +++ b/.localerc.json @@ -0,0 +1,10 @@ +{ + "basic": { + "source": "packages/playground/node_modules/@fuyeor/locale/src/common.json", + "outDir": "packages/playground/public/assets/locale" + }, + "main": { + "source": "packages/playground/src/locale/locale.json", + "outDir": "packages/playground/public/assets/locale" + } +} diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..424942b --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@fuyeor:registry=https://fpm.fuyeor.com/v1/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 1223cd0..af9c146 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,7 @@ "editor.formatOnSave": true, // assign default formatting tool "[html]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.html-language-features" }, "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" diff --git a/Dockerfile b/Dockerfile index d9352d3..a0be6bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,8 +26,11 @@ COPY . . # build parser package before workspace consumers resolve its package exports RUN pnpm --filter @fuyeor/markdown-parser build +# generate production locale assets before the playground build copies public files +RUN pnpm locale make playground prod + # build playground -RUN pnpm --filter @fuyeor/markdown-parser-playground build +RUN pnpm --filter @fuyeor/markdown-playground build # ========================================== # release diff --git a/package.json b/package.json index c188742..6786f01 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "scripts": { "format": "prettier --write \"**/*.ts\"", "test": "pnpm -F @fuyeor/markdown-parser test", - "playground": "pnpm -F @fuyeor/markdown-playground dev" + "playground": "pnpm -F @fuyeor/markdown-playground dev", + "locale": "locale-cli" }, "devDependencies": { + "@fuyeor/locale-cli": "^0.1.1", "@types/node": "^25.6.0", "jsdom": "^29.0.1", "prettier": "^3.8.3", diff --git a/packages/markdown-parser-vue/src/index.ts b/packages/markdown-parser-vue/src/index.ts new file mode 100644 index 0000000..d54cf72 --- /dev/null +++ b/packages/markdown-parser-vue/src/index.ts @@ -0,0 +1,2 @@ +// @fuyeor/markdown-parser-vue/src/index.ts +export { renderToVue } from './render'; diff --git a/packages/playground/index.html b/packages/playground/index.html index 157bee3..64e5d83 100644 --- a/packages/playground/index.html +++ b/packages/playground/index.html @@ -1,20 +1,114 @@ - - - - - - @fuyeor/markdown-parser - - + + + + + + + + + + + + + + + + + + + + + + Fuyeor Flavored Markdown Playground + + + + + + + + + + + + - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/packages/playground/package.json b/packages/playground/package.json index fa5166f..6dd0db8 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -3,25 +3,32 @@ "license": "MIT", "author": "Fuyeor ", "type": "module", - "sideEffects": false, "scripts": { "dev": "vite dev", - "build": "vite build" - }, - "imports": { - "#/*": "./src/*" + "build": "vite build", + "typecheck": "vue-tsc --noEmit" }, "exports": { ".": "./src/main.ts" }, "dependencies": { - "@fuyeor/markdown-parser-lit": "workspace:*", - "@fuyeor/locale": "https://github.com/Fuyeor/webroamer.git#path:packages/locale", - "lit": "^3.3.2" + "@fuyeor/commons": "^0.1.2", + "@fuyeor/config": "^0.1.1", + "@fuyeor/interactify": "^0.1.1", + "@fuyeor/locale": "^0.1.0", + "@fuyeor/markdown-formatter": "workspace:*", + "@fuyeor/markdown-parser": "workspace:*", + "@fuyeor/markdown-parser-vue": "workspace:*", + "@fuyeor/vue-router": "^0.0.9", + "vue": "^3.5.41" }, "devDependencies": { - "@types/node": "^25.6.0", - "typescript": "^6.0.3", - "vite": "^8.0.1" + "@fuyeor/tsconfig": "0.1.0", + "@types/node": "^26.2.0", + "@vitejs/plugin-vue": "^6.0.8", + "html-minifier-terser": "^7.2.0", + "lightningcss": "^1.33.0", + "typescript": "^7.0.2", + "vite": "8.0.1" } } diff --git a/packages/playground/public/assets/css/style.css b/packages/playground/public/assets/css/style.css new file mode 100644 index 0000000..19db6ff --- /dev/null +++ b/packages/playground/public/assets/css/style.css @@ -0,0 +1,158 @@ +:root { + --width-body: 100%; + --width-main: 1000px; + --width-left-sidebar: 350px; + --width-right-sidebar: 0; + + --playground-border: #e2e8f0; + --playground-bg-section: #ffffff; + --playground-bg-header: #f8fafc; + --playground-font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; +} + +@media (width >= 1000px) { + main { + width: 100%; + } + + .header { + border: none; + } +} + +h3::after { + display: none; +} + +.markdown-rendered { + ol, + ul { + margin: 0 0 20px 20px; + padding: 0; + } + + li { + margin: 10px 0 10px 0; + } + + code, + pre, + pre * { + font-size: 0.9rem; + } +} + +html { + /* remove scroll bar */ + scrollbar-gutter: unset; +} + +body { + overflow: hidden; +} + +.playground-layout { + display: grid; + grid-template-columns: minmax(280px, 1fr) minmax(360px, 1.2fr); + height: calc(-110px + 100vh); +} + +.section { + display: flex; + flex-direction: column; + min-width: 0; + min-height: 0; + overflow: hidden; +} + +.editor { + border-right: var(--border-subtle); + + textarea { + flex: 1; + resize: none; + background: transparent; + font: 400 13px / 1.6 var(--playground-font-mono); + tab-size: 2; + overflow-y: auto; + } + + textarea:hover, + textarea:focus { + box-shadow: none; + } +} + +@media (width <= 900px) { + .playground-layout { + height: auto; + grid-template-columns: 1fr; + grid-template-rows: 400px 520px; + position: absolute; + top: var(--height-header); + } + + .preview { + border-top: var(--border-subtle); + } +} + +/* FFM Ambassador Theme Tokens */ +:root { + --ink: #24354b; + --ink-soft: #64707d; + --paper: #fbfaf7; + --paper-deep: #f1efe8; + --lilac: #aea4e4; + --lilac-deep: #8275ce; + --lilac-pale: #eeebfb; + --sage: #8ba493; + --line: rgba(36, 53, 75, 0.12); + --card: rgba(255, 255, 255, 0.86); + --radius: 16px; + --ease-out: cubic-bezier(0.23, 1, 0.32, 1); + --background: var(--paper); + --foreground: var(--ink); + --card-foreground: var(--ink); + --popover: var(--paper); + --popover-foreground: var(--ink); + --primary: var(--lilac-deep); + --primary-foreground: #fff; + --secondary: var(--lilac-pale); + --secondary-foreground: var(--ink); + --muted: var(--paper-deep); + --muted-foreground: var(--ink-soft); + --accent: var(--lilac-pale); + --accent-foreground: var(--ink); + --destructive: #c84c4a; + --destructive-foreground: #fff; + --border: var(--line); + --input: var(--line); + --ring: var(--lilac); +} + +.night { + --ink: #f0eff5; + --ink-soft: #b7b6c4; + --paper: #11101c; + --paper-deep: #191827; + --lilac-pale: #292743; + --line: rgba(239, 238, 247, 0.12); + --card: rgba(30, 29, 44, 0.9); +} + +body.home-page { + overflow: auto; + background: var(--paper); + color: var(--ink); +} + +.home-page .paper-grain { + mix-blend-mode: multiply; +} + +.night .paper-grain { + mix-blend-mode: screen; + opacity: 0.13; +} diff --git a/packages/playground/public/assets/examples/en.ffm b/packages/playground/public/assets/examples/en.ffm new file mode 100644 index 0000000..6d549d0 --- /dev/null +++ b/packages/playground/public/assets/examples/en.ffm @@ -0,0 +1,203 @@ +# Welcome to the Markdown Playground + +This is a sample document designed to showcase and test the syntax of Fuyeor Flavored Markdown. Feel free to edit and preview your changes in real time. + +## Basic Syntax + +### Headings + +```ffm +# Level 1 Heading + +## Level 2 Heading + +### Level 3 Heading + +#### Level 4 Heading + +##### Level 5 Heading + +###### Level 6 Heading +``` + +### Emphasis + +- **Bold text**: use `**text**` +- *Italic text*: use `*text*` +- --Strikethrough--: use `--text--` +- `Inline code`: use backticks `` `code` `` + +### Paragraphs & Line Breaks + +This is the first paragraph. +In Markdown, consecutive lines without a blank line are merged into a single paragraph. + +This is the second paragraph. An empty line creates a new paragraph. + +## Lists + +### Unordered List + +- Apple +- Banana + - Lady Finger Banana + - Cavendish Banana +- Orange + +### Ordered List + +1. Step 1: Open the editor +2. Step 2: Write your Markdown +3. Step 3: Preview the rendered output + 1. Live preview + 2. Export HTML + +## Links & Images + +### Links + +[Example link with text](https://www.example.com) and an autolink: https://www.example.com + +### Images + +![](/favicon.svg) + +## Quotes + +```quote +A small syntax can make a large pause. + +- Format in one breath +- Preview as you write +- Keep every idea close +``` + +## Code + +### Inline Code + +In Python, use `print("Hello, Markdown!")` to print text. + +### Code Blocks + +```fon +{ + identifier = `reference.fuyeor.com` + params = { + locale = .en + module = `ffm` + slug = [`tutorials`, `overview`] + } +} +``` + +## Tables + +| Left-aligned | Center-aligned | Right-aligned | +| :--- | :---: | ---: | +| Content | Content | Content | +| Longer content | Longer content | Longer content | + +## Horizontal Rule + +--- + +## Interactive Components + +### Carousel Slides + +```slide +**Ф social** +- Character limit: 3,000 - 5,000 characters +- Content format: Fuyeor Flavored Markdown + +--- + +**Bluesky** +- Character limit: 300 characters +- Content format: Plain text + +--- + +**Mastodon** +- Character limit: Varies by instance (default is 500) +- Content format: Plain text +``` + +### Chain of Thought + +```chain +**[x] Book the party venue** +Reserved the board game café everyone agreed on; the deposit has been paid. + +**[x] Confirm attendance** +Everyone responded in the group chat; 8 people confirmed in total. + +**[ ] Buy snacks and drinks** +Shopping list ready; planning to pick them up Saturday morning before heading over. + +**[ ] Prepare the mystery birthday gift** +Ordered online and currently in transit; expected delivery by Friday afternoon. + +**Share on social media** +Don't forget to post the party photos on social media afterward~ +``` + +### Accordion + +```accordion +**How can I join the volunteer team?** +Click "Join Us" at the top right of the homepage to fill out a short form. Our coordinators will get in touch within three business days. + +**Do I need to bring my own tools to events?** +Not at all! All necessary materials and tools will be provided on-site free of charge. + +**What if I can no longer make it?** +No problem. Simply go to your profile and click "Cancel Booking" at least 24 hours prior to the event. +``` + +## Academic Extensions + +### LaTeX + +Inline formula: $E = mc^2$ + +Block formula: + +$$ +\int_0^1 x^2 \, dx = \frac{1}{3} +$$ + +### Diagrams & Flowcharts + +```mermaid +graph TD + A[Start] --> B(Processing) + B --> C{Decision} + C -- Approve --> D[End] + C -- Reject --> E[Revise] +``` + +### Chemical Formulas + +When it comes to pain relief, the well-known structural formula for aspirin is #[smiles = `CC(=O)OC1=CC=CC=C1C(=O)O`]; its counterpart, ibuprofen, has the molecular formula #[smiles = `CC(C)CC1=CC=C(C=C1)C(C)C(=O)O`]. + +### Musical Score + +```abc +X: 1 +T: Scale Example +M: 4/4 +L: 1/4 +K: C +C D E F | G A B c | +``` + +## Summary + +Congratulations on completing the Markdown Playground tutorial! You are now ready to craft your own Markdown documents: + +- Switch documents from the left sidebar (or the menu in the top-left corner on mobile). +- All documents are saved locally and accessible only to you. + +Happy writing! \ No newline at end of file diff --git a/packages/playground/public/assets/examples/fr.ffm b/packages/playground/public/assets/examples/fr.ffm new file mode 100644 index 0000000..7e32f3a --- /dev/null +++ b/packages/playground/public/assets/examples/fr.ffm @@ -0,0 +1,203 @@ +# Bienvenue sur l'Espace Markdown + +Ce document est un exemple conçu pour tester et découvrir la syntaxe du Fuyeor Flavored Markdown. Vous pouvez le modifier et prévisualiser le rendu en temps réel. + +## Syntaxe de base + +### Titres + +```ffm +# Titre de niveau 1 + +## Titre de niveau 2 + +### Titre de niveau 3 + +#### Titre de niveau 4 + +##### Titre de niveau 5 + +###### Titre de niveau 6 +``` + +### Emphase + +- **Texte en gras** : utilisez `**texte**` +- *Texte en italique* : utilisez `*texte*` +- --Texte barré-- : utilisez `--texte--` +- `Code en ligne` : utilisez les accents graves `` `code` `` + +### Paragraphes et retours à la ligne + +Ceci est le premier paragraphe. +En Markdown, deux lignes consécutives sans ligne vide sont fusionnées dans le même paragraphe. + +Ceci est le second paragraphe. Une ligne vide crée un nouveau paragraphe. + +## Listes + +### Liste à puces + +- Pomme +- Banane + - Banane Frécinette + - Banane Cavendish +- Orange + +### Liste numérotée + +1. Étape 1 : Ouvrez l'éditeur +2. Étape 2 : Rédigez votre Markdown +3. Étape 3 : Prévisualisez le résultat + 1. Aperçu en temps réel + 2. Exporter en HTML + +## Liens et images + +### Liens + +[Exemple de lien avec texte](https://www.example.com) et lien brut : https://www.example.com + +### Images + +![](/favicon.svg) + +## Citations + +```quote +A small syntax can make a large pause. + +- Format in one breath +- Preview as you write +- Keep every idea close +``` + +## Code + +### Code en ligne + +En Python, utilisez `print("Hello, Markdown!")` pour afficher du texte. + +### Blocs de code + +```fon +{ + identifier = `reference.fuyeor.com` + params = { + locale = .en + module = `ffm` + slug = [`tutorials`, `overview`] + } +} +``` + +## Tableaux + +| Aligné à gauche | Centré | Aligné à droite | +| :--- | :---: | ---: | +| Contenu | Contenu | Contenu | +| Contenu plus long | Contenu plus long | Contenu plus long | + +## Ligne de séparation + +--- + +## Composants interactifs + +### Diapositives + +```slide +**Ф social** +- Limite de caractères : 3 000 - 5 000 caractères +- Format de contenu : Fuyeor Flavored Markdown + +--- + +**Bluesky** +- Limite de caractères : 300 caractères +- Format de contenu : Texte brut + +--- + +**Mastodon** +- Limite de caractères : Variable selon l'instance (500 par défaut) +- Format de contenu : Texte brut +``` + +### Fil de pensée + +```chain +**[x] Réserver le lieu de la soirée** +Le bar à jeux choisi à l'unanimité est réservé, et l'acompte est versé. + +**[x] Confirmer le nombre de participants** +Tout le monde a répondu sur le groupe de discussion ; 8 personnes confirmées au total. + +**[ ] Acheter les boissons et les collations** +Liste de courses prête ; prévu de faire les achats samedi matin avant de s'y rendre. + +**[ ] Préparer le cadeau d'anniversaire surprise** +Cadeau commandé en ligne, en cours de livraison ; arrivée prévue vendredi après-midi. + +**Publier sur les réseaux sociaux** +N'oubliez pas de partager les photos de la fête sur les réseaux sociaux ensuite~ +``` + +### Accordéon + +```accordion +**Comment rejoindre notre équipe de bénévoles ?** +Cliquez sur « Rejoignez-nous » en haut à droite de la page d'accueil pour remplir un court formulaire. Notre équipe vous contactera sous trois jours ouvrés. + +**Dois-je apporter mes propres outils pour les événements ?** +Pas du tout ! Tout le matériel et les outils nécessaires sont fournis gratuitement sur place. + +**Que faire en cas d'empêchement ?** +Aucun problème. Il vous suffit de vous rendre dans votre espace personnel et de cliquer sur « Annuler la réservation » au moins 24 heures avant l'événement. +``` + +## Extensions académiques + +### Formules mathématiques + +Formule en ligne : $E = mc^2$ + +Formule en bloc : + +$$ +\int_0^1 x^2 \, dx = \frac{1}{3} +$$ + +### Diagrammes et organigrammes + +```mermaid +graph TD + A[Début] --> B(Traitement) + B --> C{Condition} + C -- Approuvé --> D[Fin] + C -- Refusé --> E[À modifier] +``` + +### Formules chimiques + +Pour soulager la douleur, la structure de l'aspirine la plus connue est #[smiles = `CC(=O)OC1=CC=CC=C1C(=O)O`] ; son pendant, l'ibuprofène, a pour formule moléculaire #[smiles = `CC(C)CC1=CC=C(C=C1)C(C)C(=O)O`]. + +### Partition de musique + +```abc +X: 1 +T: Exemple de gamme (Scale Example) +M: 4/4 +L: 1/4 +K: C +C D E F | G A B c | +``` + +## Conclusion + +Félicitations pour avoir terminé le guide de l'espace Markdown ! Vous êtes maintenant prêt(e) à rédiger vos propres documents : + +- Changez de document depuis la barre latérale gauche (ou le menu en haut à gauche sur mobile). +- Tous vos documents sont enregistrés localement et vous êtes la seule personne à pouvoir y accéder. + +Bonne rédaction ! \ No newline at end of file diff --git a/packages/playground/public/assets/examples/ja.ffm b/packages/playground/public/assets/examples/ja.ffm new file mode 100644 index 0000000..4359988 --- /dev/null +++ b/packages/playground/public/assets/examples/ja.ffm @@ -0,0 +1,203 @@ +# Markdown プレイグラウンドへようこそ + +本ドキュメントは、Fuyeor Flavored Markdown の構文をテスト・体験するためのサンプルドキュメントです。ここで自由に編集し、リアルタイムでプレビューを確認できます。 + +## 基本構文 + +### 見出し + +```ffm +# レベル 1 見出し + +## レベル 2 見出し + +### レベル 3 見出し + +#### レベル 4 見出し + +##### レベル 5 見出し + +###### レベル 6 見出し +``` + +### 強調 + +- **太字テキスト**:`**テキスト**` を使用 +- *斜体テキスト*:`*テキスト*` を使用 +- --取り消し線--:`--テキスト--` を使用 +- `インラインコード`:バッククォート `` `コード` `` を使用 + +### 段落と改行 + +これは 1 つ目の段落です。 +Markdown では、空行を挟まない連続した行は同じ段落として結合されます。 + +これは 2 つ目の段落です。空行を入れることで新しい段落が作成されます。 + +## リスト + +### 箇条書きリスト + +- りんご +- バナナ + - モンキーバナナ + - キャベンディッシュ +- オレンジ + +### 番号付きリスト + +1. ステップ 1:エディタを開く +2. ステップ 2:Markdown を記述する +3. ステップ 3:プレビューを確認する + 1. リアルタイムプレビュー + 2. HTML のエクスポート + +## リンクと画像 + +### リンク + +[テキスト付きリンクの例](https://www.example.com) と 自動リンク:https://www.example.com + +### 画像 + +![](/favicon.svg) + +## 引用 + +```quote +A small syntax can make a large pause. + +- Format in one breath +- Preview as you write +- Keep every idea close +``` + +## コード + +### インラインコード + +Python では、`print("Hello, Markdown!")` を使用してテキストを出力します。 + +### コードブロック + +```fon +{ + identifier = `reference.fuyeor.com` + params = { + locale = .en + module = `ffm` + slug = [`tutorials`, `overview`] + } +} +``` + +## テーブル + +| 左揃え | 中央揃え | 右揃え | +| :--- | :---: | ---: | +| コンテンツ | コンテンツ | コンテンツ | +| 長いコンテンツ | 長いコンテンツ | 長いコンテンツ | + +## 区切り線 + +--- + +## レイアウトコンポーネント + +### スライド + +```slide +**Ф social** +- 文字数制限:3,000 - 5,000 文字 +- フォーマット:Fuyeor Flavored Markdown + +--- + +**Bluesky** +- 文字数制限:300 文字 +- フォーマット:プレーンテキスト + +--- + +**Mastodon** +- 文字数制限:インスタンスにより異なりますが、デフォルトは 500 文字です +- フォーマット:プレーンテキスト +``` + +### 思考チェーン + +```chain +**[x] パーティー会場の予約** +みんなで決めたボードゲームカフェを予約し、予約金の支払いも完了。 + +**[x] 当日の参加人数の確認** +グループチャットでの出欠確認が完了。合計 8 名が参加予定。 + +**[ ] お菓子と飲み物の買い出し** +買い物リストを作成済み。土曜の午前に購入して直接お店へ持参する予定。 + +**[ ] サプライズ誕生日プレゼントの準備** +ネット注文したプレゼントは配送中。金曜日の午後に到着予定。 + +**SNS に投稿** +最後にパーティーの写真を SNS にシェアするのをお忘れなく〜 +``` + +### アコーディオン + +```accordion +**ボランティアチームに参加するには?** +ホームページ右上の「参加登録」から簡単なフォームに入力してください。3 営業日以内に担当コーディネーターよりご連絡いたします。 + +**イベントへの参加に道具の持参は必要ですか?** +いいえ、必要な資材や道具はすべて会場にて無料でご用意しております。 + +**急用で参加できなくなった場合は?** +問題ありません。イベント開始の 24 時間前までに、マイページから「予約をキャンセル」をクリックしてください。 +``` + +## アカデミック拡張 + +### 数式 + +インライン数式:$E = mc^2$ + +ブロック数式: + +$$ +\int_0^1 x^2 \, dx = \frac{1}{3} +$$ + +### フローチャート・ダイアグラム + +```mermaid +graph TD + A[開始ノード] --> B(処理プロセス) + B --> C{条件分岐} + C -- 承認 --> D[終了ノード] + C -- 却下 --> E[修正へ戻る] +``` + +### 化学構造式 + +鎮痛剤として広く知られるアスピリンの構造式は #[smiles = `CC(=O)OC1=CC=CC=C1C(=O)O`] であり、その対抗薬であるイブプロフェンの分子式は #[smiles = `CC(C)CC1=CC=C(C=C1)C(C)C(=O)O`] です。 + +### 楽譜 + +```abc +X: 1 +T: 練習曲 (Scale Example) +M: 4/4 +L: 1/4 +K: C +C D E F | G A B c | +``` + +## まとめ + +Markdown プレイグラウンドのチュートリアル完了、お疲れさまでした!これで独自の Markdown ドキュメントを作成する準備が整いました: + +- 左サイドバー(モバイル端末では左上のメニュー)からドキュメントを切り替えられます。 +- すべてのドキュメントはローカルに保存され、あなただけが閲覧できます。 + +素敵なライティング体験を! \ No newline at end of file diff --git a/packages/playground/public/assets/examples/zh-hans.ffm b/packages/playground/public/assets/examples/zh-hans.ffm new file mode 100644 index 0000000..b5ea937 --- /dev/null +++ b/packages/playground/public/assets/examples/zh-hans.ffm @@ -0,0 +1,203 @@ +# 欢迎使用 Markdown 演练场 + +这是一个用于测试和展示 Fuyeor Flavored Markdown 语法的示例文档。你可以在这里随意修改、预览。 + +## 基础语法 + +### 标题 + +```ffm +# 一级标题 + +## 二级标题 + +### 三级标题 + +#### 四级标题 + +##### 五级标题 + +###### 六级标题 +``` + +### 强调 + +- **粗体文本**:使用 `**文本**` +- *斜体文本*:使用 `*文本*` +- --删除线--:使用 `--文本--` +- `行内代码`:使用反引号 `` `代码` `` + +### 段落与换行 + +这是第一段。 +在 Markdown 中,连续的两行会合并为同一段落。 + +这是第二段。空一行会创建新的段落。 + +## 列表 + +### 无序列表 + +- 苹果 +- 香蕉 + - 小米蕉 + - 芝麻蕉 +- 橙子 + +### 有序列表 + +1. 第一步:打开编辑器 +2. 第二步:编写 Markdown +3. 第三步:预览效果 + 1. 实时预览 + 2. 导出 HTML + +## 链接与图片 + +### 链接 + +[带文字的链接示例](https://www.example.com)和不带文字的链接:https://www.example.com + +### 图片 + +![](/favicon.svg) + +## 引用 + +```quote +A small syntax can make a large pause. + +- Format in one breath +- Preview as you write +- Keep every idea close +``` + +## 代码 + +### 行内代码 + +在 Python 中,使用 `print("Hello, Markdown!")` 输出文本。 + +### 代码块 + +```fon +{ + identifier = `reference.fuyeor.com` + params = { + locale = .en + module = `ffm` + slug = [`tutorials`, `overview`] + } +} +``` + +## 表格 + +| 左对齐 | 居中对齐 | 右对齐 | +| :--- | :---: | ---: | +| 内容 | 内容 | 内容 | +| 长内容 | 长内容 | 长内容 | + +## 分割线 + +--- + +## 排版 + +### 滑块 + +```slide +**Ф social** +- 字数限制:3000 - 5000(字符数) +- 内容格式:Fuyeor Flavored Markdown + +--- + +**Bluesky** +- 字数限制:300(字符数) +- 内容格式:纯文本 + +--- + +**Mastodon** +- 字数限制:视实例而不同,但大多数实例为默认的 500 +- 内容格式:纯文本 +``` + +### 思维链 + +```chain +**[x] 定好聚会场地** +已经预订好了大家一致同意的桌游店,定金也付过了。 + +**[x] 统计当天到场人数** +群聊里大家都接龙完毕,总共有 8 个人参加。 + +**[ ] 买好零食和饮料** +列好了购物清单,打算周六早上买完直接带去店里。 + +**[ ] 准备神秘生日礼物** +网购的礼物还在路上,预计周五下午送到。 + +**发布社交媒体** +最后记得把聚会照片发在社交媒体〜 +``` + +### 手风琴 + +```accordion +**如何加入我们的志愿者团队?** +点击首页右上角的「加入我们」填写一张简单的报名表,我们的管理员会在三个工作日内联系你。 + +**参与活动需要自己带工具吗?** +不需要哦,每次活动所需的全部材料和工具,我们都会在现场为你免费提供。 + +**如果临时有事去不了怎么办?** +没关系,只需在活动开始前 24 小时,在个人中心点击「取消预约」即可。 +``` + +## 学术扩展 + +### 数学公式 + +行内公式:$E = mc^2$ + +块级公式: + +$$ +\int_0^1 x^2 \, dx = \frac{1}{3} +$$ + +### 流程图与图表 + +```mermaid +graph TD + A[开始节点] --> B(处理过程) + B --> C{条件判断} + C -- 同意 --> D[结束节点] + C -- 拒绝 --> E[返回修改] +``` + +### 化学式 + +提到止痛,大家最熟悉的阿司匹林结构式为 #[smiles = `CC(=O)OC1=CC=CC=C1C(=O)O`];而它的死对头布洛芬,分子式则是 #[smiles = `CC(C)CC1=CC=C(C=C1)C(C)C(=O)O`]。 + +### 五线谱 + +```abc +X: 1 +T: 示例乐曲 (Scale Example) +M: 4/4 +L: 1/4 +K: C +C D E F | G A B c | +``` + +## 总结 + +恭喜你完成了 Markdown 演练场的教程!现在你可以开始创建自己的 Markdown 文档了: + +- 点击左侧边栏(移动端点击左上角菜单)切换文档。 +- 所有的文档保存于本地,只有自己能看到。 + +祝你写作愉快! \ No newline at end of file diff --git a/packages/playground/favicon.svg b/packages/playground/public/favicon.svg similarity index 100% rename from packages/playground/favicon.svg rename to packages/playground/public/favicon.svg diff --git a/packages/playground/public/robots.txt b/packages/playground/public/robots.txt new file mode 100644 index 0000000..26b4d70 --- /dev/null +++ b/packages/playground/public/robots.txt @@ -0,0 +1,2 @@ +User-Agent: * +Allow: / \ No newline at end of file diff --git a/packages/playground/src/App.vue b/packages/playground/src/App.vue new file mode 100644 index 0000000..7e33d8c --- /dev/null +++ b/packages/playground/src/App.vue @@ -0,0 +1,25 @@ + + + + diff --git a/packages/playground/src/api/examples.ts b/packages/playground/src/api/examples.ts new file mode 100644 index 0000000..b06e81f --- /dev/null +++ b/packages/playground/src/api/examples.ts @@ -0,0 +1,11 @@ +// @/api/examples.ts +import apiClient from './index'; + +export async function fetchExample(locale: string): Promise { + try { + return await apiClient.get(`assets/examples/${locale}.ffm`); + } catch (error) { + // Fallback to English example if the requested locale is not found + return await apiClient.get('assets/examples/en.ffm'); + } +} diff --git a/packages/playground/src/api/index.ts b/packages/playground/src/api/index.ts new file mode 100644 index 0000000..549b061 --- /dev/null +++ b/packages/playground/src/api/index.ts @@ -0,0 +1,9 @@ +// @/api/index.ts +import { HttpClient } from '@fuyeor/commons'; + +const apiClient = new HttpClient({ + baseURL: '/', + timeout: 10000, +}); + +export default apiClient; diff --git a/packages/playground/src/components/Home/HomeCampaign.vue b/packages/playground/src/components/Home/HomeCampaign.vue new file mode 100644 index 0000000..dde68e3 --- /dev/null +++ b/packages/playground/src/components/Home/HomeCampaign.vue @@ -0,0 +1,160 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeFeatures.vue b/packages/playground/src/components/Home/HomeFeatures.vue new file mode 100644 index 0000000..959cc4e --- /dev/null +++ b/packages/playground/src/components/Home/HomeFeatures.vue @@ -0,0 +1,201 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeFooter.vue b/packages/playground/src/components/Home/HomeFooter.vue new file mode 100644 index 0000000..c137b51 --- /dev/null +++ b/packages/playground/src/components/Home/HomeFooter.vue @@ -0,0 +1,101 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeHeader.vue b/packages/playground/src/components/Home/HomeHeader.vue new file mode 100644 index 0000000..8ab61d3 --- /dev/null +++ b/packages/playground/src/components/Home/HomeHeader.vue @@ -0,0 +1,223 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeHero.vue b/packages/playground/src/components/Home/HomeHero.vue new file mode 100644 index 0000000..4ce0811 --- /dev/null +++ b/packages/playground/src/components/Home/HomeHero.vue @@ -0,0 +1,323 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeImagePlaceholder.vue b/packages/playground/src/components/Home/HomeImagePlaceholder.vue new file mode 100644 index 0000000..ec7a366 --- /dev/null +++ b/packages/playground/src/components/Home/HomeImagePlaceholder.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeIntro.vue b/packages/playground/src/components/Home/HomeIntro.vue new file mode 100644 index 0000000..831c2d9 --- /dev/null +++ b/packages/playground/src/components/Home/HomeIntro.vue @@ -0,0 +1,71 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeSectionLabel.vue b/packages/playground/src/components/Home/HomeSectionLabel.vue new file mode 100644 index 0000000..c2b42f5 --- /dev/null +++ b/packages/playground/src/components/Home/HomeSectionLabel.vue @@ -0,0 +1,58 @@ + + + + + + diff --git a/packages/playground/src/components/Home/HomeStatement.vue b/packages/playground/src/components/Home/HomeStatement.vue new file mode 100644 index 0000000..bd0c2db --- /dev/null +++ b/packages/playground/src/components/Home/HomeStatement.vue @@ -0,0 +1,119 @@ + + + + + + diff --git a/packages/playground/src/components/Playground/DocumentHistory.vue b/packages/playground/src/components/Playground/DocumentHistory.vue new file mode 100644 index 0000000..84e7b40 --- /dev/null +++ b/packages/playground/src/components/Playground/DocumentHistory.vue @@ -0,0 +1,371 @@ + + + + + + diff --git a/packages/playground/src/components/Playground/DocumentStatsBar.vue b/packages/playground/src/components/Playground/DocumentStatsBar.vue new file mode 100644 index 0000000..2299fdf --- /dev/null +++ b/packages/playground/src/components/Playground/DocumentStatsBar.vue @@ -0,0 +1,60 @@ + + + + + + diff --git a/packages/playground/src/components/Playground/MarkdownToolbar.vue b/packages/playground/src/components/Playground/MarkdownToolbar.vue new file mode 100644 index 0000000..13d21d0 --- /dev/null +++ b/packages/playground/src/components/Playground/MarkdownToolbar.vue @@ -0,0 +1,149 @@ + + + + + + diff --git a/packages/playground/src/components/Playground/PlaygroundEditor.vue b/packages/playground/src/components/Playground/PlaygroundEditor.vue new file mode 100644 index 0000000..b157e39 --- /dev/null +++ b/packages/playground/src/components/Playground/PlaygroundEditor.vue @@ -0,0 +1,263 @@ + +