Full Code of typst-doc-cn/tutorial for AI

main 64a950fa0650 cached
134 files
486.1 KB
175.6k tokens
38 symbols
1 requests
Download .txt
Showing preview only (636K chars total). Download the full file or copy to clipboard to get everything.
Repository: typst-doc-cn/tutorial
Branch: main
Commit: 64a950fa0650
Files: 134
Total size: 486.1 KB

Directory structure:
gitextract_r5ef022r/

├── .codex/
│   └── skills/
│       ├── openspec-apply-change/
│       │   └── SKILL.md
│       ├── openspec-archive-change/
│       │   └── SKILL.md
│       ├── openspec-explore/
│       │   └── SKILL.md
│       ├── openspec-propose/
│       │   └── SKILL.md
│       ├── typst-grammar-authoring/
│       │   └── SKILL.md
│       └── update-typst-grammar-authoring/
│           ├── SKILL.md
│           ├── agents/
│           │   └── openai.yaml
│           ├── references/
│           │   └── grammar-catalog.json
│           └── scripts/
│               └── generate_grammar_catalog.py
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build.yml
│       └── gh_pages.yml
├── .gitignore
├── .gitmodules
├── .vscode/
│   └── settings.json
├── .zed/
│   └── settings.json
├── Cargo.toml
├── LICENSE
├── README.md
├── _typos.toml
├── assets/
│   └── files/
│       └── tokyo-night.tmTheme
├── crates/
│   └── embedded-typst/
│       ├── Cargo.toml
│       └── src/
│           └── lib.rs
├── meta.json
├── openspec/
│   ├── changes/
│   │   └── archive/
│   │       └── 2026-03-15-create-english-typst-grammar-skill/
│   │           ├── .openspec.yaml
│   │           ├── design.md
│   │           ├── proposal.md
│   │           ├── specs/
│   │           │   └── typst-document-authoring-skill/
│   │           │       └── spec.md
│   │           └── tasks.md
│   ├── config.yaml
│   └── specs/
│       └── typst-document-authoring-skill/
│           └── spec.md
├── scripts/
│   ├── build.ps1
│   └── build.sh
├── src/
│   ├── book.typ
│   ├── ebook.typ
│   ├── figures.typ
│   ├── graph/
│   │   ├── digraph.typ
│   │   ├── electronics.typ
│   │   ├── mod.typ
│   │   ├── solid-geometry.typ
│   │   ├── state-machine.typ
│   │   ├── statistics.typ
│   │   └── table.typ
│   ├── intermediate/
│   │   └── mod.typ
│   ├── introduction.typ
│   ├── misc/
│   │   ├── code-syntax.typ
│   │   ├── code-theme.typ
│   │   ├── font-setting.typ
│   │   ├── mod.typ
│   │   └── text-processing.typ
│   ├── mod.typ
│   ├── prefaces/
│   │   ├── acknowledgement.typ
│   │   ├── license.typ
│   │   └── mod.typ
│   ├── science/
│   │   ├── algorithm.typ
│   │   ├── chemical.typ
│   │   ├── mod.typ
│   │   └── theorem.typ
│   ├── template/
│   │   ├── book.typ
│   │   ├── mod.typ
│   │   ├── paper.typ
│   │   └── slides.typ
│   ├── topics/
│   │   ├── call-externals.typ
│   │   ├── mod.typ
│   │   ├── template-book.typ
│   │   ├── template-cv.typ
│   │   ├── template-paper.typ
│   │   ├── writing-component-lib.typ
│   │   ├── writing-math.typ
│   │   └── writing-plugin-lib.typ
│   └── tutorial/
│       ├── doc-modulize.typ
│       ├── doc-stateful.typ
│       ├── figure-time-travel.typ
│       ├── latex-look.typ
│       ├── mod.typ
│       ├── other-file.typ
│       ├── packages/
│       │   └── m1.typ
│       ├── reference-bibliography.typ
│       ├── reference-calculation.typ
│       ├── reference-color.typ
│       ├── reference-counter-state.typ
│       ├── reference-data-process.typ
│       ├── reference-date.typ
│       ├── reference-grammar.typ
│       ├── reference-layout.typ
│       ├── reference-length.typ
│       ├── reference-math-mode.typ
│       ├── reference-math-symbols.typ
│       ├── reference-outline.typ
│       ├── reference-syntax-analysis.typ
│       ├── reference-table.typ
│       ├── reference-type-builtin.typ
│       ├── reference-typebase.typ
│       ├── reference-utils.typ
│       ├── reference-visualization.typ
│       ├── reference-wasm-plugin.typ
│       ├── scripting-block-and-expression.typ
│       ├── scripting-color.typ
│       ├── scripting-composite.typ
│       ├── scripting-content.typ
│       ├── scripting-control-flow.typ
│       ├── scripting-layout.typ
│       ├── scripting-literal.typ
│       ├── scripting-main.typ
│       ├── scripting-shape.typ
│       ├── scripting-style.typ
│       ├── scripting-variable.typ
│       ├── stateful/
│       │   ├── q0.typ
│       │   ├── q1.typ
│       │   ├── s1.typ
│       │   ├── s2.typ
│       │   └── s3.typ
│       ├── stateful-v0.12.0/
│       │   ├── q0.typ
│       │   ├── q1.typ
│       │   ├── s1.typ
│       │   ├── s2.typ
│       │   └── s3.typ
│       ├── writing-chinese.typ
│       ├── writing-markup.typ
│       ├── writing-math.typ
│       ├── writing-scripting.typ
│       └── writing.typ
└── typ/
    ├── book/
    │   ├── lib.typ
    │   ├── typst.toml
    │   └── variables.typ
    ├── embedded-typst/
    │   ├── example.typ
    │   └── lib.typ
    ├── templates/
    │   ├── ebook.typ
    │   ├── page.typ
    │   ├── side-notes.typ
    │   ├── template-link.typ
    │   ├── term.typ
    │   └── theme-style.toml
    └── typst-meta/
        └── docs.typ

================================================
FILE CONTENTS
================================================

================================================
FILE: .codex/skills/openspec-apply-change/SKILL.md
================================================
---
name: openspec-apply-change
description: Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.
license: MIT
compatibility: Requires openspec CLI.
metadata:
  author: openspec
  version: "1.0"
  generatedBy: "1.2.0"
---

Implement tasks from an OpenSpec change.

**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.

**Steps**

1. **Select the change**

   If a name is provided, use it. Otherwise:
   - Infer from conversation context if the user mentioned a change
   - Auto-select if only one active change exists
   - If ambiguous, run `openspec list --json` to get available changes and use the **AskUserQuestion tool** to let the user select

   Always announce: "Using change: <name>" and how to override (e.g., `/opsx:apply <other>`).

2. **Check status to understand the schema**
   ```bash
   openspec status --change "<name>" --json
   ```
   Parse the JSON to understand:
   - `schemaName`: The workflow being used (e.g., "spec-driven")
   - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others)

3. **Get apply instructions**

   ```bash
   openspec instructions apply --change "<name>" --json
   ```

   This returns:
   - Context file paths (varies by schema - could be proposal/specs/design/tasks or spec/tests/implementation/docs)
   - Progress (total, complete, remaining)
   - Task list with status
   - Dynamic instruction based on current state

   **Handle states:**
   - If `state: "blocked"` (missing artifacts): show message, suggest using openspec-continue-change
   - If `state: "all_done"`: congratulate, suggest archive
   - Otherwise: proceed to implementation

4. **Read context files**

   Read the files listed in `contextFiles` from the apply instructions output.
   The files depend on the schema being used:
   - **spec-driven**: proposal, specs, design, tasks
   - Other schemas: follow the contextFiles from CLI output

5. **Show current progress**

   Display:
   - Schema being used
   - Progress: "N/M tasks complete"
   - Remaining tasks overview
   - Dynamic instruction from CLI

6. **Implement tasks (loop until done or blocked)**

   For each pending task:
   - Show which task is being worked on
   - Make the code changes required
   - Keep changes minimal and focused
   - Mark task complete in the tasks file: `- [ ]` → `- [x]`
   - Continue to next task

   **Pause if:**
   - Task is unclear → ask for clarification
   - Implementation reveals a design issue → suggest updating artifacts
   - Error or blocker encountered → report and wait for guidance
   - User interrupts

7. **On completion or pause, show status**

   Display:
   - Tasks completed this session
   - Overall progress: "N/M tasks complete"
   - If all done: suggest archive
   - If paused: explain why and wait for guidance

**Output During Implementation**

```
## Implementing: <change-name> (schema: <schema-name>)

Working on task 3/7: <task description>
[...implementation happening...]
✓ Task complete

Working on task 4/7: <task description>
[...implementation happening...]
✓ Task complete
```

**Output On Completion**

```
## Implementation Complete

**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 7/7 tasks complete ✓

### Completed This Session
- [x] Task 1
- [x] Task 2
...

All tasks complete! Ready to archive this change.
```

**Output On Pause (Issue Encountered)**

```
## Implementation Paused

**Change:** <change-name>
**Schema:** <schema-name>
**Progress:** 4/7 tasks complete

### Issue Encountered
<description of the issue>

**Options:**
1. <option 1>
2. <option 2>
3. Other approach

What would you like to do?
```

**Guardrails**
- Keep going through tasks until done or blocked
- Always read context files before starting (from the apply instructions output)
- If task is ambiguous, pause and ask before implementing
- If implementation reveals issues, pause and suggest artifact updates
- Keep code changes minimal and scoped to each task
- Update task checkbox immediately after completing each task
- Pause on errors, blockers, or unclear requirements - don't guess
- Use contextFiles from CLI output, don't assume specific file names

**Fluid Workflow Integration**

This skill supports the "actions on a change" model:

- **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions
- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly


================================================
FILE: .codex/skills/openspec-archive-change/SKILL.md
================================================
---
name: openspec-archive-change
description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.
license: MIT
compatibility: Requires openspec CLI.
metadata:
  author: openspec
  version: "1.0"
  generatedBy: "1.2.0"
---

Archive a completed change in the experimental workflow.

**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.

**Steps**

1. **If no change name provided, prompt for selection**

   Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.

   Show only active changes (not already archived).
   Include the schema used for each change if available.

   **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.

2. **Check artifact completion status**

   Run `openspec status --change "<name>" --json` to check artifact completion.

   Parse the JSON to understand:
   - `schemaName`: The workflow being used
   - `artifacts`: List of artifacts with their status (`done` or other)

   **If any artifacts are not `done`:**
   - Display warning listing incomplete artifacts
   - Use **AskUserQuestion tool** to confirm user wants to proceed
   - Proceed if user confirms

3. **Check task completion status**

   Read the tasks file (typically `tasks.md`) to check for incomplete tasks.

   Count tasks marked with `- [ ]` (incomplete) vs `- [x]` (complete).

   **If incomplete tasks found:**
   - Display warning showing count of incomplete tasks
   - Use **AskUserQuestion tool** to confirm user wants to proceed
   - Proceed if user confirms

   **If no tasks file exists:** Proceed without task-related warning.

4. **Assess delta spec sync state**

   Check for delta specs at `openspec/changes/<name>/specs/`. If none exist, proceed without sync prompt.

   **If delta specs exist:**
   - Compare each delta spec with its corresponding main spec at `openspec/specs/<capability>/spec.md`
   - Determine what changes would be applied (adds, modifications, removals, renames)
   - Show a combined summary before prompting

   **Prompt options:**
   - If changes needed: "Sync now (recommended)", "Archive without syncing"
   - If already synced: "Archive now", "Sync anyway", "Cancel"

   If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.

5. **Perform the archive**

   Create the archive directory if it doesn't exist:
   ```bash
   mkdir -p openspec/changes/archive
   ```

   Generate target name using current date: `YYYY-MM-DD-<change-name>`

   **Check if target already exists:**
   - If yes: Fail with error, suggest renaming existing archive or using different date
   - If no: Move the change directory to archive

   ```bash
   mv openspec/changes/<name> openspec/changes/archive/YYYY-MM-DD-<name>
   ```

6. **Finalize synced spec purpose**

   If specs were synced or created under `openspec/specs/`:
   - Open each affected main spec at `openspec/specs/<capability>/spec.md`
   - Check the `## Purpose` section
   - If it contains the autogenerated archive placeholder (for example,
     `TBD - created by archiving change ...`) or is still too generic, replace
     it with a concise, capability-specific purpose statement before reporting
     completion

7. **Display summary**

   Show archive completion summary including:
   - Change name
   - Schema that was used
   - Archive location
   - Whether specs were synced (if applicable)
   - Note about any warnings (incomplete artifacts/tasks)

**Output On Success**

```
## Archive Complete

**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** openspec/changes/archive/YYYY-MM-DD-<name>/
**Specs:** ✓ Synced to main specs (or "No delta specs" or "Sync skipped")

All artifacts complete. All tasks complete.
```

**Guardrails**
- Always prompt for change selection if not provided
- Use artifact graph (openspec status --json) for completion checking
- Don't block archive on warnings - just inform and confirm
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
- Show clear summary of what happened
- If sync is requested, use openspec-sync-specs approach (agent-driven)
- If delta specs exist, always run the sync assessment and show the combined summary before prompting
- If archiving creates or updates canonical specs, do not leave autogenerated placeholder `## Purpose` text behind


================================================
FILE: .codex/skills/openspec-explore/SKILL.md
================================================
---
name: openspec-explore
description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.
license: MIT
compatibility: Requires openspec CLI.
metadata:
  author: openspec
  version: "1.0"
  generatedBy: "1.2.0"
---

Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.

**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.

**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.

---

## The Stance

- **Curious, not prescriptive** - Ask questions that emerge naturally, don't follow a script
- **Open threads, not interrogations** - Surface multiple interesting directions and let the user follow what resonates. Don't funnel them through a single path of questions.
- **Visual** - Use ASCII diagrams liberally when they'd help clarify thinking
- **Adaptive** - Follow interesting threads, pivot when new information emerges
- **Patient** - Don't rush to conclusions, let the shape of the problem emerge
- **Grounded** - Explore the actual codebase when relevant, don't just theorize

---

## What You Might Do

Depending on what the user brings, you might:

**Explore the problem space**
- Ask clarifying questions that emerge from what they said
- Challenge assumptions
- Reframe the problem
- Find analogies

**Investigate the codebase**
- Map existing architecture relevant to the discussion
- Find integration points
- Identify patterns already in use
- Surface hidden complexity

**Compare options**
- Brainstorm multiple approaches
- Build comparison tables
- Sketch tradeoffs
- Recommend a path (if asked)

**Visualize**
```
┌─────────────────────────────────────────┐
│     Use ASCII diagrams liberally        │
├─────────────────────────────────────────┤
│                                         │
│   ┌────────┐         ┌────────┐        │
│   │ State  │────────▶│ State  │        │
│   │   A    │         │   B    │        │
│   └────────┘         └────────┘        │
│                                         │
│   System diagrams, state machines,      │
│   data flows, architecture sketches,    │
│   dependency graphs, comparison tables  │
│                                         │
└─────────────────────────────────────────┘
```

**Surface risks and unknowns**
- Identify what could go wrong
- Find gaps in understanding
- Suggest spikes or investigations

---

## OpenSpec Awareness

You have full context of the OpenSpec system. Use it naturally, don't force it.

### Check for context

At the start, quickly check what exists:
```bash
openspec list --json
```

This tells you:
- If there are active changes
- Their names, schemas, and status
- What the user might be working on

### When no change exists

Think freely. When insights crystallize, you might offer:

- "This feels solid enough to start a change. Want me to create a proposal?"
- Or keep exploring - no pressure to formalize

### When a change exists

If the user mentions a change or you detect one is relevant:

1. **Read existing artifacts for context**
   - `openspec/changes/<name>/proposal.md`
   - `openspec/changes/<name>/design.md`
   - `openspec/changes/<name>/tasks.md`
   - etc.

2. **Reference them naturally in conversation**
   - "Your design mentions using Redis, but we just realized SQLite fits better..."
   - "The proposal scopes this to premium users, but we're now thinking everyone..."

3. **Offer to capture when decisions are made**

   | Insight Type | Where to Capture |
   |--------------|------------------|
   | New requirement discovered | `specs/<capability>/spec.md` |
   | Requirement changed | `specs/<capability>/spec.md` |
   | Design decision made | `design.md` |
   | Scope changed | `proposal.md` |
   | New work identified | `tasks.md` |
   | Assumption invalidated | Relevant artifact |

   Example offers:
   - "That's a design decision. Capture it in design.md?"
   - "This is a new requirement. Add it to specs?"
   - "This changes scope. Update the proposal?"

4. **The user decides** - Offer and move on. Don't pressure. Don't auto-capture.

---

## What You Don't Have To Do

- Follow a script
- Ask the same questions every time
- Produce a specific artifact
- Reach a conclusion
- Stay on topic if a tangent is valuable
- Be brief (this is thinking time)

---

## Handling Different Entry Points

**User brings a vague idea:**
```
User: I'm thinking about adding real-time collaboration

You: Real-time collab is a big space. Let me think about this...

      COLLABORATION SPECTRUM
      ════════════════════════════════════════════

      Awareness          Coordination         Sync
          │                   │                 │
          ▼                   ▼                 ▼
      ┌────────┐         ┌────────┐        ┌────────┐
      │Presence│         │Cursors │        │  CRDT  │
      │  "3    │         │ Multi  │        │Conflict│
      │online" │         │ select │        │  free  │
      └────────┘         └────────┘        └────────┘
          │                   │                 │
       trivial            moderate           complex

      Where's your head at?
```

**User brings a specific problem:**
```
User: The auth system is a mess

You: [reads codebase]

     ┌─────────────────────────────────────────────┐
     │              CURRENT AUTH FLOW              │
     └─────────────────────────────────────────────┘
                        │
          ┌─────────────┼─────────────┐
          ▼             ▼             ▼
     ┌─────────┐  ┌─────────┐  ┌─────────┐
     │ Google  │  │  GitHub │  │  Email  │
     │  OAuth  │  │  OAuth  │  │  Magic  │
     └────┬────┘  └────┬────┘  └────┬────┘
          │             │             │
          └─────────────┼─────────────┘
                        ▼
                  ┌───────────┐
                  │  Session  │
                  └─────┬─────┘
                        │
                        ▼
                  ┌───────────┐
                  │   Perms   │
                  └───────────┘

     I see three tangles. Which one's burning?
```

**User is stuck mid-implementation:**
```
User: /opsx:explore add-auth-system
      The OAuth integration is more complex than expected

You: [reads change artifacts]

     You're on task 4: "Implement OAuth flow"

     Let me trace what's involved...

     [draws diagram, explores options, suggests paths]

     Want to update the design to reflect this?
     Or add a spike task to investigate?
```

**User wants to compare options:**
```
User: Should we use Postgres or SQLite?

You: Generic answer is boring. What's the context?

User: A CLI tool that tracks local dev environments

You: That changes everything.

     ┌─────────────────────────────────────────────────┐
     │         CLI TOOL DATA STORAGE                  │
     └─────────────────────────────────────────────────┘

     Key constraints:
     • No daemon running
     • Must work offline
     • Single user

                  SQLite          Postgres
     Deployment   embedded ✓      needs server ✗
     Offline      yes ✓           no ✗
     Single file  yes ✓           no ✗

     SQLite. Not even close.

     Unless... is there a sync component?
```

---

## Ending Discovery

There's no required ending. Discovery might:

- **Flow into a proposal**: "Ready to start? I can create a change proposal."
- **Result in artifact updates**: "Updated design.md with these decisions"
- **Just provide clarity**: User has what they need, moves on
- **Continue later**: "We can pick this up anytime"

When it feels like things are crystallizing, you might summarize:

```
## What We Figured Out

**The problem**: [crystallized understanding]

**The approach**: [if one emerged]

**Open questions**: [if any remain]

**Next steps** (if ready):
- Create a change proposal
- Keep exploring: just keep talking
```

But this summary is optional. Sometimes the thinking IS the value.

---

## Guardrails

- **Don't implement** - Never write code or implement features. Creating OpenSpec artifacts is fine, writing application code is not.
- **Don't fake understanding** - If something is unclear, dig deeper
- **Don't rush** - Discovery is thinking time, not task time
- **Don't force structure** - Let patterns emerge naturally
- **Don't auto-capture** - Offer to save insights, don't just do it
- **Do visualize** - A good diagram is worth many paragraphs
- **Do explore the codebase** - Ground discussions in reality
- **Do question assumptions** - Including the user's and your own


================================================
FILE: .codex/skills/openspec-propose/SKILL.md
================================================
---
name: openspec-propose
description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
license: MIT
compatibility: Requires openspec CLI.
metadata:
  author: openspec
  version: "1.0"
  generatedBy: "1.2.0"
---

Propose a new change - create the change and generate all artifacts in one step.

I'll create a change with artifacts:
- proposal.md (what & why)
- design.md (how)
- tasks.md (implementation steps)

When ready to implement, run /opsx:apply

---

**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.

**Steps**

1. **If no clear input provided, ask what they want to build**

   Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
   > "What change do you want to work on? Describe what you want to build or fix."

   From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).

   **IMPORTANT**: Do NOT proceed without understanding what the user wants to build.

2. **Create the change directory**
   ```bash
   openspec new change "<name>"
   ```
   This creates a scaffolded change at `openspec/changes/<name>/` with `.openspec.yaml`.

3. **Get the artifact build order**
   ```bash
   openspec status --change "<name>" --json
   ```
   Parse the JSON to get:
   - `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
   - `artifacts`: list of all artifacts with their status and dependencies

4. **Create artifacts in sequence until apply-ready**

   Use the **TodoWrite tool** to track progress through the artifacts.

   Loop through artifacts in dependency order (artifacts with no pending dependencies first):

   a. **For each artifact that is `ready` (dependencies satisfied)**:
      - Get instructions:
        ```bash
        openspec instructions <artifact-id> --change "<name>" --json
        ```
      - The instructions JSON includes:
        - `context`: Project background (constraints for you - do NOT include in output)
        - `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
        - `template`: The structure to use for your output file
        - `instruction`: Schema-specific guidance for this artifact type
        - `outputPath`: Where to write the artifact
        - `dependencies`: Completed artifacts to read for context
      - Read any completed dependency files for context
      - Create the artifact file using `template` as the structure
      - Apply `context` and `rules` as constraints - but do NOT copy them into the file
      - Show brief progress: "Created <artifact-id>"

   b. **Continue until all `applyRequires` artifacts are complete**
      - After creating each artifact, re-run `openspec status --change "<name>" --json`
      - Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
      - Stop when all `applyRequires` artifacts are done

   c. **If an artifact requires user input** (unclear context):
      - Use **AskUserQuestion tool** to clarify
      - Then continue with creation

5. **Show final status**
   ```bash
   openspec status --change "<name>"
   ```

**Output**

After completing all artifacts, summarize:
- Change name and location
- List of artifacts created with brief descriptions
- What's ready: "All artifacts created! Ready for implementation."
- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."

**Artifact Creation Guidelines**

- Follow the `instruction` field from `openspec instructions` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use `template` as the structure for your output file - fill in its sections
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
  - Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
  - These guide what you write, but should never appear in the output

**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
- Always read dependency artifacts before creating a new one
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
- If a change with that name already exists, ask if user wants to continue it or create a new one
- Verify each artifact file exists after writing before proceeding to next


================================================
FILE: .codex/skills/typst-grammar-authoring/SKILL.md
================================================
---
name: typst-grammar-authoring
description: Use when authoring or validating Typst documents from canonical grammar examples, especially when you need compile, HTML, or SVG-based validation workflows.
metadata:
  short-description: Author Typst docs from canonical grammar examples
  from-tutorial-rev: https://github.com/typst-doc-cn/tutorial/tree/971815a6b4898c0339b620e08c62824ec03bba7f
---

# Typst Grammar Authoring

Use this skill when the user wants help drafting, fixing, or validating Typst
documents. Everything needed for grammar lookup lives in this file so it can be
copied into another repository without sibling scripts or reference files.

## Workflow

1. Start with the grammar lookup section in this file and pick the closest
   existing pattern before inventing new syntax.
2. Copy the smallest matching example, then adapt it incrementally.
3. Run `typst compile` after each meaningful edit. Any non-zero exit code is a
   blocking failure.
4. After compile succeeds, use HTML output to inspect rendered text and
   document structure when wording or content ordering matters.
5. Use SVG output plus Playwright MCP when you need to inspect visual layout,
   spacing, numbering, line breaks, or emphasis.

## Validation

Compile validation:

```sh
typst compile --root . path/to/document.typ target/typst-grammar-authoring-check/document.pdf
```

Text validation through HTML:

```sh
typst compile --root . --features html path/to/document.typ target/typst-grammar-authoring-check/document.html
rg "expected text" target/typst-grammar-authoring-check/document.html
```

Visual validation through SVG:

```sh
typst compile --root . path/to/document.typ target/typst-grammar-authoring-check/document.svg
typst compile --root . path/to/document.typ target/typst-grammar-authoring-check/document-{0p}.svg
```

Playwright inspection:

- Use Playwright only after SVG generation succeeds.
- Open the SVG directly if the MCP server supports local files.
- Otherwise use a tiny local HTML wrapper that embeds the SVG, then capture a
  screenshot and inspect layout, spacing, numbering, line breaks, and emphasis.

## Guardrails

- Keep all skill-authored prose and instructions in English.
- Canonical syntax examples may retain non-English literals from their source
  examples.
- Do not treat Tinymist or editor diagnostics as the source of truth.
- Do not assume sibling updater scripts, reference files, or repo-local
  metadata exist when using this skill elsewhere.
- Use `{p}` or `{0p}` in multi-page SVG output paths.
- Treat HTML export as a validation aid, not a production contract.
- Keep command examples platform-neutral by using forward-slash or placeholder
  paths.

## Grammar Lookup

This section is embedded on purpose so the skill stays self-contained. Examples
are derived from the unofficial tutorial grammar samples and kept compact so the
lookup remains usable in a single file.

<!-- BEGIN GENERATED GRAMMAR LOOKUP -->

### Base Elements

- `paragraph`: `writing-markup`
- `heading`: `= Heading`; `== Heading`
- `strong`: `*Strong*`
- `emph`: `_emphasis_`; `*_emphasis_*`
- `list`:

```typ
+ List 1
+ List 2
```

- `continue-list`:

```typ
4. List 1
+ List 2
```

- `emum`:

```typ
- Enum 1
- Enum 2
```

- `mix-list-emum`:

```typ
- Enum 1
  + Item 1
- Enum 2
```

- `raw`:

```typ
`code`
```

- `long-raw`:

````typ
``` code```
````

- `lang-raw`:

````typ
```rs  trait World```
````

- `blocky-raw`:

````typ
```typ
= Heading
```
````

- `image`: `#image("/assets/files/香風とうふ店.jpg", width: 50pt)`
- `image-stretch`: `#image("/assets/files/香風とうふ店.jpg", width: 50pt, height: 50pt, fit: "stretch")`
- `image-inline`: `在一段话中插入一个#box(baseline: 0.15em, image("/assets/files/info-icon.svg", width: 1em))图片。`
- `figure`:

````typ
#figure(```typ
#image("/assets/files/香風とうふ店.jpg")
```, caption: [用于加载香風とうふ店送外卖的宝贵影像的代码])
````

- `link`: `#link("https://zh.wikipedia.org")[维基百科]`
- `http-link`: `https://zh.wikipedia.org`
- `internal-link`:

```typ
== 某个标题 <ref-internal-link>
#link(<ref-internal-link>)[链接到某个标题]
```

- `table`: `#table(columns: 2, [111], [2], [3])`
- `table-align`: `#table(columns: 2, align: center, [111], [2], [3])`
- `inline-math`: `$sum_x$`
- `display-math`: `$ sum_x $`
- `escape-sequences`: `>\_<`
- `unicode-escape-sequences`: `\u{9999}`
- `newline-by-space`: `A \ B`
- `newline`:

```typ
A \
B
```

- `shorthand`: `北京--上海`
- `shorthand-space`: `A~B`
- `inline-comment`: `// 行内注释`
- `cross-line-comment`:

```typ
/* 行间注释
  */
```

- `box`: `在一段话中插入一个#box(baseline: 0.15em, image("/assets/files/info-icon.svg", width: 1em))图片。`

### Text Styling

- `highlight`: `#highlight[高亮一段内容]`
- `underline`: `#underline[Language]`
- `underline-evade`:

```typ
#underline(
  evade: false)[ጿኈቼዽ]
```

- `overline`: `#overline[ጿኈቼዽ]`
- `strike`: `#strike[ጿኈቼዽ]`
- `subscript`: `威严满满#sub[抱头蹲防]`
- `superscript`: `香風とうふ店#super[TM]`
- `text-size`: `#text(size: 24pt)[一斤鸭梨]`
- `text-fill`: `#text(fill: blue)[蓝色鸭梨]`
- `text-font`: `#text(font: "Microsoft YaHei")[板正鸭梨]`

### Script Declarations

- `enter-script`: `#1`
- `code-block`: `#{"a"; "b"}`
- `content-block`: `#[内容块]`
- `none-literal`: `#none`
- `false-literal`: `#false`
- `true-literal`: `#true`
- `integer-literal`: `#(-1), #(0), #(1)`
- `n-adecimal-literal`: `#(-0xdeadbeef), #(-0o644), #(-0b1001)`
- `float-literal`: `#(0.001), #(.1), #(2.)`
- `exp-repr-float`: `#(1e2), #(1.926e3), #(-1e-3)`
- `string-literal`: `#"Hello world!!"`
- `str-escape-sequences`: `#"\""`
- `str-unicode-escape-sequences`: `#"\u{9999}"`
- `array-literal`: `#(1, "OvO", [一段内容])`
- `dict-literal`: `#(neko-mimi: 2, "utterance": "喵喵喵")`
- `empty-array`: `#()`
- `empty-dict`: `#(:)`
- `paren-empty-array`: `#(())`
- `single-member-array`: `#(1,)`
- `var-decl`: `#let x = 1`
- `func-decl`: `#let f(x) = x * 2`
- `closure`: `#let f = (x, y) => x + y`
- `named-param`: `#let g(named: none) = named`
- `variadic-param`: `#let g(..args) = args.pos().join([、])`
- `destruct-array`: `#let (one, hello-world) = (1, "Hello, World")`
- `destruct-array-eliminate`: `#let (_, second, ..) = (1, "Hello, World", []); #second`
- `destruct-dict`: `#let (neko-mimi: mimi) = (neko-mimi: 2); #mimi`
- `array-remapping`:

```typ
#let (a, b, c) = (1, 2, 3)
#let (b, c, a) = (a, b, c)
#a, #b, #c
```

- `array-swap`:

```typ
#let (a, b) = (1, 2)
#((a, b) = (b, a))
#a, #b
```

- `placeholder`:

```typ
#let last-two(t) = {
  let _ = t.pop()
  t.pop()
}
#last-two((1, 2, 3, 4))
```

### Script Statements

- `if`:

```typ
#if true { 1 },
#if false { 1 } else { 0 }
```

- `if-if`:

```typ
#if false { 0 } else if true { 1 },
#if false { 2 } else if false { 1 } else { 0 }
```

- `while`:

```typ
#{
  let i = 0;
  while i < 10 {
    (i * 2, )
    i += 1;
  }
}
```

- `for`:

```typ
#for i in range(10) {
  (i * 2, )
}
```

- `for-destruct`: `#for (特色, 这个) in (neko-mimi: 2) [猫猫的 #特色 是 #这个\ ]`
- `break`: `#for i in range(10) { (i, ); (i + 1926, ); break }`
- `continue`:

```typ
#for i in range(10) {
  if calc.even(i) { continue }
  (i, )
}
```

- `return`:

```typ
#let never(..args) = return
#type(never(1, 2))
```

- `include`: `#include "other-file.typ"`

### Script Styling

- `set`:

```typ
#set text(size: 24pt)
四斤鸭梨
```

- `scope`:

```typ
两只#[兔#set text(fill: rgb("#ffd1dc").darken(15%))
  #[兔白#set text(fill: orange)
  又白],真可爱
]
```

- `set-if`:

```typ
#let is-dark-theme = true
#set rect(fill: black) if is-dark-theme
#set text(fill: white) if is-dark-theme
#rect([wink!])
```

- `show-set`:

```typ
#show: set text(fill: blue)
wink!
```

- `show`:

````typ
#show raw: it => it.lines.at(1)
获取代码片段第二行内容:```typ
#{
set text(fill: true)
}
```
````

- `text-selector`:

```typ
#show "cpp": strong(emph(box("C++")))
在古代,cpp是一门常用语言。
```

- `regex-selector`:

```typ
#show regex("[”。]+"): it => {
  set text(font: "KaiTi")
  highlight(it, fill: yellow)
}
“无名,万物之始也;有名,万物之母也。”
```

- `label-selector`:

```typ
#show <一整段话>: set text(fill: blue)
#[$lambda$语言是世界上最好的语言。] <一整段话>

另一段话。
```

- `selector-exp`:

```typ
#show heading.where(level: 2): set text(fill: blue)
= 一级标题
== 二级标题
```

- `here`: `#context here().position()`
- `here-calc`: `#context [ 页码是偶数:#calc.even(here().page()) ]`
- `query`: `#context query(<ref-internal-link>).at(0).body`
- `state`: `#state("my-state", 1)`

### Script Expressions

- `func-call`: `#calc.pow(4, 3)`
- `content-param`: `#emph[emphasis]`
- `member-exp`:

```typ
#`OvO`.text
```

- `method-exp`: `#"Hello World".split(" ")`
- `dict-member-exp`:

```typ
#let cat = (neko-mimi: 2)
#cat.neko-mimi
```

- `content-member-exp`:

```typ
#`OvO`.text
```

- `repr`: `#repr[ 一段文本 ]`
- `type`: `#type[一段文本]`
- `eval`: `#type(eval("1"))`
- `eval-markup-mode`: `#eval("== 一个标题", mode: "markup")`
- `array-in`:

```typ
#let pol = (1, "OvO", [])
#(1 in pol)
```

- `array-not-in`:

```typ
#let pol = (1, "OvO", [])
#([另一段内容] not in pol)
```

- `dict-in`:

```typ
#let cat = (neko-mimi: 2)
#("neko-mimi" in cat)
```

- `logical-cmp-exp`:

```typ
#(1 < 0), #(1 >= 2),
#(1 == 2), #(1 != 2)
```

- `logical-calc-exp`: `#(not false), #(false or true), #(true and false)`
- `plus-exp`: `#(+1), #(+0), #(1), #(++1)`
- `minus-exp`:

```typ
#(-1), #(-0), #(--1),
#(-+-1)
```

- `arith-exp`:

```typ
#(1 + 1), #(1 + -1),
#(1 - 1), #(1 - -1)
```

- `assign-exp`: `#let a = 1; #repr(a = 10), #a, #repr(a += 2), #a`
- `string-concat-exp`: `#("a" + "b")`
- `string-mul-exp`: `#("a" * 4), #(4 * "ab")`
- `string-cmp-exp`: `#("a" == "b"), #("a" != "b"), #("a" < "ab"), #("a" >= "a")`
- `int-to-float`: `#float(1), #(type(float(1)))`
- `bool-to-int`: `#int(true), #(type(int(true)))`
- `float-to-int`: `#int(1), #(type(int(1)))`
- `dec-str-to-int`: `#int("1"), #(type(int("1")))`
- `nadec-str-to-int`:

```typ
#let safe-to-int(x) = {
  let res = eval(x)
  assert(type(res) == int, message: "should be integer")
  res
}
#safe-to-int("0xf"), #(type(safe-to-int("0xf"))) \
#safe-to-int("0o755"), #(type(safe-to-int("0o755"))) \
#safe-to-int("0b1011"), #(type(safe-to-int("0b1011"))) \
```

- `num-to-str`:

```typ
#repr(str(1)),
#repr(str(.5))
```

- `int-to-nadec-str`: `#str(501, base:16), #str(0xdeadbeef, base:36)`
- `bool-to-str`: `#repr(false)`
- `int-to-bool`:

```typ
#let to-bool(x) = x != 0
#repr(to-bool(0)),
#repr(to-bool(1))
```

<!-- END GENERATED GRAMMAR LOOKUP -->


================================================
FILE: .codex/skills/update-typst-grammar-authoring/SKILL.md
================================================
---
name: update-typst-grammar-authoring
description: Use when maintaining the portable typst-grammar-authoring skill from this repository's canonical Typst grammar source.
metadata:
  short-description: Regenerate the portable Typst grammar skill
---

# Update Typst Grammar Authoring

Use this skill when a maintainer needs to refresh the portable
`typst-grammar-authoring` skill after changing the canonical grammar examples in
`src/tutorial/reference-grammar.typ`.

## Inputs And Outputs

- Canonical source: `src/tutorial/reference-grammar.typ`
- Portable skill: `.codex/skills/typst-grammar-authoring/SKILL.md`
- Traceability artifact:
  `.codex/skills/update-typst-grammar-authoring/references/grammar-catalog.json`

## Workflow

1. Review the source edits in `src/tutorial/reference-grammar.typ` and confirm
   they are ready to publish into the portable skill.
2. Regenerate the portable skill body and traceability artifact:

   ```sh
   python .codex/skills/update-typst-grammar-authoring/scripts/generate_grammar_catalog.py
   ```

3. Review the generated diff for the portable skill and the traceability JSON:

   ```sh
   git diff -- .codex/skills/typst-grammar-authoring/SKILL.md .codex/skills/update-typst-grammar-authoring/references/grammar-catalog.json
   ```

4. Verify the portable skill stayed single-file:

   ```powershell
   Get-ChildItem -Force .codex/skills/typst-grammar-authoring
   ```

5. Verify the portable skill's command examples stayed platform-neutral and did
   not reintroduce Windows absolute paths:

   ```sh
   rg -n "[A-Za-z]:\\\\|path\\\\to|target\\\\typst-grammar-authoring-check|\\.codex\\\\skills|src\\\\tutorial" .codex/skills/typst-grammar-authoring/SKILL.md
   ```

6. If the regenerated lookup looks correct, keep the portable skill focused on
   author guidance only. Any exact source mapping belongs in the updater-owned
   traceability JSON, not in the portable `SKILL.md`.

## Guardrails

- Keep the distributed `typst-grammar-authoring` folder limited to `SKILL.md`.
- Treat `.codex/skills/update-typst-grammar-authoring/references/grammar-catalog.json`
  as the source-mapping artifact for maintainers.
- Keep maintenance-only commands, source-path references, and review steps in
  this updater skill rather than the portable one.
- If the generator output reveals a design issue in the portable skill, update
  the portable template first and rerun the generator before final review.


================================================
FILE: .codex/skills/update-typst-grammar-authoring/agents/openai.yaml
================================================
interface:
  display_name: "Update Typst Grammar Authoring"
  short_description: "Regenerate the portable Typst grammar skill"
  default_prompt: "Use $update-typst-grammar-authoring to refresh the portable Typst grammar skill and its traceability artifacts from src/tutorial/reference-grammar.typ."


================================================
FILE: .codex/skills/update-typst-grammar-authoring/references/grammar-catalog.json
================================================
{
  "source_path": "src/tutorial/reference-grammar.typ",
  "category_count": 6,
  "entry_count": 127,
  "categories": [
    {
      "id": "base-elements",
      "english_heading": "Base Elements",
      "source_heading": "基本元素",
      "source_anchor": "grammar-table:base-elements",
      "heading_line": 30,
      "entries": [
        {
          "lookup_key": "paragraph",
          "source_label": "段落",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-paragraph>)",
            "module": "writing-markup",
            "anchor": "grammar-paragraph"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 33,
            "entry_line_end": 39,
            "code_line_start": 37,
            "code_line_end": 37
          },
          "code": "writing-markup"
        },
        {
          "lookup_key": "heading",
          "source_label": "标题",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-heading>)",
            "module": "writing-markup",
            "anchor": "grammar-heading"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 40,
            "entry_line_end": 46,
            "code_line_start": 44,
            "code_line_end": 44
          },
          "code": "= Heading"
        },
        {
          "lookup_key": "heading",
          "source_label": "二级标题",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-heading>)",
            "module": "writing-markup",
            "anchor": "grammar-heading"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 47,
            "entry_line_end": 53,
            "code_line_start": 51,
            "code_line_end": 51
          },
          "code": "== Heading"
        },
        {
          "lookup_key": "strong",
          "source_label": "着重标记",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-strong>)",
            "module": "writing-markup",
            "anchor": "grammar-strong"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 54,
            "entry_line_end": 60,
            "code_line_start": 58,
            "code_line_end": 58
          },
          "code": "*Strong*"
        },
        {
          "lookup_key": "emph",
          "source_label": "强调标记",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-emph>)",
            "module": "writing-markup",
            "anchor": "grammar-emph"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 61,
            "entry_line_end": 67,
            "code_line_start": 65,
            "code_line_end": 65
          },
          "code": "_emphasis_"
        },
        {
          "lookup_key": "emph",
          "source_label": "着重且强调标记",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-emph>)",
            "module": "writing-markup",
            "anchor": "grammar-emph"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 68,
            "entry_line_end": 74,
            "code_line_start": 72,
            "code_line_end": 72
          },
          "code": "*_emphasis_*"
        },
        {
          "lookup_key": "list",
          "source_label": "有序列表",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-list>)",
            "module": "writing-markup",
            "anchor": "grammar-list"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 75,
            "entry_line_end": 82,
            "code_line_start": 79,
            "code_line_end": 80
          },
          "code": "+ List 1\n+ List 2"
        },
        {
          "lookup_key": "continue-list",
          "source_label": "有序列表(重新开始标号)",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-continue-list>)",
            "module": "writing-markup",
            "anchor": "grammar-continue-list"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 83,
            "entry_line_end": 90,
            "code_line_start": 87,
            "code_line_end": 88
          },
          "code": "4. List 1\n+ List 2"
        },
        {
          "lookup_key": "emum",
          "source_label": "无序列表",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-emum>)",
            "module": "writing-markup",
            "anchor": "grammar-emum"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 91,
            "entry_line_end": 98,
            "code_line_start": 95,
            "code_line_end": 96
          },
          "code": "- Enum 1\n- Enum 2"
        },
        {
          "lookup_key": "mix-list-emum",
          "source_label": "交替有序与无序列表",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-mix-list-emum>)",
            "module": "writing-markup",
            "anchor": "grammar-mix-list-emum"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 99,
            "entry_line_end": 107,
            "code_line_start": 103,
            "code_line_end": 105
          },
          "code": "- Enum 1\n  + Item 1\n- Enum 2"
        },
        {
          "lookup_key": "raw",
          "source_label": "短代码片段",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-raw>)",
            "module": "writing-markup",
            "anchor": "grammar-raw"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 108,
            "entry_line_end": 114,
            "code_line_start": 112,
            "code_line_end": 112
          },
          "code": "`code`"
        },
        {
          "lookup_key": "long-raw",
          "source_label": "长代码片段",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-long-raw>)",
            "module": "writing-markup",
            "anchor": "grammar-long-raw"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 115,
            "entry_line_end": 121,
            "code_line_start": 119,
            "code_line_end": 119
          },
          "code": "``` code```"
        },
        {
          "lookup_key": "lang-raw",
          "source_label": "语法高亮",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-lang-raw>)",
            "module": "writing-markup",
            "anchor": "grammar-lang-raw"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 122,
            "entry_line_end": 128,
            "code_line_start": 126,
            "code_line_end": 126
          },
          "code": "```rs  trait World```"
        },
        {
          "lookup_key": "blocky-raw",
          "source_label": "块代码片段",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-blocky-raw>)",
            "module": "writing-markup",
            "anchor": "grammar-blocky-raw"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 129,
            "entry_line_end": 137,
            "code_line_start": 133,
            "code_line_end": 135
          },
          "code": "```typ\n= Heading\n```"
        },
        {
          "lookup_key": "image",
          "source_label": "图像",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-image>)",
            "module": "writing-markup",
            "anchor": "grammar-image"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 138,
            "entry_line_end": 144,
            "code_line_start": 142,
            "code_line_end": 142
          },
          "code": "#image(\"/assets/files/香風とうふ店.jpg\", width: 50pt)"
        },
        {
          "lookup_key": "image-stretch",
          "source_label": "拉伸图像",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-image-stretch>)",
            "module": "writing-markup",
            "anchor": "grammar-image-stretch"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 145,
            "entry_line_end": 151,
            "code_line_start": 149,
            "code_line_end": 149
          },
          "code": "#image(\"/assets/files/香風とうふ店.jpg\", width: 50pt, height: 50pt, fit: \"stretch\")"
        },
        {
          "lookup_key": "image-inline",
          "source_label": "内联图像(盒子法)",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-image-inline>)",
            "module": "writing-markup",
            "anchor": "grammar-image-inline"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 152,
            "entry_line_end": 158,
            "code_line_start": 156,
            "code_line_end": 156
          },
          "code": "在一段话中插入一个#box(baseline: 0.15em, image(\"/assets/files/info-icon.svg\", width: 1em))图片。"
        },
        {
          "lookup_key": "figure",
          "source_label": "图像标题",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-figure>)",
            "module": "writing-markup",
            "anchor": "grammar-figure"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 159,
            "entry_line_end": 167,
            "code_line_start": 163,
            "code_line_end": 165
          },
          "code": "#figure(```typ\n#image(\"/assets/files/香風とうふ店.jpg\")\n```, caption: [用于加载香風とうふ店送外卖的宝贵影像的代码])"
        },
        {
          "lookup_key": "link",
          "source_label": "链接",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-link>)",
            "module": "writing-markup",
            "anchor": "grammar-link"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 168,
            "entry_line_end": 174,
            "code_line_start": 172,
            "code_line_end": 172
          },
          "code": "#link(\"https://zh.wikipedia.org\")[维基百科]"
        },
        {
          "lookup_key": "http-link",
          "source_label": "HTTP(S)链接",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-http-link>)",
            "module": "writing-markup",
            "anchor": "grammar-http-link"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 175,
            "entry_line_end": 181,
            "code_line_start": 179,
            "code_line_end": 179
          },
          "code": "https://zh.wikipedia.org"
        },
        {
          "lookup_key": "internal-link",
          "source_label": "内部链接",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-internal-link>)",
            "module": "writing-markup",
            "anchor": "grammar-internal-link"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 182,
            "entry_line_end": 189,
            "code_line_start": 186,
            "code_line_end": 187
          },
          "code": "== 某个标题 <ref-internal-link>\n#link(<ref-internal-link>)[链接到某个标题]"
        },
        {
          "lookup_key": "table",
          "source_label": "表格",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-table>)",
            "module": "writing-markup",
            "anchor": "grammar-table"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 190,
            "entry_line_end": 196,
            "code_line_start": 194,
            "code_line_end": 194
          },
          "code": "#table(columns: 2, [111], [2], [3])"
        },
        {
          "lookup_key": "table-align",
          "source_label": "对齐表格",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-table-align>)",
            "module": "writing-markup",
            "anchor": "grammar-table-align"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 197,
            "entry_line_end": 203,
            "code_line_start": 201,
            "code_line_end": 201
          },
          "code": "#table(columns: 2, align: center, [111], [2], [3])"
        },
        {
          "lookup_key": "inline-math",
          "source_label": "行内数学公式",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-inline-math>)",
            "module": "writing-markup",
            "anchor": "grammar-inline-math"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 204,
            "entry_line_end": 210,
            "code_line_start": 208,
            "code_line_end": 208
          },
          "code": "$sum_x$"
        },
        {
          "lookup_key": "display-math",
          "source_label": "行间数学公式",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-display-math>)",
            "module": "writing-markup",
            "anchor": "grammar-display-math"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 211,
            "entry_line_end": 217,
            "code_line_start": 215,
            "code_line_end": 215
          },
          "code": "$ sum_x $"
        },
        {
          "lookup_key": "escape-sequences",
          "source_label": "标记转义序列",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-escape-sequences>)",
            "module": "writing-markup",
            "anchor": "grammar-escape-sequences"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 218,
            "entry_line_end": 224,
            "code_line_start": 222,
            "code_line_end": 222
          },
          "code": ">\\_<"
        },
        {
          "lookup_key": "unicode-escape-sequences",
          "source_label": "标记的Unicode转义序列",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-unicode-escape-sequences>)",
            "module": "writing-markup",
            "anchor": "grammar-unicode-escape-sequences"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 225,
            "entry_line_end": 231,
            "code_line_start": 229,
            "code_line_end": 229
          },
          "code": "\\u{9999}"
        },
        {
          "lookup_key": "newline-by-space",
          "source_label": "换行符(转义序列)",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-newline-by-space>)",
            "module": "writing-markup",
            "anchor": "grammar-newline-by-space"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 232,
            "entry_line_end": 238,
            "code_line_start": 236,
            "code_line_end": 236
          },
          "code": "A \\ B"
        },
        {
          "lookup_key": "newline",
          "source_label": "换行符情形二",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-newline>)",
            "module": "writing-markup",
            "anchor": "grammar-newline"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 239,
            "entry_line_end": 246,
            "code_line_start": 243,
            "code_line_end": 244
          },
          "code": "A \\\nB"
        },
        {
          "lookup_key": "shorthand",
          "source_label": "速记符",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-shorthand>)",
            "module": "writing-markup",
            "anchor": "grammar-shorthand"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 247,
            "entry_line_end": 253,
            "code_line_start": 251,
            "code_line_end": 251
          },
          "code": "北京--上海"
        },
        {
          "lookup_key": "shorthand-space",
          "source_label": "空格(速记符)",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-shorthand-space>)",
            "module": "writing-markup",
            "anchor": "grammar-shorthand-space"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 254,
            "entry_line_end": 260,
            "code_line_start": 258,
            "code_line_end": 258
          },
          "code": "A~B"
        },
        {
          "lookup_key": "inline-comment",
          "source_label": "行内注释",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-inline-comment>)",
            "module": "writing-markup",
            "anchor": "grammar-inline-comment"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 261,
            "entry_line_end": 267,
            "code_line_start": 265,
            "code_line_end": 265
          },
          "code": "// 行内注释"
        },
        {
          "lookup_key": "cross-line-comment",
          "source_label": "行间注释",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-cross-line-comment>)",
            "module": "writing-markup",
            "anchor": "grammar-cross-line-comment"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 268,
            "entry_line_end": 275,
            "code_line_start": 272,
            "code_line_end": 273
          },
          "code": "/* 行间注释\n  */"
        },
        {
          "lookup_key": "box",
          "source_label": "行内盒子",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-box>)",
            "module": "writing-markup",
            "anchor": "grammar-box"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 276,
            "entry_line_end": 282,
            "code_line_start": 280,
            "code_line_end": 280
          },
          "code": "在一段话中插入一个#box(baseline: 0.15em, image(\"/assets/files/info-icon.svg\", width: 1em))图片。"
        }
      ]
    },
    {
      "id": "text-styling",
      "english_heading": "Text Styling",
      "source_heading": "修饰文本",
      "source_anchor": "grammar-table:text",
      "heading_line": 285,
      "entries": [
        {
          "lookup_key": "highlight",
          "source_label": "背景高亮",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-highlight>)",
            "module": "writing-markup",
            "anchor": "grammar-highlight"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 288,
            "entry_line_end": 294,
            "code_line_start": 292,
            "code_line_end": 292
          },
          "code": "#highlight[高亮一段内容]"
        },
        {
          "lookup_key": "underline",
          "source_label": "下划线",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-underline>)",
            "module": "writing-markup",
            "anchor": "grammar-underline"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 295,
            "entry_line_end": 301,
            "code_line_start": 299,
            "code_line_end": 299
          },
          "code": "#underline[Language]"
        },
        {
          "lookup_key": "underline-evade",
          "source_label": "无驱逐效果的下划线",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-underline-evade>)",
            "module": "writing-markup",
            "anchor": "grammar-underline-evade"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 302,
            "entry_line_end": 309,
            "code_line_start": 306,
            "code_line_end": 307
          },
          "code": "#underline(\n  evade: false)[ጿኈቼዽ]"
        },
        {
          "lookup_key": "overline",
          "source_label": "上划线",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-overline>)",
            "module": "writing-markup",
            "anchor": "grammar-overline"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 310,
            "entry_line_end": 316,
            "code_line_start": 314,
            "code_line_end": 314
          },
          "code": "#overline[ጿኈቼዽ]"
        },
        {
          "lookup_key": "strike",
          "source_label": "中划线(删除线)",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-strike>)",
            "module": "writing-markup",
            "anchor": "grammar-strike"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 317,
            "entry_line_end": 323,
            "code_line_start": 321,
            "code_line_end": 321
          },
          "code": "#strike[ጿኈቼዽ]"
        },
        {
          "lookup_key": "subscript",
          "source_label": "下标",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-subscript>)",
            "module": "writing-markup",
            "anchor": "grammar-subscript"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 324,
            "entry_line_end": 330,
            "code_line_start": 328,
            "code_line_end": 328
          },
          "code": "威严满满#sub[抱头蹲防]"
        },
        {
          "lookup_key": "superscript",
          "source_label": "上标",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-superscript>)",
            "module": "writing-markup",
            "anchor": "grammar-superscript"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 331,
            "entry_line_end": 337,
            "code_line_start": 335,
            "code_line_end": 335
          },
          "code": "香風とうふ店#super[TM]"
        },
        {
          "lookup_key": "text-size",
          "source_label": "设置文本大小",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-text-size>)",
            "module": "writing-markup",
            "anchor": "grammar-text-size"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 338,
            "entry_line_end": 344,
            "code_line_start": 342,
            "code_line_end": 342
          },
          "code": "#text(size: 24pt)[一斤鸭梨]"
        },
        {
          "lookup_key": "text-fill",
          "source_label": "设置文本颜色",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-text-fill>)",
            "module": "writing-markup",
            "anchor": "grammar-text-fill"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 345,
            "entry_line_end": 351,
            "code_line_start": 349,
            "code_line_end": 349
          },
          "code": "#text(fill: blue)[蓝色鸭梨]"
        },
        {
          "lookup_key": "text-font",
          "source_label": "设置字体",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-text-font>)",
            "module": "writing-markup",
            "anchor": "grammar-text-font"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 352,
            "entry_line_end": 358,
            "code_line_start": 356,
            "code_line_end": 356
          },
          "code": "#text(font: \"Microsoft YaHei\")[板正鸭梨]"
        }
      ]
    },
    {
      "id": "script-declarations",
      "english_heading": "Script Declarations",
      "source_heading": "脚本声明",
      "source_anchor": "grammar-table:decl",
      "heading_line": 361,
      "entries": [
        {
          "lookup_key": "enter-script",
          "source_label": "进入脚本模式",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-enter-script>)",
            "module": "writing-markup",
            "anchor": "grammar-enter-script"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 364,
            "entry_line_end": 370,
            "code_line_start": 368,
            "code_line_end": 368
          },
          "code": "#1"
        },
        {
          "lookup_key": "code-block",
          "source_label": "代码块",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-code-block>)",
            "module": "writing-markup",
            "anchor": "grammar-code-block"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 371,
            "entry_line_end": 377,
            "code_line_start": 375,
            "code_line_end": 375
          },
          "code": "#{\"a\"; \"b\"}"
        },
        {
          "lookup_key": "content-block",
          "source_label": "内容块",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-content-block>)",
            "module": "writing-markup",
            "anchor": "grammar-content-block"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 378,
            "entry_line_end": 384,
            "code_line_start": 382,
            "code_line_end": 382
          },
          "code": "#[内容块]"
        },
        {
          "lookup_key": "none-literal",
          "source_label": "空字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-none-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-none-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 385,
            "entry_line_end": 391,
            "code_line_start": 389,
            "code_line_end": 389
          },
          "code": "#none"
        },
        {
          "lookup_key": "false-literal",
          "source_label": "假(布尔值)",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-false-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-false-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 392,
            "entry_line_end": 398,
            "code_line_start": 396,
            "code_line_end": 396
          },
          "code": "#false"
        },
        {
          "lookup_key": "true-literal",
          "source_label": "真(布尔值)",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-true-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-true-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 399,
            "entry_line_end": 405,
            "code_line_start": 403,
            "code_line_end": 403
          },
          "code": "#true"
        },
        {
          "lookup_key": "integer-literal",
          "source_label": "整数字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-integer-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-integer-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 406,
            "entry_line_end": 412,
            "code_line_start": 410,
            "code_line_end": 410
          },
          "code": "#(-1), #(0), #(1)"
        },
        {
          "lookup_key": "n-adecimal-literal",
          "source_label": "进制数字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-n-adecimal-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-n-adecimal-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 413,
            "entry_line_end": 419,
            "code_line_start": 417,
            "code_line_end": 417
          },
          "code": "#(-0xdeadbeef), #(-0o644), #(-0b1001)"
        },
        {
          "lookup_key": "float-literal",
          "source_label": "浮点数字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-float-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-float-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 420,
            "entry_line_end": 426,
            "code_line_start": 424,
            "code_line_end": 424
          },
          "code": "#(0.001), #(.1), #(2.)"
        },
        {
          "lookup_key": "exp-repr-float",
          "source_label": "指数表示法",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-exp-repr-float>)",
            "module": "content-scope-style",
            "anchor": "grammar-exp-repr-float"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 427,
            "entry_line_end": 433,
            "code_line_start": 431,
            "code_line_end": 431
          },
          "code": "#(1e2), #(1.926e3), #(-1e-3)"
        },
        {
          "lookup_key": "string-literal",
          "source_label": "字符串字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-string-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-string-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 434,
            "entry_line_end": 440,
            "code_line_start": 438,
            "code_line_end": 438
          },
          "code": "#\"Hello world!!\""
        },
        {
          "lookup_key": "str-escape-sequences",
          "source_label": "字符串转义序列",
          "reference": {
            "expression": "refs.scripting-base.with(reference: <grammar-str-escape-sequences>)",
            "module": "scripting-base",
            "anchor": "grammar-str-escape-sequences"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 441,
            "entry_line_end": 447,
            "code_line_start": 445,
            "code_line_end": 445
          },
          "code": "#\"\\\"\""
        },
        {
          "lookup_key": "str-unicode-escape-sequences",
          "source_label": "字符串的Unicode转义序列",
          "reference": {
            "expression": "refs.scripting-base.with(reference: <grammar-str-unicode-escape-sequences>)",
            "module": "scripting-base",
            "anchor": "grammar-str-unicode-escape-sequences"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 448,
            "entry_line_end": 454,
            "code_line_start": 452,
            "code_line_end": 452
          },
          "code": "#\"\\u{9999}\""
        },
        {
          "lookup_key": "array-literal",
          "source_label": "数组字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-array-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-array-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 455,
            "entry_line_end": 461,
            "code_line_start": 459,
            "code_line_end": 459
          },
          "code": "#(1, \"OvO\", [一段内容])"
        },
        {
          "lookup_key": "dict-literal",
          "source_label": "字典字面量",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-dict-literal>)",
            "module": "content-scope-style",
            "anchor": "grammar-dict-literal"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 462,
            "entry_line_end": 468,
            "code_line_start": 466,
            "code_line_end": 466
          },
          "code": "#(neko-mimi: 2, \"utterance\": \"喵喵喵\")"
        },
        {
          "lookup_key": "empty-array",
          "source_label": "空数组",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-empty-array>)",
            "module": "content-scope-style",
            "anchor": "grammar-empty-array"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 469,
            "entry_line_end": 475,
            "code_line_start": 473,
            "code_line_end": 473
          },
          "code": "#()"
        },
        {
          "lookup_key": "empty-dict",
          "source_label": "空字典",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-empty-dict>)",
            "module": "content-scope-style",
            "anchor": "grammar-empty-dict"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 476,
            "entry_line_end": 482,
            "code_line_start": 480,
            "code_line_end": 480
          },
          "code": "#(:)"
        },
        {
          "lookup_key": "paren-empty-array",
          "source_label": "被括号包裹的空数组",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-paren-empty-array>)",
            "module": "content-scope-style",
            "anchor": "grammar-paren-empty-array"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 483,
            "entry_line_end": 489,
            "code_line_start": 487,
            "code_line_end": 487
          },
          "code": "#(())"
        },
        {
          "lookup_key": "single-member-array",
          "source_label": "含有一个元素的数组",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-single-member-array>)",
            "module": "content-scope-style",
            "anchor": "grammar-single-member-array"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 490,
            "entry_line_end": 496,
            "code_line_start": 494,
            "code_line_end": 494
          },
          "code": "#(1,)"
        },
        {
          "lookup_key": "var-decl",
          "source_label": "变量声明",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-var-decl>)",
            "module": "content-scope-style",
            "anchor": "grammar-var-decl"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 497,
            "entry_line_end": 503,
            "code_line_start": 501,
            "code_line_end": 501
          },
          "code": "#let x = 1"
        },
        {
          "lookup_key": "func-decl",
          "source_label": "函数声明",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-func-decl>)",
            "module": "content-scope-style",
            "anchor": "grammar-func-decl"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 504,
            "entry_line_end": 510,
            "code_line_start": 508,
            "code_line_end": 508
          },
          "code": "#let f(x) = x * 2"
        },
        {
          "lookup_key": "closure",
          "source_label": "函数闭包",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-closure>)",
            "module": "content-scope-style",
            "anchor": "grammar-closure"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 511,
            "entry_line_end": 517,
            "code_line_start": 515,
            "code_line_end": 515
          },
          "code": "#let f = (x, y) => x + y"
        },
        {
          "lookup_key": "named-param",
          "source_label": "具名参数声明",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-named-param>)",
            "module": "content-scope-style",
            "anchor": "grammar-named-param"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 518,
            "entry_line_end": 524,
            "code_line_start": 522,
            "code_line_end": 522
          },
          "code": "#let g(named: none) = named"
        },
        {
          "lookup_key": "variadic-param",
          "source_label": "含变参函数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-variadic-param>)",
            "module": "content-scope-style",
            "anchor": "grammar-variadic-param"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 525,
            "entry_line_end": 531,
            "code_line_start": 529,
            "code_line_end": 529
          },
          "code": "#let g(..args) = args.pos().join([、])"
        },
        {
          "lookup_key": "destruct-array",
          "source_label": "数组解构赋值",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-destruct-array>)",
            "module": "content-scope-style",
            "anchor": "grammar-destruct-array"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 532,
            "entry_line_end": 538,
            "code_line_start": 536,
            "code_line_end": 536
          },
          "code": "#let (one, hello-world) = (1, \"Hello, World\")"
        },
        {
          "lookup_key": "destruct-array-eliminate",
          "source_label": "数组解构赋值情形二",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-destruct-array-eliminate>)",
            "module": "content-scope-style",
            "anchor": "grammar-destruct-array-eliminate"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 539,
            "entry_line_end": 545,
            "code_line_start": 543,
            "code_line_end": 543
          },
          "code": "#let (_, second, ..) = (1, \"Hello, World\", []); #second"
        },
        {
          "lookup_key": "destruct-dict",
          "source_label": "字典解构赋值",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-destruct-dict>)",
            "module": "content-scope-style",
            "anchor": "grammar-destruct-dict"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 546,
            "entry_line_end": 552,
            "code_line_start": 550,
            "code_line_end": 550
          },
          "code": "#let (neko-mimi: mimi) = (neko-mimi: 2); #mimi"
        },
        {
          "lookup_key": "array-remapping",
          "source_label": "数组内容重映射",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-array-remapping>)",
            "module": "content-scope-style",
            "anchor": "grammar-array-remapping"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 553,
            "entry_line_end": 561,
            "code_line_start": 557,
            "code_line_end": 559
          },
          "code": "#let (a, b, c) = (1, 2, 3)\n#let (b, c, a) = (a, b, c)\n#a, #b, #c"
        },
        {
          "lookup_key": "array-swap",
          "source_label": "数组内容交换",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-array-swap>)",
            "module": "content-scope-style",
            "anchor": "grammar-array-swap"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 562,
            "entry_line_end": 570,
            "code_line_start": 566,
            "code_line_end": 568
          },
          "code": "#let (a, b) = (1, 2)\n#((a, b) = (b, a))\n#a, #b"
        },
        {
          "lookup_key": "placeholder",
          "source_label": "占位符(`let _ = ..`)",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-placeholder>)",
            "module": "content-scope-style",
            "anchor": "grammar-placeholder"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 571,
            "entry_line_end": 581,
            "code_line_start": 575,
            "code_line_end": 579
          },
          "code": "#let last-two(t) = {\n  let _ = t.pop()\n  t.pop()\n}\n#last-two((1, 2, 3, 4))"
        }
      ]
    },
    {
      "id": "script-statements",
      "english_heading": "Script Statements",
      "source_heading": "脚本语句",
      "source_anchor": null,
      "heading_line": 584,
      "entries": [
        {
          "lookup_key": "if",
          "source_label": "`if`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-if>)",
            "module": "content-scope-style",
            "anchor": "grammar-if"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 587,
            "entry_line_end": 594,
            "code_line_start": 591,
            "code_line_end": 592
          },
          "code": "#if true { 1 },\n#if false { 1 } else { 0 }"
        },
        {
          "lookup_key": "if-if",
          "source_label": "串联`if`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-if-if>)",
            "module": "content-scope-style",
            "anchor": "grammar-if-if"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 595,
            "entry_line_end": 602,
            "code_line_start": 599,
            "code_line_end": 600
          },
          "code": "#if false { 0 } else if true { 1 },\n#if false { 2 } else if false { 1 } else { 0 }"
        },
        {
          "lookup_key": "while",
          "source_label": "`while`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-while>)",
            "module": "content-scope-style",
            "anchor": "grammar-while"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 603,
            "entry_line_end": 615,
            "code_line_start": 607,
            "code_line_end": 613
          },
          "code": "#{\n  let i = 0;\n  while i < 10 {\n    (i * 2, )\n    i += 1;\n  }\n}"
        },
        {
          "lookup_key": "for",
          "source_label": "`for`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-for>)",
            "module": "content-scope-style",
            "anchor": "grammar-for"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 616,
            "entry_line_end": 624,
            "code_line_start": 620,
            "code_line_end": 622
          },
          "code": "#for i in range(10) {\n  (i * 2, )\n}"
        },
        {
          "lookup_key": "for-destruct",
          "source_label": "`for`语句解构赋值",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-for-destruct>)",
            "module": "content-scope-style",
            "anchor": "grammar-for-destruct"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 625,
            "entry_line_end": 631,
            "code_line_start": 629,
            "code_line_end": 629
          },
          "code": "#for (特色, 这个) in (neko-mimi: 2) [猫猫的 #特色 是 #这个\\ ]"
        },
        {
          "lookup_key": "break",
          "source_label": "`break`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-break>)",
            "module": "content-scope-style",
            "anchor": "grammar-break"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 632,
            "entry_line_end": 638,
            "code_line_start": 636,
            "code_line_end": 636
          },
          "code": "#for i in range(10) { (i, ); (i + 1926, ); break }"
        },
        {
          "lookup_key": "continue",
          "source_label": "`continue`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-continue>)",
            "module": "content-scope-style",
            "anchor": "grammar-continue"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 639,
            "entry_line_end": 648,
            "code_line_start": 643,
            "code_line_end": 646
          },
          "code": "#for i in range(10) {\n  if calc.even(i) { continue }\n  (i, )\n}"
        },
        {
          "lookup_key": "return",
          "source_label": "`return`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-return>)",
            "module": "content-scope-style",
            "anchor": "grammar-return"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 649,
            "entry_line_end": 656,
            "code_line_start": 653,
            "code_line_end": 654
          },
          "code": "#let never(..args) = return\n#type(never(1, 2))"
        },
        {
          "lookup_key": "include",
          "source_label": "`include`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-include>)",
            "module": "content-scope-style",
            "anchor": "grammar-include"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 657,
            "entry_line_end": 663,
            "code_line_start": 661,
            "code_line_end": 661
          },
          "code": "#include \"other-file.typ\""
        }
      ]
    },
    {
      "id": "script-styling",
      "english_heading": "Script Styling",
      "source_heading": "脚本样式",
      "source_anchor": null,
      "heading_line": 666,
      "entries": [
        {
          "lookup_key": "set",
          "source_label": "`set`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-set>)",
            "module": "content-scope-style",
            "anchor": "grammar-set"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 669,
            "entry_line_end": 676,
            "code_line_start": 673,
            "code_line_end": 674
          },
          "code": "#set text(size: 24pt)\n四斤鸭梨"
        },
        {
          "lookup_key": "scope",
          "source_label": "作用域",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-scope>)",
            "module": "content-scope-style",
            "anchor": "grammar-scope"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 677,
            "entry_line_end": 686,
            "code_line_start": 681,
            "code_line_end": 684
          },
          "code": "两只#[兔#set text(fill: rgb(\"#ffd1dc\").darken(15%))\n  #[兔白#set text(fill: orange)\n  又白],真可爱\n]"
        },
        {
          "lookup_key": "set-if",
          "source_label": "`set if`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-set-if>)",
            "module": "content-scope-style",
            "anchor": "grammar-set-if"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 687,
            "entry_line_end": 696,
            "code_line_start": 691,
            "code_line_end": 694
          },
          "code": "#let is-dark-theme = true\n#set rect(fill: black) if is-dark-theme\n#set text(fill: white) if is-dark-theme\n#rect([wink!])"
        },
        {
          "lookup_key": "show-set",
          "source_label": "`show set`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-show-set>)",
            "module": "content-scope-style",
            "anchor": "grammar-show-set"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 697,
            "entry_line_end": 704,
            "code_line_start": 701,
            "code_line_end": 702
          },
          "code": "#show: set text(fill: blue)\nwink!"
        },
        {
          "lookup_key": "show",
          "source_label": "`show`语句",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-show>)",
            "module": "content-scope-style",
            "anchor": "grammar-show"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 705,
            "entry_line_end": 716,
            "code_line_start": 709,
            "code_line_end": 714
          },
          "code": "#show raw: it => it.lines.at(1)\n获取代码片段第二行内容:```typ\n#{\nset text(fill: true)\n}\n```"
        },
        {
          "lookup_key": "text-selector",
          "source_label": "文本选择器",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-text-selector>)",
            "module": "content-scope-style",
            "anchor": "grammar-text-selector"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 717,
            "entry_line_end": 724,
            "code_line_start": 721,
            "code_line_end": 722
          },
          "code": "#show \"cpp\": strong(emph(box(\"C++\")))\n在古代,cpp是一门常用语言。"
        },
        {
          "lookup_key": "regex-selector",
          "source_label": "正则文本选择器",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-regex-selector>)",
            "module": "content-scope-style",
            "anchor": "grammar-regex-selector"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 725,
            "entry_line_end": 735,
            "code_line_start": 729,
            "code_line_end": 733
          },
          "code": "#show regex(\"[”。]+\"): it => {\n  set text(font: \"KaiTi\")\n  highlight(it, fill: yellow)\n}\n“无名,万物之始也;有名,万物之母也。”"
        },
        {
          "lookup_key": "label-selector",
          "source_label": "标签选择器",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-label-selector>)",
            "module": "content-scope-style",
            "anchor": "grammar-label-selector"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 736,
            "entry_line_end": 745,
            "code_line_start": 740,
            "code_line_end": 743
          },
          "code": "#show <一整段话>: set text(fill: blue)\n#[$lambda$语言是世界上最好的语言。] <一整段话>\n\n另一段话。"
        },
        {
          "lookup_key": "selector-exp",
          "source_label": "选择器表达式",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-selector-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-selector-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 746,
            "entry_line_end": 754,
            "code_line_start": 750,
            "code_line_end": 752
          },
          "code": "#show heading.where(level: 2): set text(fill: blue)\n= 一级标题\n== 二级标题"
        },
        {
          "lookup_key": "here",
          "source_label": "获取位置",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-here>)",
            "module": "content-scope-style",
            "anchor": "grammar-here"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 755,
            "entry_line_end": 761,
            "code_line_start": 759,
            "code_line_end": 759
          },
          "code": "#context here().position()"
        },
        {
          "lookup_key": "here-calc",
          "source_label": "检测当前页面是否为偶数页(位置相关计算)",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-here-calc>)",
            "module": "content-scope-style",
            "anchor": "grammar-here-calc"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 762,
            "entry_line_end": 768,
            "code_line_start": 766,
            "code_line_end": 766
          },
          "code": "#context [ 页码是偶数:#calc.even(here().page()) ]"
        },
        {
          "lookup_key": "query",
          "source_label": "查询文档内容",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-query>)",
            "module": "content-scope-style",
            "anchor": "grammar-query"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 769,
            "entry_line_end": 775,
            "code_line_start": 773,
            "code_line_end": 773
          },
          "code": "#context query(<ref-internal-link>).at(0).body"
        },
        {
          "lookup_key": "state",
          "source_label": "声明全局状态",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-state>)",
            "module": "content-scope-style",
            "anchor": "grammar-state"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 776,
            "entry_line_end": 782,
            "code_line_start": 780,
            "code_line_end": 780
          },
          "code": "#state(\"my-state\", 1)"
        }
      ]
    },
    {
      "id": "script-expressions",
      "english_heading": "Script Expressions",
      "source_heading": "脚本表达式",
      "source_anchor": null,
      "heading_line": 785,
      "entries": [
        {
          "lookup_key": "func-call",
          "source_label": "函数调用",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-func-call>)",
            "module": "writing-markup",
            "anchor": "grammar-func-call"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 788,
            "entry_line_end": 794,
            "code_line_start": 792,
            "code_line_end": 792
          },
          "code": "#calc.pow(4, 3)"
        },
        {
          "lookup_key": "content-param",
          "source_label": "函数调用传递内容参数",
          "reference": {
            "expression": "refs.writing-markup.with(reference: <grammar-content-param>)",
            "module": "writing-markup",
            "anchor": "grammar-content-param"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 795,
            "entry_line_end": 801,
            "code_line_start": 799,
            "code_line_end": 799
          },
          "code": "#emph[emphasis]"
        },
        {
          "lookup_key": "member-exp",
          "source_label": "成员访问",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-member-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-member-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 802,
            "entry_line_end": 808,
            "code_line_start": 806,
            "code_line_end": 806
          },
          "code": "#`OvO`.text"
        },
        {
          "lookup_key": "method-exp",
          "source_label": "方法调用",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-method-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-method-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 809,
            "entry_line_end": 815,
            "code_line_start": 813,
            "code_line_end": 813
          },
          "code": "#\"Hello World\".split(\" \")"
        },
        {
          "lookup_key": "dict-member-exp",
          "source_label": "字典成员访问",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-dict-member-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-dict-member-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 816,
            "entry_line_end": 823,
            "code_line_start": 820,
            "code_line_end": 821
          },
          "code": "#let cat = (neko-mimi: 2)\n#cat.neko-mimi"
        },
        {
          "lookup_key": "content-member-exp",
          "source_label": "内容成员访问",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-content-member-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-content-member-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 824,
            "entry_line_end": 830,
            "code_line_start": 828,
            "code_line_end": 828
          },
          "code": "#`OvO`.text"
        },
        {
          "lookup_key": "repr",
          "source_label": "代码表示的自省函数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-repr>)",
            "module": "content-scope-style",
            "anchor": "grammar-repr"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 831,
            "entry_line_end": 837,
            "code_line_start": 835,
            "code_line_end": 835
          },
          "code": "#repr[ 一段文本 ]"
        },
        {
          "lookup_key": "type",
          "source_label": "类型的自省函数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-type>)",
            "module": "content-scope-style",
            "anchor": "grammar-type"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 838,
            "entry_line_end": 844,
            "code_line_start": 842,
            "code_line_end": 842
          },
          "code": "#type[一段文本]"
        },
        {
          "lookup_key": "eval",
          "source_label": "求值函数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-eval>)",
            "module": "content-scope-style",
            "anchor": "grammar-eval"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 845,
            "entry_line_end": 851,
            "code_line_start": 849,
            "code_line_end": 849
          },
          "code": "#type(eval(\"1\"))"
        },
        {
          "lookup_key": "eval-markup-mode",
          "source_label": "求值函数(标记模式)",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-eval-markup-mode>)",
            "module": "content-scope-style",
            "anchor": "grammar-eval-markup-mode"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 852,
            "entry_line_end": 858,
            "code_line_start": 856,
            "code_line_end": 856
          },
          "code": "#eval(\"== 一个标题\", mode: \"markup\")"
        },
        {
          "lookup_key": "array-in",
          "source_label": "判断数组内容",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-array-in>)",
            "module": "content-scope-style",
            "anchor": "grammar-array-in"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 859,
            "entry_line_end": 866,
            "code_line_start": 863,
            "code_line_end": 864
          },
          "code": "#let pol = (1, \"OvO\", [])\n#(1 in pol)"
        },
        {
          "lookup_key": "array-not-in",
          "source_label": "判断数组内容不在",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-array-not-in>)",
            "module": "content-scope-style",
            "anchor": "grammar-array-not-in"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 867,
            "entry_line_end": 874,
            "code_line_start": 871,
            "code_line_end": 872
          },
          "code": "#let pol = (1, \"OvO\", [])\n#([另一段内容] not in pol)"
        },
        {
          "lookup_key": "dict-in",
          "source_label": "判断字典内容",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-dict-in>)",
            "module": "content-scope-style",
            "anchor": "grammar-dict-in"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 875,
            "entry_line_end": 882,
            "code_line_start": 879,
            "code_line_end": 880
          },
          "code": "#let cat = (neko-mimi: 2)\n#(\"neko-mimi\" in cat)"
        },
        {
          "lookup_key": "logical-cmp-exp",
          "source_label": "逻辑比较表达式",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-logical-cmp-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-logical-cmp-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 883,
            "entry_line_end": 890,
            "code_line_start": 887,
            "code_line_end": 888
          },
          "code": "#(1 < 0), #(1 >= 2),\n#(1 == 2), #(1 != 2)"
        },
        {
          "lookup_key": "logical-calc-exp",
          "source_label": "逻辑运算表达式",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-logical-calc-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-logical-calc-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 891,
            "entry_line_end": 897,
            "code_line_start": 895,
            "code_line_end": 895
          },
          "code": "#(not false), #(false or true), #(true and false)"
        },
        {
          "lookup_key": "plus-exp",
          "source_label": "取正运算",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-plus-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-plus-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 898,
            "entry_line_end": 904,
            "code_line_start": 902,
            "code_line_end": 902
          },
          "code": "#(+1), #(+0), #(1), #(++1)"
        },
        {
          "lookup_key": "minus-exp",
          "source_label": "取负运算",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-minus-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-minus-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 905,
            "entry_line_end": 912,
            "code_line_start": 909,
            "code_line_end": 910
          },
          "code": "#(-1), #(-0), #(--1),\n#(-+-1)"
        },
        {
          "lookup_key": "arith-exp",
          "source_label": "算术运算表达式",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-arith-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-arith-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 913,
            "entry_line_end": 920,
            "code_line_start": 917,
            "code_line_end": 918
          },
          "code": "#(1 + 1), #(1 + -1),\n#(1 - 1), #(1 - -1)"
        },
        {
          "lookup_key": "assign-exp",
          "source_label": "赋值表达式",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-assign-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-assign-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 921,
            "entry_line_end": 927,
            "code_line_start": 925,
            "code_line_end": 925
          },
          "code": "#let a = 1; #repr(a = 10), #a, #repr(a += 2), #a"
        },
        {
          "lookup_key": "string-concat-exp",
          "source_label": "字符串连接",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-string-concat-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-string-concat-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 928,
            "entry_line_end": 934,
            "code_line_start": 932,
            "code_line_end": 932
          },
          "code": "#(\"a\" + \"b\")"
        },
        {
          "lookup_key": "string-mul-exp",
          "source_label": "重复连接字符串",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-string-mul-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-string-mul-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 935,
            "entry_line_end": 941,
            "code_line_start": 939,
            "code_line_end": 939
          },
          "code": "#(\"a\" * 4), #(4 * \"ab\")"
        },
        {
          "lookup_key": "string-cmp-exp",
          "source_label": "字符串比较",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-string-cmp-exp>)",
            "module": "content-scope-style",
            "anchor": "grammar-string-cmp-exp"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 942,
            "entry_line_end": 948,
            "code_line_start": 946,
            "code_line_end": 946
          },
          "code": "#(\"a\" == \"b\"), #(\"a\" != \"b\"), #(\"a\" < \"ab\"), #(\"a\" >= \"a\")"
        },
        {
          "lookup_key": "int-to-float",
          "source_label": "整数转浮点数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-int-to-float>)",
            "module": "content-scope-style",
            "anchor": "grammar-int-to-float"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 949,
            "entry_line_end": 955,
            "code_line_start": 953,
            "code_line_end": 953
          },
          "code": "#float(1), #(type(float(1)))"
        },
        {
          "lookup_key": "bool-to-int",
          "source_label": "布尔值转整数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-bool-to-int>)",
            "module": "content-scope-style",
            "anchor": "grammar-bool-to-int"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 956,
            "entry_line_end": 962,
            "code_line_start": 960,
            "code_line_end": 960
          },
          "code": "#int(true), #(type(int(true)))"
        },
        {
          "lookup_key": "float-to-int",
          "source_label": "浮点数转整数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-float-to-int>)",
            "module": "content-scope-style",
            "anchor": "grammar-float-to-int"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 963,
            "entry_line_end": 969,
            "code_line_start": 967,
            "code_line_end": 967
          },
          "code": "#int(1), #(type(int(1)))"
        },
        {
          "lookup_key": "dec-str-to-int",
          "source_label": "十进制字符串转整数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-dec-str-to-int>)",
            "module": "content-scope-style",
            "anchor": "grammar-dec-str-to-int"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 970,
            "entry_line_end": 976,
            "code_line_start": 974,
            "code_line_end": 974
          },
          "code": "#int(\"1\"), #(type(int(\"1\")))"
        },
        {
          "lookup_key": "nadec-str-to-int",
          "source_label": "十六进制/八进制/二进制字符串转整数",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-nadec-str-to-int>)",
            "module": "content-scope-style",
            "anchor": "grammar-nadec-str-to-int"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 977,
            "entry_line_end": 990,
            "code_line_start": 981,
            "code_line_end": 988
          },
          "code": "#let safe-to-int(x) = {\n  let res = eval(x)\n  assert(type(res) == int, message: \"should be integer\")\n  res\n}\n#safe-to-int(\"0xf\"), #(type(safe-to-int(\"0xf\"))) \\\n#safe-to-int(\"0o755\"), #(type(safe-to-int(\"0o755\"))) \\\n#safe-to-int(\"0b1011\"), #(type(safe-to-int(\"0b1011\"))) \\"
        },
        {
          "lookup_key": "num-to-str",
          "source_label": "数字转字符串",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-num-to-str>)",
            "module": "content-scope-style",
            "anchor": "grammar-num-to-str"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 991,
            "entry_line_end": 998,
            "code_line_start": 995,
            "code_line_end": 996
          },
          "code": "#repr(str(1)),\n#repr(str(.5))"
        },
        {
          "lookup_key": "int-to-nadec-str",
          "source_label": "整数转十六进制字符串",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-int-to-nadec-str>)",
            "module": "content-scope-style",
            "anchor": "grammar-int-to-nadec-str"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 999,
            "entry_line_end": 1005,
            "code_line_start": 1003,
            "code_line_end": 1003
          },
          "code": "#str(501, base:16), #str(0xdeadbeef, base:36)"
        },
        {
          "lookup_key": "bool-to-str",
          "source_label": "布尔值转字符串",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-bool-to-str>)",
            "module": "content-scope-style",
            "anchor": "grammar-bool-to-str"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 1006,
            "entry_line_end": 1012,
            "code_line_start": 1010,
            "code_line_end": 1010
          },
          "code": "#repr(false)"
        },
        {
          "lookup_key": "int-to-bool",
          "source_label": "数字转布尔值",
          "reference": {
            "expression": "refs.content-scope-style.with(reference: <grammar-int-to-bool>)",
            "module": "content-scope-style",
            "anchor": "grammar-int-to-bool"
          },
          "source": {
            "path": "src/tutorial/reference-grammar.typ",
            "entry_line_start": 1013,
            "entry_line_end": 1021,
            "code_line_start": 1017,
            "code_line_end": 1019
          },
          "code": "#let to-bool(x) = x != 0\n#repr(to-bool(0)),\n#repr(to-bool(1))"
        }
      ]
    }
  ]
}


================================================
FILE: .codex/skills/update-typst-grammar-authoring/scripts/generate_grammar_catalog.py
================================================
#!/usr/bin/env python3
"""Generate Typst grammar data and sync it into the portable skill."""

from __future__ import annotations

import argparse
import json
import os
import re
import sys
import textwrap
from collections import OrderedDict
from pathlib import Path


CATEGORY_MAP = {
    "基本元素": {
        "id": "base-elements",
        "title": "Base Elements",
    },
    "修饰文本": {
        "id": "text-styling",
        "title": "Text Styling",
    },
    "脚本声明": {
        "id": "script-declarations",
        "title": "Script Declarations",
    },
    "脚本语句": {
        "id": "script-statements",
        "title": "Script Statements",
    },
    "脚本样式": {
        "id": "script-styling",
        "title": "Script Styling",
    },
    "脚本表达式": {
        "id": "script-expressions",
        "title": "Script Expressions",
    },
}

CATEGORY_PATTERN = re.compile(
    r"^==\s+分类:(?P<source_heading>.+?)(?:\s+<(?P<source_anchor>[^>]+)>)?\s*$",
    re.MULTILINE,
)

ENTRY_PATTERN = re.compile(
    r"""
    \(\s*\n
    \s*\[(?P<source_label>.*?)\],\s*\n
    \s*(?P<reference_expr>refs\.(?P<reference_module>[\w-]+)\.with\(reference:\s*<(?P<reference_anchor>[^>]+)>\)),\s*\n
    \s*`{3,4}typ\s*\n
    (?P<code>.*?)
    \n\s*`{3,4},\s*\n
    \s*\),
    """,
    re.DOTALL | re.VERBOSE,
)

GENERATED_BEGIN = "<!-- BEGIN GENERATED GRAMMAR LOOKUP -->"
GENERATED_END = "<!-- END GENERATED GRAMMAR LOOKUP -->"
INLINE_CODE_LIMIT = 88


def line_number(text: str, offset: int) -> int:
    return text.count("\n", 0, offset) + 1


def normalize_code(raw_code: str) -> str:
    return textwrap.dedent(raw_code).strip("\n")


def lookup_key(reference_anchor: str) -> str:
    prefix = "grammar-"
    if reference_anchor.startswith(prefix):
        return reference_anchor[len(prefix) :]
    return reference_anchor


def repo_relative(path: Path, repo_root: Path) -> str:
    try:
        return Path(os.path.relpath(path.resolve(), repo_root.resolve())).as_posix()
    except ValueError:
        return path.resolve().as_posix()


def parse_categories(
    source_text: str, source_path: Path, repo_root: Path
) -> list[dict]:
    categories = []
    category_matches = list(CATEGORY_PATTERN.finditer(source_text))
    if not category_matches:
        raise ValueError(f"No categories found in {source_path}")

    for index, match in enumerate(category_matches):
        section_start = match.end()
        section_end = (
            category_matches[index + 1].start()
            if index + 1 < len(category_matches)
            else len(source_text)
        )
        section_text = source_text[section_start:section_end]
        source_heading = match.group("source_heading")
        english_heading = CATEGORY_MAP.get(source_heading, {}).get(
            "title", source_heading
        )
        category_id = CATEGORY_MAP.get(source_heading, {}).get(
            "id",
            f"category-{index + 1}",
        )
        category = {
            "id": category_id,
            "english_heading": english_heading,
            "source_heading": source_heading,
            "source_anchor": match.group("source_anchor"),
            "heading_line": line_number(source_text, match.start()),
            "entries": [],
        }

        for entry_match in ENTRY_PATTERN.finditer(section_text):
            absolute_start = section_start + entry_match.start()
            absolute_end = section_start + entry_match.end()
            code_start = section_start + entry_match.start("code")
            code_end = section_start + entry_match.end("code")
            entry = {
                "lookup_key": lookup_key(entry_match.group("reference_anchor")),
                "source_label": entry_match.group("source_label").strip(),
                "reference": {
                    "expression": entry_match.group("reference_expr").strip(),
                    "module": entry_match.group("reference_module"),
                    "anchor": entry_match.group("reference_anchor"),
                },
                "source": {
                    "path": repo_relative(source_path, repo_root),
                    "entry_line_start": line_number(source_text, absolute_start),
                    "entry_line_end": line_number(source_text, absolute_end),
                    "code_line_start": line_number(source_text, code_start),
                    "code_line_end": line_number(source_text, code_end),
                },
                "code": normalize_code(entry_match.group("code")),
            }
            category["entries"].append(entry)

        if not category["entries"]:
            raise ValueError(
                f"No entries parsed for category '{source_heading}' in {source_path}"
            )

        categories.append(category)

    return categories


def build_catalog(source_path: Path, repo_root: Path) -> dict:
    source_text = source_path.read_text(encoding="utf-8")
    categories = parse_categories(source_text, source_path, repo_root)
    return {
        "source_path": repo_relative(source_path, repo_root),
        "category_count": len(categories),
        "entry_count": sum(len(category["entries"]) for category in categories),
        "categories": categories,
    }


def is_inline_safe(code: str) -> bool:
    return "\n" not in code and "`" not in code and len(code) <= INLINE_CODE_LIMIT


def grouped_entries(entries: list[dict]) -> list[dict]:
    groups: OrderedDict[str, list[str]] = OrderedDict()
    for entry in entries:
        groups.setdefault(entry["lookup_key"], [])
        if entry["code"] not in groups[entry["lookup_key"]]:
            groups[entry["lookup_key"]].append(entry["code"])
    return [
        {
            "lookup_key": lookup_key,
            "examples": examples,
        }
        for lookup_key, examples in groups.items()
    ]


def render_example_block(code: str) -> list[str]:
    return [
        "```typ",
        code,
        "```",
    ]


def render_skill_lookup(catalog: dict) -> str:
    lines: list[str] = []
    for category in catalog["categories"]:
        lines.extend(
            [
                f"### {category['english_heading']}",
                "",
            ]
        )
        for group in grouped_entries(category["entries"]):
            inline_examples = [
                code for code in group["examples"] if is_inline_safe(code)
            ]
            if len(inline_examples) == len(group["examples"]):
                joined = "; ".join(f"`{code}`" for code in inline_examples)
                lines.append(f"- `{group['lookup_key']}`: {joined}")
                continue

            lines.append(f"- `{group['lookup_key']}`:")
            lines.append("")
            for index, code in enumerate(group["examples"]):
                lines.extend(render_example_block(code))
                if index != len(group["examples"]) - 1:
                    lines.append("")
            lines.append("")

    while lines and not lines[-1]:
        lines.pop()
    return "\n".join(lines) + "\n"


def update_skill(skill_path: Path, generated_lookup: str) -> None:
    skill_text = skill_path.read_text(encoding="utf-8")
    pattern = re.compile(
        rf"{re.escape(GENERATED_BEGIN)}(?P<newline>\r?\n).*?{re.escape(GENERATED_END)}",
        re.DOTALL,
    )

    def _replacement(match: re.Match[str]) -> str:
        newline = match.group("newline")
        return f"{GENERATED_BEGIN}{newline}{generated_lookup}{GENERATED_END}"

    updated_text, count = pattern.subn(_replacement, skill_text, count=1)
    if count != 1:
        raise ValueError(f"Could not find generated section markers in {skill_path}")
    skill_path.write_text(updated_text, encoding="utf-8")


def write_outputs(
    catalog: dict,
    output_dir: Path,
    skill_path: Path,
) -> None:
    output_dir.mkdir(parents=True, exist_ok=True)
    json_path = output_dir / "grammar-catalog.json"
    json_path.write_text(
        json.dumps(catalog, indent=2, ensure_ascii=False) + "\n",
        encoding="utf-8",
    )
    update_skill(skill_path, render_skill_lookup(catalog))
    print(f"[OK] Wrote {json_path}")
    print(f"[OK] Updated {skill_path}")


def default_source(script_path: Path) -> Path:
    return script_path.parents[4] / "src" / "tutorial" / "reference-grammar.typ"


def default_skill_path(script_path: Path) -> Path:
    return script_path.parents[2] / "typst-grammar-authoring" / "SKILL.md"


def main() -> int:
    script_path = Path(__file__).resolve()
    parser = argparse.ArgumentParser(
        description="Generate Typst grammar data from reference-grammar.typ.",
    )
    parser.add_argument(
        "--source",
        type=Path,
        default=default_source(script_path),
        help="Path to src/tutorial/reference-grammar.typ",
    )
    parser.add_argument(
        "--output-dir",
        type=Path,
        default=script_path.parent.parent / "references",
        help="Directory for generated reference files",
    )
    parser.add_argument(
        "--skill-path",
        type=Path,
        default=default_skill_path(script_path),
        help="Path to the portable SKILL.md file to sync",
    )
    args = parser.parse_args()

    try:
        repo_root = script_path.parents[4]
        source_path = args.source.resolve()
        catalog = build_catalog(source_path, repo_root)
        write_outputs(
            catalog,
            args.output_dir.resolve(),
            args.skill_path.resolve(),
        )
    except Exception as exc:  # pragma: no cover - CLI error surface
        print(f"[ERROR] {exc}", file=sys.stderr)
        return 1

    return 0


if __name__ == "__main__":
    raise SystemExit(main())


================================================
FILE: .gitattributes
================================================
.zed/settings.json linguist-language=json5

================================================
FILE: .github/workflows/build.yml
================================================
name: tutorial::ci
on: push
jobs:
  render_pdf:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: typst-community/setup-typst@v3
      - run: git submodule update --init --recursive
      - name: Download & install shiroa
        run: |
          curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.3.1-rc2/shiroa-installer.sh | sh
      - name: Build Book
        run: |
          shiroa build --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ --path-to-root /tutorial/ -w . src
      - run: typst compile --root . --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ ./src/ebook.typ
      - uses: actions/upload-artifact@v4
        id: artifact-upload-step
        with:
          name: ebook
          path: src/ebook.pdf
      - run: echo 'Artifact URL is ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/${{ steps.artifact-upload-step.outputs.artifact-id }}'


================================================
FILE: .github/workflows/gh_pages.yml
================================================
name: tutorial::gh_pages
on:
  push:
    branches:
      - main
  workflow_dispatch:
    
permissions:
  pages: write
  id-token: write
  contents: read

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: 'pages'
  cancel-in-progress: false

jobs:
  build-gh-pages:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - run: git submodule update --init --recursive
      - name: Download font assets
        # use fonts in stable releases
        run: |
          mkdir -p assets/fonts/
          curl -L https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.1.2/font-assets.tar.gz | tar -xvz -C assets/fonts
      - name: Download & install shiroa
        run: |
          curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Myriad-Dreamin/shiroa/releases/download/v0.3.1-rc2/shiroa-installer.sh | sh
      - name: Build Book
        run: |
          shiroa build --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ --path-to-root /tutorial/ -w . src 
      - name: Setup Pages
        uses: actions/configure-pages@v5
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: "./dist"
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

================================================
FILE: .gitignore
================================================
dist/
target/
.DS_Store
src/*.pdf
.idea


================================================
FILE: .gitmodules
================================================
[submodule "assets/typst-fonts"]
	path = assets/typst-fonts
	url = https://github.com/typst-doc-cn/fonts
	branch = typst-v0.10.0
[submodule "assets/artifacts"]
	path = assets/artifacts
	url = https://github.com/typst-doc-cn/tutorial-artifacts
	branch = v0.1.0
[submodule "assets/fonts"]
	path = assets/fonts
	url = https://github.com/typst-doc-cn/fonts
	branch = tutorial-v0.1.0


================================================
FILE: .vscode/settings.json
================================================
{
  "tinymist.fontPaths": ["${workspaceFolder}/assets/fonts"],
  "tinymist.exportPdf": "onSave",
  "tinymist.outputPath": "$root/target/$dir/$name",
  "tinymist.formatterMode": "typstyle",
  "editor.pasteAs.preferences": [
    "typst.link.uri",
    "typst.link.image",
    "typst.link"
  ],
  "tinymist.preview.invertColors": "auto",
  "tinymist.lint.enabled": true,
  "tinymist.lint.when": "onSave",
  "[typst]": {
    "editor.inlayHints.enabled": "off"
  },
  "files.watcherExclude": {
    "**/target": true
  }
}


================================================
FILE: .zed/settings.json
================================================
// Folder-specific settings
//
// For a full list of overridable settings, and general information on folder-specific settings,
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{
  "lsp": {
    "tinymist": {
      "initialization_options": {
        "exportPdf": "onSave",
        "outputPath": "$root/target/typst/$name"
      }
    }
  }
}


================================================
FILE: Cargo.toml
================================================
[workspace.package]
description = "The Raindrop Book - Typst中文教程"
authors = ["Myriad-Dreamin <camiyoru@gmail.com>"]
version = "0.1.0"
edition = "2021"
readme = "README.md"
license = "Apache-2.0"
homepage = "https://github.com/typst-doc-cn/tutorial"
repository = "https://github.com/typst-doc-cn/tutorial"

[workspace]
resolver = "2"
members = ["crates/*"]

[workspace.dependencies]
typst = "0.13.1"
typst-svg = "0.13.1"

serde_json = "1"

reflexo-typst = { version = "0.6.0-rc1", default-features = false }

[profile.release]
# to satisfy stubber
lto = false       # Enable link-time optimization
strip = true      # Strip symbols from binary*
opt-level = 3     # Optimize for speed
codegen-units = 2 # Reduce number of codegen units to increase optimizations
panic = 'abort'   # Abort on panic

[patch.crates-io]
typst = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "typst.ts/v0.6.0-rc1" }
typst-library = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "typst.ts/v0.6.0-rc1" }
typst-syntax = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "typst.ts/v0.6.0-rc1" }
typst-utils = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "typst.ts/v0.6.0-rc1" }
typst-svg = { git = "https://github.com/Myriad-Dreamin/typst.git", tag = "typst.ts/v0.6.0-rc1" }
# reflexo-typst = { git = "https://github.com/Myriad-Dreamin/typst.ts", tag = "v0.5.5-rc7" }
# typst-ts-core = { path = "../../rust/typst.ts/core" }
# typst-ts-compiler = { path = "../../rust/typst.ts/compiler" }

[workspace.lints.rust]
missing_docs = "warn"

[workspace.lints.clippy]
uninlined_format_args = "warn"
missing_safety_doc = "warn"
undocumented_unsafe_blocks = "warn"


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# Tutorial

Typst 中文教程

[![下载最新版本](https://custom-icon-badges.demolab.com/badge/-Download-blue?style=for-the-badge&logo=download&logoColor=white "下载最新版本")](https://nightly.link/typst-doc-cn/tutorial/workflows/build/main/ebook.zip) **(latest 版本)**

[![下载最新版本](https://custom-icon-badges.demolab.com/badge/-Download-blue?style=for-the-badge&logo=download&logoColor=white "下载最新版本")](https://github.com/typst-doc-cn/tutorial/releases/download/v0.1.0/Typst.Tutorial.CN.v0.1.0.pdf) **(0.1.0 版本)**

## 安装字体

```bash
git submodule update --init --recursive
```

## 托管为静态网站

```bash
shiroa serve --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ -w . ./src/
```

## 编译为静态网站

```bash
shiroa build --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ -w . ./src/
```

## 编译电子书

```bash
typst compile --root . --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ ./src/ebook.typ
```

## 编译单独章节

选择一个章节文件,比如 `第一章.typ`,然后执行:

```bash
typst compile --root . --font-path ./assets/typst-fonts/ --font-path ./assets/fonts/ 章节文件.typ
```

## 复现 Artifacts

生成`typst-docs-v0.11.0.json`:

```bash
cargo install --git https://github.com/typst/typst --locked typst-docs --features="cli" --tag v0.11.0
typst-docs --out-file ./assets/artifacts/typst-docs-v0.11.0.json --assets-dir target/typst-docs/assets
```


================================================
FILE: _typos.toml
================================================
[default]
extend-ignore-identifiers-re = ["typ", "typc", "typm"]


================================================
FILE: assets/files/tokyo-night.tmTheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>name</key>
    <string>Tokyo Night</string>
    <key>settings</key>
    <array>
      <dict>
        <key>settings</key>
        <dict>
          <key>caret</key>
          <string>#c0caf5</string>
          <key>selection</key>
          <string>#515c7e4d</string>
          <key>lineHighlight</key>
          <string>#1e202e</string>
          <key>foreground</key>
          <string>#a9b1d6</string>
          <key>background</key>
          <string>#1a1b26</string>
          <key>invisibles</key>
          <string>#363b54</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Italics - Comments, Storage, Keyword Flow, Vue attributes, Decorators</string>
        <key>scope</key>
        <string>comment,meta.var.expr storage.type,keyword.control.flow,keyword.control.return,meta.directive.vue punctuation.separator.key-value.html,meta.directive.vue entity.other.attribute-name.html,tag.decorator.js entity.name.tag.js,tag.decorator.js punctuation.definition.tag.js,storage.modifier</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>italic</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Fix YAML block scalar</string>
        <key>scope</key>
        <string>keyword.control.flow.block-scalar.literal</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string/>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Comment</string>
        <key>scope</key>
        <string>comment,comment.block.documentation,punctuation.definition.comment,comment.block.documentation punctuation</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#444b6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Comment Doc</string>
        <key>scope</key>
        <string>keyword.operator.assignment.jsdoc,comment.block.documentation variable,comment.block.documentation storage,comment.block.documentation keyword,comment.block.documentation support,comment.block.documentation markup,comment.block.documentation markup.inline.raw.string.markdown,meta.other.type.phpdoc.php keyword.other.type.php,meta.other.type.phpdoc.php support.other.namespace.php,meta.other.type.phpdoc.php punctuation.separator.inheritance.php,meta.other.type.phpdoc.php support.class,keyword.other.phpdoc.php,log.date</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#5a638c</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Comment Doc Emphasized</string>
        <key>scope</key>
        <string>meta.other.type.phpdoc.php support.class,comment.block.documentation storage.type,comment.block.documentation punctuation.definition.block.tag,comment.block.documentation entity.name.type.instance</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#646e9c</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Number, Boolean, Undefined, Null</string>
        <key>scope</key>
        <string>variable.other.constant,punctuation.definition.constant,constant.language,constant.numeric,support.constant</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ff9e64</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>String, Symbols</string>
        <key>scope</key>
        <string>string,constant.other.symbol,constant.other.key,meta.attribute-selector</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string/>
          <key>foreground</key>
          <string>#9ece6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Colors</string>
        <key>scope</key>
        <string>constant.other.color,constant.other.color.rgb-value.hex punctuation.definition.constant</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9aa5ce</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Invalid</string>
        <key>scope</key>
        <string>invalid,invalid.illegal</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ff5370</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Invalid deprecated</string>
        <key>scope</key>
        <string>invalid.deprecated</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Storage Type</string>
        <key>scope</key>
        <string>storage.type</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Storage - modifier, var, const, let</string>
        <key>scope</key>
        <string>meta.var.expr storage.type,storage.modifier</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9d7cd8</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Interpolation, PHP tags, Smarty tags</string>
        <key>scope</key>
        <string>punctuation.definition.template-expression,punctuation.section.embedded,meta.embedded.line.tag.smarty,support.constant.handlebars,punctuation.section.tag.twig</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Blade, Twig, Smarty Handlebars keywords</string>
        <key>scope</key>
        <string>keyword.control.smarty,keyword.control.twig,support.constant.handlebars keyword.control,keyword.operator.comparison.twig,keyword.blade,entity.name.function.blade</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Spread</string>
        <key>scope</key>
        <string>keyword.operator.spread,keyword.operator.rest</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
          <key>fontStyle</key>
          <string>bold</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Operator, Misc</string>
        <key>scope</key>
        <string>keyword.operator,keyword.control.as,keyword.other,keyword.operator.bitwise.shift,punctuation,expression.embbeded.vue punctuation.definition.tag,text.html.twig meta.tag.inline.any.html,meta.tag.template.value.twig meta.function.arguments.twig,meta.directive.vue punctuation.separator.key-value.html,punctuation.definition.constant.markdown,punctuation.definition.string,punctuation.support.type.property-name,text.html.vue-html meta.tag,meta.attribute.directive,punctuation.definition.keyword,punctuation.terminator.rule,punctuation.definition.entity,punctuation.separator.inheritance.php,keyword.other.template,keyword.other.substitution,entity.name.operator,meta.property-list punctuation.separator.key-value,meta.at-rule.mixin punctuation.separator.key-value,meta.at-rule.function variable.parameter.url</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#89ddff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Import, Export, From, Default</string>
        <key>scope</key>
        <string>keyword.control.import,keyword.control.export,keyword.control.from,keyword.control.default,meta.import keyword.other</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Keyword</string>
        <key>scope</key>
        <string>keyword,keyword.control,keyword.other.important</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Keyword SQL</string>
        <key>scope</key>
        <string>keyword.other.DML</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Keyword Operator Logical, Arrow, Ternary, Comparison</string>
        <key>scope</key>
        <string>keyword.operator.logical,storage.type.function,keyword.operator.bitwise,keyword.operator.ternary,keyword.operator.comparison,keyword.operator.relational,keyword.operator.or.regexp</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Tag</string>
        <key>scope</key>
        <string>entity.name.tag</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Tag - Custom</string>
        <key>scope</key>
        <string>entity.name.tag support.class.component,meta.tag.custom entity.name.tag,meta.tag</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#de5971</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Tag Punctuation</string>
        <key>scope</key>
        <string>punctuation.definition.tag</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ba3c97</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Globals, PHP Constants, etc</string>
        <key>scope</key>
        <string>constant.other.php,variable.other.global.safer,variable.other.global.safer punctuation.definition.variable,variable.other.global,variable.other.global punctuation.definition.variable,constant.other</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#e0af68</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Variables</string>
        <key>scope</key>
        <string>variable,support.variable,string constant.other.placeholder,variable.parameter.handlebars,variable.other.object</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Variable Array Key</string>
        <key>scope</key>
        <string>meta.array.literal variable</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Object Key</string>
        <key>scope</key>
        <string>meta.object-literal.key,entity.name.type.hcl,string.alias.graphql,string.unquoted.graphql,string.unquoted.alias.graphql,meta.group.braces.curly constant.other.object.key.js string.unquoted.label.js,meta.field.declaration.ts variable.object.property,meta.block entity.name.label</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#73daca</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Object Property</string>
        <key>scope</key>
        <string>variable.other.property,support.variable.property,support.variable.property.dom,meta.function-call variable.other.object.property</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Object Property</string>
        <key>scope</key>
        <string>variable.other.object.property</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Object Literal Member lvl 3 (Vue Prop Validation)</string>
        <key>scope</key>
        <string>meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.objectliteral meta.object.member meta.object-literal.key</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#41a6b5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>C-related Block Level Variables</string>
        <key>scope</key>
        <string>source.cpp meta.block variable.other</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Other Variable</string>
        <key>scope</key>
        <string>support.other.variable</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Methods</string>
        <key>scope</key>
        <string>meta.class-method.js entity.name.function.js,entity.name.method.js,variable.function.constructor,keyword.other.special-method,storage.type.cs</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Function Definition</string>
        <key>scope</key>
        <string>entity.name.function,variable.other.enummember,meta.function-call,meta.function-call entity.name.function,variable.function,meta.definition.method entity.name.function,meta.object-literal entity.name.function</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Function Argument</string>
        <key>scope</key>
        <string>variable.parameter.function.language.special,variable.parameter,meta.function.parameters punctuation.definition.variable,meta.function.parameter variable</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#e0af68</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Constant, Tag Attribute</string>
        <key>scope</key>
        <string>keyword.other.type.php,storage.type.php,constant.character,constant.escape,keyword.other.unit</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Variable Definition</string>
        <key>scope</key>
        <string>meta.definition.variable variable.other.constant,meta.definition.variable variable.other.readwrite,variable.declaration.hcl variable.other.readwrite.hcl,meta.mapping.key.hcl variable.other.readwrite.hcl,variable.other.declaration</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Inherited Class</string>
        <key>scope</key>
        <string>entity.other.inherited-class</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string/>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Class, Support, DOM, etc</string>
        <key>scope</key>
        <string>support.class,support.type,variable.other.readwrite.alias,support.orther.namespace.use.php,meta.use.php,support.other.namespace.php,support.type.sys-types,support.variable.dom,support.constant.math,support.type.object.module,support.constant.json,entity.name.namespace,meta.import.qualifier,variable.other.constant.object</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Class Name</string>
        <key>scope</key>
        <string>entity.name</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Support Function</string>
        <key>scope</key>
        <string>support.function</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Class and Support</string>
        <key>scope</key>
        <string>source.css support.type.property-name,source.sass support.type.property-name,source.scss support.type.property-name,source.less support.type.property-name,source.stylus support.type.property-name,source.postcss support.type.property-name,support.type.property-name.css,support.type.vendored.property-name,support.type.map.key</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Font</string>
        <key>scope</key>
        <string>support.constant.font-name,meta.definition.variable</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9ece6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Class</string>
        <key>scope</key>
        <string>entity.other.attribute-name.class,meta.at-rule.mixin.scss entity.name.function.scss</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9ece6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS ID</string>
        <key>scope</key>
        <string>entity.other.attribute-name.id</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#fc7b7b</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Tag</string>
        <key>scope</key>
        <string>entity.name.tag.css</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Tag Reference, Pseudo &amp; Class Punctuation</string>
        <key>scope</key>
        <string>entity.other.attribute-name.pseudo-class punctuation.definition.entity,entity.other.attribute-name.pseudo-element punctuation.definition.entity,entity.other.attribute-name.class punctuation.definition.entity,entity.name.tag.reference</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#e0af68</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Punctuation</string>
        <key>scope</key>
        <string>meta.property-list</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9abdf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS at-rule fix</string>
        <key>scope</key>
        <string>meta.property-list meta.at-rule.if,meta.at-rule.return variable.parameter.url,meta.property-list meta.at-rule.else</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ff9e64</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Parent Selector Entity</string>
        <key>scope</key>
        <string>entity.other.attribute-name.parent-selector-suffix punctuation.definition.entity.css</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#73daca</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Punctuation comma fix</string>
        <key>scope</key>
        <string>meta.property-list meta.property-list</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9abdf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>SCSS @</string>
        <key>scope</key>
        <string>meta.at-rule.mixin keyword.control.at-rule.mixin,meta.at-rule.include entity.name.function.scss,meta.at-rule.include keyword.control.at-rule.include</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>SCSS Mixins, Extends, Include Keyword</string>
        <key>scope</key>
        <string>keyword.control.at-rule.include punctuation.definition.keyword,keyword.control.at-rule.mixin punctuation.definition.keyword,meta.at-rule.include keyword.control.at-rule.include,keyword.control.at-rule.extend punctuation.definition.keyword,meta.at-rule.extend keyword.control.at-rule.extend,entity.other.attribute-name.placeholder.css punctuation.definition.entity.css,meta.at-rule.media keyword.control.at-rule.media,meta.at-rule.mixin keyword.control.at-rule.mixin,meta.at-rule.function keyword.control.at-rule.function,keyword.control punctuation.definition.keyword</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9d7cd8</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>SCSS Include Mixin Argument</string>
        <key>scope</key>
        <string>meta.property-list meta.at-rule.include</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS value</string>
        <key>scope</key>
        <string>support.constant.property-value</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ff9e64</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Sub-methods</string>
        <key>scope</key>
        <string>entity.name.module.js,variable.import.parameter.js,variable.other.class.js</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Language methods</string>
        <key>scope</key>
        <string>variable.language</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Variable punctuation</string>
        <key>scope</key>
        <string>variable.other punctuation.definition.variable</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Keyword this with Punctuation, ES7 Bind Operator</string>
        <key>scope</key>
        <string>source.js constant.other.object.key.js string.unquoted.label.js,variable.language.this punctuation.definition.variable,keyword.other.this</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>HTML Attributes</string>
        <key>scope</key>
        <string>entity.other.attribute-name,text.html.basic entity.other.attribute-name.html,text.html.basic entity.other.attribute-name</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>HTML Character Entity</string>
        <key>scope</key>
        <string>text.html constant.character.entity</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0DB9D7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Vue (Vetur / deprecated) Template attributes</string>
        <key>scope</key>
        <string>entity.other.attribute-name.id.html,meta.directive.vue entity.other.attribute-name.html</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS ID's</string>
        <key>scope</key>
        <string>source.sass keyword.control</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS psuedo selectors</string>
        <key>scope</key>
        <string>entity.other.attribute-name.pseudo-class,entity.other.attribute-name.pseudo-element,entity.other.attribute-name.placeholder,meta.property-list meta.property-value</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Inserted</string>
        <key>scope</key>
        <string>markup.inserted</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#449dab</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Deleted</string>
        <key>scope</key>
        <string>markup.deleted</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#914c54</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Changed</string>
        <key>scope</key>
        <string>markup.changed</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#6183bb</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions</string>
        <key>scope</key>
        <string>string.regexp</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#b4f9f8</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions - Punctuation</string>
        <key>scope</key>
        <string>punctuation.definition.group</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions - Character Class</string>
        <key>scope</key>
        <string>constant.other.character-class.regexp</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions - Character Class Set</string>
        <key>scope</key>
        <string>constant.other.character-class.set.regexp,punctuation.definition.character-class.regexp</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#e0af68</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions - Quantifier</string>
        <key>scope</key>
        <string>keyword.operator.quantifier.regexp</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#89ddff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Regular Expressions - Backslash</string>
        <key>scope</key>
        <string>constant.character.escape.backslash</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Escape Characters</string>
        <key>scope</key>
        <string>constant.character.escape</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#89ddff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Decorators</string>
        <key>scope</key>
        <string>tag.decorator.js entity.name.tag.js,tag.decorator.js punctuation.definition.tag.js</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>CSS Units</string>
        <key>scope</key>
        <string>keyword.other.unit</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 0</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 1</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 2</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7dcfff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 3</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 4</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#e0af68</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 5</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 6</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#73daca</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 7</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>JSON Key - Level 8</string>
        <key>scope</key>
        <string>source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json support.type.property-name.json</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9ece6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Plain Punctuation</string>
        <key>scope</key>
        <string>punctuation.definition.list_item.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9abdf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Block Punctuation</string>
        <key>scope</key>
        <string>meta.block,meta.brace,punctuation.definition.block,punctuation.definition.use,punctuation.definition.class,punctuation.definition.begin.bracket,punctuation.definition.end.bracket,punctuation.definition.switch-expression.begin.bracket,punctuation.definition.switch-expression.end.bracket,punctuation.definition.section.switch-block.begin.bracket,punctuation.definition.section.switch-block.end.bracket,punctuation.definition.group.shell,punctuation.definition.parameters,punctuation.definition.arguments,punctuation.definition.dictionary,punctuation.definition.array,punctuation.section</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9abdf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Plain</string>
        <key>scope</key>
        <string>meta.jsx.children,meta.embedded.block</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>HTML text</string>
        <key>scope</key>
        <string>text.html,text.log</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#9aa5ce</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Markup Raw Inline</string>
        <key>scope</key>
        <string>text.html.markdown markup.inline.raw.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#bb9af7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Markup Raw Inline Punctuation</string>
        <key>scope</key>
        <string>text.html.markdown markup.inline.raw.markdown punctuation.definition.raw.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#4E5579</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 1</string>
        <key>scope</key>
        <string>heading.1.markdown entity.name,heading.1.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#89ddff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 2</string>
        <key>scope</key>
        <string>heading.2.markdown entity.name,heading.2.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#61bdf2</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 3</string>
        <key>scope</key>
        <string>heading.3.markdown entity.name,heading.3.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 4</string>
        <key>scope</key>
        <string>heading.4.markdown entity.name,heading.4.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#6d91de</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 5</string>
        <key>scope</key>
        <string>heading.5.markdown entity.name,heading.5.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#9aa5ce</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Heading 6</string>
        <key>scope</key>
        <string>heading.6.markdown entity.name,heading.6.markdown punctuation.definition.heading.markdown</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#747ca1</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Italic</string>
        <key>scope</key>
        <string>markup.italic,markup.italic punctuation</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>italic</string>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Bold</string>
        <key>scope</key>
        <string>markup.bold,markup.bold punctuation</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Bold-Italic</string>
        <key>scope</key>
        <string>markup.bold markup.italic,markup.bold markup.italic punctuation</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold italic</string>
          <key>foreground</key>
          <string>#c0caf5</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Underline</string>
        <key>scope</key>
        <string>markup.underline,markup.underline punctuation</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>underline</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Blockquote</string>
        <key>scope</key>
        <string>markup.quote punctuation.definition.blockquote.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#4e5579</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Quote</string>
        <key>scope</key>
        <string>markup.quote</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>italic</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Link</string>
        <key>scope</key>
        <string>string.other.link,markup.underline.link,constant.other.reference.link.markdown,string.other.link.description.title.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#73daca</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Fenced Code Block</string>
        <key>scope</key>
        <string>markup.fenced_code.block.markdown,markup.inline.raw.string.markdown,variable.language.fenced.markdown</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#89ddff</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markdown - Separator</string>
        <key>scope</key>
        <string>meta.separator</string>
        <key>settings</key>
        <dict>
          <key>fontStyle</key>
          <string>bold</string>
          <key>foreground</key>
          <string>#444b6a</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Markup - Table</string>
        <key>scope</key>
        <string>markup.table</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#c0cefc</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Token - Info</string>
        <key>scope</key>
        <string>token.info-token</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#0db9d7</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Token - Warn</string>
        <key>scope</key>
        <string>token.warn-token</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#ffdb69</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Token - Error</string>
        <key>scope</key>
        <string>token.error-token</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#db4b4b</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Token - Debug</string>
        <key>scope</key>
        <string>token.debug-token</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#b267e6</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Apache Tag</string>
        <key>scope</key>
        <string>entity.tag.apacheconf</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#f7768e</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>Preprocessor</string>
        <key>scope</key>
        <string>meta.preprocessor</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#73daca</string>
        </dict>
      </dict>
      <dict>
        <key>name</key>
        <string>ENV value</string>
        <key>scope</key>
        <string>source.env</string>
        <key>settings</key>
        <dict>
          <key>foreground</key>
          <string>#7aa2f7</string>
        </dict>
      </dict>
    </array>
  </dict>
</plist>


================================================
FILE: crates/embedded-typst/Cargo.toml
================================================
[package]
name = "embedded-typst"
description = "Run typst inside of typst"
authors.workspace = true
version.workspace = true
license.workspace = true
edition.workspace = true
homepage.workspace = true
repository.workspace = true

[lib]
crate-type = ["cdylib"]

[dependencies]
typst.workspace = true
typst-svg.workspace = true
reflexo-typst.workspace = true
serde_json.workspace = true
flate2 = "1"
tar = "0.4"

wasm-minimal-protocol = { git = "https://github.com/astrale-sharp/wasm-minimal-protocol", optional = true }

[features]
typst-plugin = ["wasm-minimal-protocol"]

default = ["typst-plugin"]

[lints]
workspace = true


================================================
FILE: crates/embedded-typst/src/lib.rs
================================================
//! This is a WASM wrapper of the embedded Typst.

#![cfg_attr(feature = "typst-plugin", allow(missing_docs))]

use std::{
    collections::HashMap,
    io::Read,
    path::{Path, PathBuf},
    str::FromStr,
    sync::{Arc, Mutex, RwLock},
    vec,
};

use reflexo_typst::{
    font::{pure::MemoryFontSearcher, FontResolverImpl},
    package::{PackageRegistry, PackageSpec, RegistryPathMapper},
    typst::prelude::EcoVec,
    vfs::{dummy::DummyAccessModel, FileSnapshot},
    CompilerUniverse, EntryReader, EntryState, ShadowApi, TaskInputs, TypstDocument,
    TypstPagedDocument,
};
use typst::{
    diag::{eco_format, FileResult, PackageError},
    foundations::Bytes,
    Features,
};

use wasm_minimal_protocol::*;
initiate_protocol!();

type StrResult<T> = Result<T, String>;

/// Allocates a data reference, return the key of the data reference.
///
/// # Panics
///
/// Panics if the world is not initialized.
///
/// # Errors
///
/// Error if there is an error
#[cfg_attr(feature = "typst-plugin", wasm_func)]
pub fn allocate_data(kind: &[u8], data: &[u8]) -> StrResult<Vec<u8>> {
    allocate_data_inner(kind, data, None)
}

/// Allocates a file reference, return the key of the data reference.
///
/// # Panics
///
/// Panics if the world is not initialized.
///
/// # Errors
///
/// Error if there is an error
#[cfg_attr(feature = "typst-plugin", wasm_func)]
pub fn allocate_file(kind: &[u8], path: &[u8], data: &[u8]) -> StrResult<Vec<u8>> {
    allocate_data_inner(kind, data, Some(path))
}

/// Allocates a data reference
fn allocate_data_inner(kind: &[u8], data: &[u8], path: Option<&[u8]>) -> StrResult<Vec<u8>> {
    let kind = std::str::from_utf8(kind).map_err(|e| e.to_string())?;
    let data = ImmutBytes(Bytes::new(data.to_owned()));

    let data_ref = match kind {
        "font" => DataRef::Font { data: Some(data) },
        "package" => {
            let path = std::str::from_utf8(path.unwrap()).map_err(|e| e.to_string())?;
            DataRef::Package {
                spec: path.to_string(),
                data: Some(data),
            }
        }
        "file" => {
            let path = std::str::from_utf8(path.unwrap()).map_err(|e| e.to_string())?;
            DataRef::File {
                path: path.to_owned(),
                data: Some(data),
            }
        }
        _ => return Err(format!("Unknown data kind: {kind}")),
    };

    let mut data = DATA.lock().unwrap();

    data.data.push(data_ref);

    Ok(vec![0])
}

/// A context that is used to resolve a world context.
pub struct Context {
    /// The data that are used in the main file.
    data: Vec<DataRef>,
}

static DATA: Mutex<Context> = Mutex::new(Context { data: vec![] });

/// A bytes object that is cheap to clone.
#[derive(Clone)]
struct ImmutBytes(Bytes);

/// A data reference in global data storage.
#[derive(Clone)]
enum DataRef {
    Font {
        data: Option<ImmutBytes>,
    },
    Package {
        spec: String,
        data: Option<ImmutBytes>,
    },
    File {
        path: String,
        data: Option<ImmutBytes>,
    },
}

impl DataRef {
    /// Gets the data of the object.
    pub fn data(&self) -> Option<&ImmutBytes> {
        match self {
            Self::Font { data, .. } => data.as_ref(),
            Self::Package { data, .. } => data.as_ref(),
            Self::File { data, .. } => data.as_ref(),
        }
    }
}

static VERSE: RwLock<Option<WorldRepr>> = RwLock::new(None);

/// Resolves a world
#[cfg_attr(feature = "typst-plugin", wasm_func)]
pub fn resolve_world() -> StrResult<Vec<u8>> {
    let resolved = create_world()?;
    let mut world = VERSE.write().unwrap();
    if world.is_some() {
        return Err("World is already initialized".to_string());
    }

    *world = Some(resolved);

    Ok(vec![])
}

/// Creates a world
fn create_world() -> StrResult<WorldRepr> {
    /// Extracts a package.
    fn extract_package(
        data: &[u8],
        mut cb: impl FnMut(String, &[u8], u64) -> StrResult<()>,
    ) -> StrResult<()> {
        let decompressed = flate2::read::GzDecoder::new(data);
        let mut reader = tar::Archive::new(decompressed);
        let entries = reader.entries();
        let entries = entries.map_err(|err| {
            let t = PackageError::MalformedArchive(Some(eco_format!("{err}")));
            format!("{t:?}",)
        })?;

        let mut buf = Vec::with_capacity(1024);
        for entry in entries {
            // Read single entry
            let mut entry = entry.map_err(|e| e.to_string())?;
            let header = entry.header();

            let is_file = header.entry_type().is_file();
            if !is_file {
                continue;
            }

            let mtime = header.mtime().unwrap_or(0);

            let path = header.path().map_err(|e| e.to_string())?;
            let path = path.to_string_lossy().as_ref().to_owned();

            let size = header.size().map_err(|e| e.to_string())?;
            buf.clear();
            buf.reserve(size as usize);
            entry.read_to_end(&mut buf).map_err(|e| e.to_string())?;

            cb(path, &buf, mtime)?
        }

        Ok(())
    }

    /// Creates a world based on the context.
    fn resolve_world_inner() -> StrResult<WorldRepr> {
        let data_guard = DATA.lock().unwrap();

        // Adds embedded fonts.
        let mut fb = MemoryFontSearcher::new();
        let mut pb = MemoryRegistry::default();

        for data in &data_guard.data {
            match data {
                DataRef::Font { data, .. } => {
                    fb.add_memory_font(data.clone().unwrap().0);
                }
                DataRef::Package { spec, .. } => {
                    let spec = PackageSpec::from_str(spec).map_err(|e| e.to_string())?;
                    pb.add_memory_package(spec);
                }
                DataRef::File { .. } => {}
            }
        }

        let registry = Arc::new(pb);
        let resolver = Arc::new(RegistryPathMapper::new(registry.clone()));
        let mut vfs = reflexo_typst::vfs::Vfs::new(resolver, DummyAccessModel);

        for data in &data_guard.data {
            match data {
                DataRef::Package { data, spec, .. } => {
                    let spec = PackageSpec::from_str(spec).map_err(|e| e.to_string())?;
                    let path = registry.resolve(&spec).map_err(|e| e.to_string())?;

                    let data = data.clone().unwrap().0;
                    extract_package(&data, |key, value, _mtime| {
                        vfs.revise()
                            .map_shadow(
                                &path.join(key.as_str()),
                                FileSnapshot::from(FileResult::Ok(Bytes::new(value.to_owned()))),
                            )
                            .map_err(|e| e.to_string())
                    })?;
                }
                DataRef::Font { .. } | DataRef::File { .. } => {}
            }
        }

        for data in EMBEDDED_FONT {
            fb.add_memory_font(Bytes::new(data));
        }

        // Creates a world.
        let world = WorldRepr::new_raw(
            EntryState::new_workspace(PathBuf::from("/").into()),
            Features::default(),
            None,
            vfs,
            registry,
            Arc::new(fb.build()),
        );

        Ok(world)
    }

    // Removes files from the context as they are not used for resolving a world.
    let mut files = Vec::new();
    let _ = &DATA.lock().unwrap().data.retain(|f| match f {
        DataRef::File { .. } => {
            files.push(f.clone());
            false
        }
        _ => true,
    });
    let mut world = resolve_world_inner()?;

    for f in files.into_iter() {
        let path = match &f {
            DataRef::File { path, .. } => path,
            _ => unreachable!(),
        };
        let path = Path::new(path);
        let data = f.data().cloned().unwrap().0;
        world.map_shadow(path, data).map_err(|e| e.to_string())?;
    }
    Ok(world)
}

/// Compile a typst file to svg.
///
/// # Panics
///
/// Panics if the world is not initialized.
///
/// # Errors
///
/// Error if there is an error
#[cfg_attr(feature = "typst-plugin", wasm_func)]
pub fn svg(input: &[u8]) -> StrResult<Vec<u8>> {
    let verse = VERSE.read().unwrap();
    let Some(verse) = verse.as_ref() else {
        return Err("World is not initialized".to_string());
    };

  
Download .txt
gitextract_r5ef022r/

├── .codex/
│   └── skills/
│       ├── openspec-apply-change/
│       │   └── SKILL.md
│       ├── openspec-archive-change/
│       │   └── SKILL.md
│       ├── openspec-explore/
│       │   └── SKILL.md
│       ├── openspec-propose/
│       │   └── SKILL.md
│       ├── typst-grammar-authoring/
│       │   └── SKILL.md
│       └── update-typst-grammar-authoring/
│           ├── SKILL.md
│           ├── agents/
│           │   └── openai.yaml
│           ├── references/
│           │   └── grammar-catalog.json
│           └── scripts/
│               └── generate_grammar_catalog.py
├── .gitattributes
├── .github/
│   └── workflows/
│       ├── build.yml
│       └── gh_pages.yml
├── .gitignore
├── .gitmodules
├── .vscode/
│   └── settings.json
├── .zed/
│   └── settings.json
├── Cargo.toml
├── LICENSE
├── README.md
├── _typos.toml
├── assets/
│   └── files/
│       └── tokyo-night.tmTheme
├── crates/
│   └── embedded-typst/
│       ├── Cargo.toml
│       └── src/
│           └── lib.rs
├── meta.json
├── openspec/
│   ├── changes/
│   │   └── archive/
│   │       └── 2026-03-15-create-english-typst-grammar-skill/
│   │           ├── .openspec.yaml
│   │           ├── design.md
│   │           ├── proposal.md
│   │           ├── specs/
│   │           │   └── typst-document-authoring-skill/
│   │           │       └── spec.md
│   │           └── tasks.md
│   ├── config.yaml
│   └── specs/
│       └── typst-document-authoring-skill/
│           └── spec.md
├── scripts/
│   ├── build.ps1
│   └── build.sh
├── src/
│   ├── book.typ
│   ├── ebook.typ
│   ├── figures.typ
│   ├── graph/
│   │   ├── digraph.typ
│   │   ├── electronics.typ
│   │   ├── mod.typ
│   │   ├── solid-geometry.typ
│   │   ├── state-machine.typ
│   │   ├── statistics.typ
│   │   └── table.typ
│   ├── intermediate/
│   │   └── mod.typ
│   ├── introduction.typ
│   ├── misc/
│   │   ├── code-syntax.typ
│   │   ├── code-theme.typ
│   │   ├── font-setting.typ
│   │   ├── mod.typ
│   │   └── text-processing.typ
│   ├── mod.typ
│   ├── prefaces/
│   │   ├── acknowledgement.typ
│   │   ├── license.typ
│   │   └── mod.typ
│   ├── science/
│   │   ├── algorithm.typ
│   │   ├── chemical.typ
│   │   ├── mod.typ
│   │   └── theorem.typ
│   ├── template/
│   │   ├── book.typ
│   │   ├── mod.typ
│   │   ├── paper.typ
│   │   └── slides.typ
│   ├── topics/
│   │   ├── call-externals.typ
│   │   ├── mod.typ
│   │   ├── template-book.typ
│   │   ├── template-cv.typ
│   │   ├── template-paper.typ
│   │   ├── writing-component-lib.typ
│   │   ├── writing-math.typ
│   │   └── writing-plugin-lib.typ
│   └── tutorial/
│       ├── doc-modulize.typ
│       ├── doc-stateful.typ
│       ├── figure-time-travel.typ
│       ├── latex-look.typ
│       ├── mod.typ
│       ├── other-file.typ
│       ├── packages/
│       │   └── m1.typ
│       ├── reference-bibliography.typ
│       ├── reference-calculation.typ
│       ├── reference-color.typ
│       ├── reference-counter-state.typ
│       ├── reference-data-process.typ
│       ├── reference-date.typ
│       ├── reference-grammar.typ
│       ├── reference-layout.typ
│       ├── reference-length.typ
│       ├── reference-math-mode.typ
│       ├── reference-math-symbols.typ
│       ├── reference-outline.typ
│       ├── reference-syntax-analysis.typ
│       ├── reference-table.typ
│       ├── reference-type-builtin.typ
│       ├── reference-typebase.typ
│       ├── reference-utils.typ
│       ├── reference-visualization.typ
│       ├── reference-wasm-plugin.typ
│       ├── scripting-block-and-expression.typ
│       ├── scripting-color.typ
│       ├── scripting-composite.typ
│       ├── scripting-content.typ
│       ├── scripting-control-flow.typ
│       ├── scripting-layout.typ
│       ├── scripting-literal.typ
│       ├── scripting-main.typ
│       ├── scripting-shape.typ
│       ├── scripting-style.typ
│       ├── scripting-variable.typ
│       ├── stateful/
│       │   ├── q0.typ
│       │   ├── q1.typ
│       │   ├── s1.typ
│       │   ├── s2.typ
│       │   └── s3.typ
│       ├── stateful-v0.12.0/
│       │   ├── q0.typ
│       │   ├── q1.typ
│       │   ├── s1.typ
│       │   ├── s2.typ
│       │   └── s3.typ
│       ├── writing-chinese.typ
│       ├── writing-markup.typ
│       ├── writing-math.typ
│       ├── writing-scripting.typ
│       └── writing.typ
└── typ/
    ├── book/
    │   ├── lib.typ
    │   ├── typst.toml
    │   └── variables.typ
    ├── embedded-typst/
    │   ├── example.typ
    │   └── lib.typ
    ├── templates/
    │   ├── ebook.typ
    │   ├── page.typ
    │   ├── side-notes.typ
    │   ├── template-link.typ
    │   ├── term.typ
    │   └── theme-style.toml
    └── typst-meta/
        └── docs.typ
Download .txt
SYMBOL INDEX (38 symbols across 2 files)

FILE: .codex/skills/update-typst-grammar-authoring/scripts/generate_grammar_catalog.py
  function line_number (line 66) | def line_number(text: str, offset: int) -> int:
  function normalize_code (line 70) | def normalize_code(raw_code: str) -> str:
  function lookup_key (line 74) | def lookup_key(reference_anchor: str) -> str:
  function repo_relative (line 81) | def repo_relative(path: Path, repo_root: Path) -> str:
  function parse_categories (line 88) | def parse_categories(
  function build_catalog (line 155) | def build_catalog(source_path: Path, repo_root: Path) -> dict:
  function is_inline_safe (line 166) | def is_inline_safe(code: str) -> bool:
  function grouped_entries (line 170) | def grouped_entries(entries: list[dict]) -> list[dict]:
  function render_example_block (line 185) | def render_example_block(code: str) -> list[str]:
  function render_skill_lookup (line 193) | def render_skill_lookup(catalog: dict) -> str:
  function update_skill (line 224) | def update_skill(skill_path: Path, generated_lookup: str) -> None:
  function write_outputs (line 241) | def write_outputs(
  function default_source (line 257) | def default_source(script_path: Path) -> Path:
  function default_skill_path (line 261) | def default_skill_path(script_path: Path) -> Path:
  function main (line 265) | def main() -> int:

FILE: crates/embedded-typst/src/lib.rs
  type StrResult (line 31) | type StrResult<T> = Result<T, String>;
  function allocate_data (line 43) | pub fn allocate_data(kind: &[u8], data: &[u8]) -> StrResult<Vec<u8>> {
  function allocate_file (line 57) | pub fn allocate_file(kind: &[u8], path: &[u8], data: &[u8]) -> StrResult...
  function allocate_data_inner (line 62) | fn allocate_data_inner(kind: &[u8], data: &[u8], path: Option<&[u8]>) ->...
  type Context (line 93) | pub struct Context {
  type ImmutBytes (line 102) | struct ImmutBytes(Bytes);
  type DataRef (line 106) | enum DataRef {
    method data (line 122) | pub fn data(&self) -> Option<&ImmutBytes> {
  function resolve_world (line 135) | pub fn resolve_world() -> StrResult<Vec<u8>> {
  function create_world (line 148) | fn create_world() -> StrResult<WorldRepr> {
  function svg (line 284) | pub fn svg(input: &[u8]) -> StrResult<Vec<u8>> {
  type WasmCompilerFeat (line 342) | pub struct WasmCompilerFeat;
    type FontResolver (line 346) | type FontResolver = FontResolverImpl;
    type AccessModel (line 348) | type AccessModel = DummyAccessModel;
    type Registry (line 350) | type Registry = MemoryRegistry;
  type WorldRepr (line 353) | type WorldRepr = reflexo_typst::world::CompilerUniverse<WasmCompilerFeat>;
  type TypstWasmWorld (line 357) | pub struct TypstWasmWorld(WorldRepr);
    method new (line 367) | pub fn new() -> Self {
  method default (line 360) | fn default() -> Self {
  type MemoryRegistry (line 396) | pub struct MemoryRegistry(HashMap<PackageSpec, Arc<Path>>);
    method add_memory_package (line 400) | pub fn add_memory_package(&mut self, spec: PackageSpec) -> Arc<Path> {
  method resolve (line 414) | fn resolve(&self, spec: &PackageSpec) -> Result<Arc<Path>, PackageError> {
  function now (line 423) | pub extern "C" fn now() -> f64 {
Condensed preview — 134 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (648K chars).
[
  {
    "path": ".codex/skills/openspec-apply-change/SKILL.md",
    "chars": 4710,
    "preview": "---\nname: openspec-apply-change\ndescription: Implement tasks from an OpenSpec change. Use when the user wants to start i"
  },
  {
    "path": ".codex/skills/openspec-archive-change/SKILL.md",
    "chars": 4725,
    "preview": "---\nname: openspec-archive-change\ndescription: Archive a completed change in the experimental workflow. Use when the use"
  },
  {
    "path": ".codex/skills/openspec-explore/SKILL.md",
    "chars": 9067,
    "preview": "---\nname: openspec-explore\ndescription: Enter explore mode - a thinking partner for exploring ideas, investigating probl"
  },
  {
    "path": ".codex/skills/openspec-propose/SKILL.md",
    "chars": 4644,
    "preview": "---\nname: openspec-propose\ndescription: Propose a new change with all artifacts generated in one step. Use when the user"
  },
  {
    "path": ".codex/skills/typst-grammar-authoring/SKILL.md",
    "chars": 10244,
    "preview": "---\nname: typst-grammar-authoring\ndescription: Use when authoring or validating Typst documents from canonical grammar e"
  },
  {
    "path": ".codex/skills/update-typst-grammar-authoring/SKILL.md",
    "chars": 2443,
    "preview": "---\nname: update-typst-grammar-authoring\ndescription: Use when maintaining the portable typst-grammar-authoring skill fr"
  },
  {
    "path": ".codex/skills/update-typst-grammar-authoring/agents/openai.yaml",
    "chars": 299,
    "preview": "interface:\n  display_name: \"Update Typst Grammar Authoring\"\n  short_description: \"Regenerate the portable Typst grammar "
  },
  {
    "path": ".codex/skills/update-typst-grammar-authoring/references/grammar-catalog.json",
    "chars": 77613,
    "preview": "{\n  \"source_path\": \"src/tutorial/reference-grammar.typ\",\n  \"category_count\": 6,\n  \"entry_count\": 127,\n  \"categories\": [\n"
  },
  {
    "path": ".codex/skills/update-typst-grammar-authoring/scripts/generate_grammar_catalog.py",
    "chars": 9647,
    "preview": "#!/usr/bin/env python3\n\"\"\"Generate Typst grammar data and sync it into the portable skill.\"\"\"\n\nfrom __future__ import an"
  },
  {
    "path": ".gitattributes",
    "chars": 42,
    "preview": ".zed/settings.json linguist-language=json5"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 1014,
    "preview": "name: tutorial::ci\non: push\njobs:\n  render_pdf:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n"
  },
  {
    "path": ".github/workflows/gh_pages.yml",
    "chars": 1582,
    "preview": "name: tutorial::gh_pages\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch:\n    \npermissions:\n  pages: write\n  "
  },
  {
    "path": ".gitignore",
    "chars": 40,
    "preview": "dist/\ntarget/\n.DS_Store\nsrc/*.pdf\n.idea\n"
  },
  {
    "path": ".gitmodules",
    "chars": 379,
    "preview": "[submodule \"assets/typst-fonts\"]\n\tpath = assets/typst-fonts\n\turl = https://github.com/typst-doc-cn/fonts\n\tbranch = typst"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 516,
    "preview": "{\n  \"tinymist.fontPaths\": [\"${workspaceFolder}/assets/fonts\"],\n  \"tinymist.exportPdf\": \"onSave\",\n  \"tinymist.outputPath\""
  },
  {
    "path": ".zed/settings.json",
    "chars": 371,
    "preview": "// Folder-specific settings\n//\n// For a full list of overridable settings, and general information on folder-specific se"
  },
  {
    "path": "Cargo.toml",
    "chars": 1684,
    "preview": "[workspace.package]\ndescription = \"The Raindrop Book - Typst中文教程\"\nauthors = [\"Myriad-Dreamin <camiyoru@gmail.com>\"]\nvers"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 1313,
    "preview": "# Tutorial\n\nTypst 中文教程\n\n[![下载最新版本](https://custom-icon-badges.demolab.com/badge/-Download-blue?style=for-the-badge&logo="
  },
  {
    "path": "_typos.toml",
    "chars": 65,
    "preview": "[default]\nextend-ignore-identifiers-re = [\"typ\", \"typc\", \"typm\"]\n"
  },
  {
    "path": "assets/files/tokyo-night.tmTheme",
    "chars": 46000,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "crates/embedded-typst/Cargo.toml",
    "chars": 627,
    "preview": "[package]\nname = \"embedded-typst\"\ndescription = \"Run typst inside of typst\"\nauthors.workspace = true\nversion.workspace ="
  },
  {
    "path": "crates/embedded-typst/src/lib.rs",
    "chars": 12370,
    "preview": "//! This is a WASM wrapper of the embedded Typst.\n\n#![cfg_attr(feature = \"typst-plugin\", allow(missing_docs))]\n\nuse std:"
  },
  {
    "path": "meta.json",
    "chars": 41,
    "preview": "{\n  \"contributors\": [\"Myriad-Dreamin\"]\n}\n"
  },
  {
    "path": "openspec/changes/archive/2026-03-15-create-english-typst-grammar-skill/.openspec.yaml",
    "chars": 40,
    "preview": "schema: spec-driven\ncreated: 2026-03-14\n"
  },
  {
    "path": "openspec/changes/archive/2026-03-15-create-english-typst-grammar-skill/design.md",
    "chars": 6569,
    "preview": "## Context\n\nThis repository contains a detailed Typst grammar catalog in\n`src/tutorial/reference-grammar.typ`. The origi"
  },
  {
    "path": "openspec/changes/archive/2026-03-15-create-english-typst-grammar-skill/proposal.md",
    "chars": 2348,
    "preview": "## Why\n\nThe current `typst-grammar-authoring` implementation mixes two different jobs:\nportable Typst authoring guidance"
  },
  {
    "path": "openspec/changes/archive/2026-03-15-create-english-typst-grammar-skill/specs/typst-document-authoring-skill/spec.md",
    "chars": 4605,
    "preview": "## ADDED Requirements\n\n### Requirement: Portable authoring skill is English-facing and self-contained\nThe distributed `t"
  },
  {
    "path": "openspec/changes/archive/2026-03-15-create-english-typst-grammar-skill/tasks.md",
    "chars": 1599,
    "preview": "## 1. Split the skill topology\n\n- [x] 1.1 Create a repo-local `update-typst-grammar-authoring` skill target under `.code"
  },
  {
    "path": "openspec/config.yaml",
    "chars": 616,
    "preview": "schema: spec-driven\n\ncontext: |\n  When a change is archived and syncs or creates canonical specs under\n  `openspec/specs"
  },
  {
    "path": "openspec/specs/typst-document-authoring-skill/spec.md",
    "chars": 5083,
    "preview": "# typst-document-authoring-skill Specification\n\n## Purpose\nDefine the canonical requirements for a portable, English-fac"
  },
  {
    "path": "scripts/build.ps1",
    "chars": 325,
    "preview": "cargo build --release --target wasm32-unknown-unknown --manifest-path ./crates/embedded-typst/Cargo.toml --features typs"
  },
  {
    "path": "scripts/build.sh",
    "chars": 254,
    "preview": "#!/bin/bash\n\ncargo build --release --target wasm32-unknown-unknown\n\nINSTALL_PATH=\"assets/artifacts/embedded_typst.wasm\"\n"
  },
  {
    "path": "src/book.typ",
    "chars": 4837,
    "preview": "#import \"@preview/shiroa:0.2.3\": *\n\n#show: book\n\n#let book-info = json(\"/meta.json\")\n\n#book-meta(\n  title: \"The Raindrop"
  },
  {
    "path": "src/ebook.typ",
    "chars": 258,
    "preview": "#import \"@preview/shiroa:0.2.3\": *\n#import \"/typ/templates/ebook.typ\"\n\n#show: ebook.project.with(\n  title: \"typst-tutori"
  },
  {
    "path": "src/figures.typ",
    "chars": 2264,
    "preview": "#import \"@preview/fletcher:0.5.7\" as fletcher: edge, node\n#import \"/typ/templates/page.typ\": is-light-theme, main-color,"
  },
  {
    "path": "src/graph/digraph.typ",
    "chars": 58,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [拓扑图])\n"
  },
  {
    "path": "src/graph/electronics.typ",
    "chars": 58,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [电路图])\n"
  },
  {
    "path": "src/graph/mod.typ",
    "chars": 107,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n\n#import \"../mod.typ\": code, exec-code, todo-box\n"
  },
  {
    "path": "src/graph/solid-geometry.typ",
    "chars": 2400,
    "preview": "#import \"mod.typ\": *\n#import \"@preview/cetz:0.3.4\": *\n\n#show: book.page.with(title: \"立体几何\")\n\n== 变换「坐标系」\n\n在绘制立体图形(以及其他抽象图"
  },
  {
    "path": "src/graph/state-machine.typ",
    "chars": 58,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [状态机])\n"
  },
  {
    "path": "src/graph/statistics.typ",
    "chars": 58,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [统计图])\n"
  },
  {
    "path": "src/graph/table.typ",
    "chars": 57,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制表])\n"
  },
  {
    "path": "src/intermediate/mod.typ",
    "chars": 249,
    "preview": "#import \"/src/book.typ\"\n#import \"../mod.typ\": code as _code, exec-code as _exec-code, pro-tip, refs, todo-box, typst-fun"
  },
  {
    "path": "src/introduction.typ",
    "chars": 4844,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [导引])\n\n本书面向所有Typst用户,按三种方式讲解Typst语言。《教程》等章节循序渐进,讲述了Typst的排版方式和原理;《参考》"
  },
  {
    "path": "src/misc/code-syntax.typ",
    "chars": 64,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [自定义代码高亮规则])\n"
  },
  {
    "path": "src/misc/code-theme.typ",
    "chars": 62,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [自定义代码主题])\n"
  },
  {
    "path": "src/misc/font-setting.typ",
    "chars": 324,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [字体设置])\n\n#let table-lnk(name, ref, it, scope: (:), res: none, ..args)"
  },
  {
    "path": "src/misc/mod.typ",
    "chars": 97,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n\n#import \"../mod.typ\": code, exec-code\n"
  },
  {
    "path": "src/misc/text-processing.typ",
    "chars": 66,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [读取外部文件和文本处理])\n"
  },
  {
    "path": "src/mod.typ",
    "chars": 9482,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n#import \"/typ/templates/term.typ\": _term\n#import \"/typ/templat"
  },
  {
    "path": "src/prefaces/acknowledgement.typ",
    "chars": 360,
    "preview": "\n#import \"mod.typ\": *\n\n#show: book.page.with(title: \"致谢\")\n\n#let MyriadDreamin = link(\"https://github.com/Myriad-Dreamin\""
  },
  {
    "path": "src/prefaces/license.typ",
    "chars": 257,
    "preview": "\n#import \"mod.typ\": *\n#page({\n  set text(size: 10.5pt)\n  set block(spacing: 1.5em)\n\n  show \"TERMS AND CONDITIONS FOR USE"
  },
  {
    "path": "src/prefaces/mod.typ",
    "chars": 63,
    "preview": "#import \"/src/book.typ\"\n\n#import \"../mod.typ\": code, exec-code\n"
  },
  {
    "path": "src/science/algorithm.typ",
    "chars": 58,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [伪算法])\n"
  },
  {
    "path": "src/science/chemical.typ",
    "chars": 60,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [化学方程式])\n"
  },
  {
    "path": "src/science/mod.typ",
    "chars": 97,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n\n#import \"../mod.typ\": code, exec-code\n"
  },
  {
    "path": "src/science/theorem.typ",
    "chars": 59,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [定理环境])\n"
  },
  {
    "path": "src/template/book.typ",
    "chars": 59,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [书籍模板])\n"
  },
  {
    "path": "src/template/mod.typ",
    "chars": 97,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n\n#import \"../mod.typ\": code, exec-code\n"
  },
  {
    "path": "src/template/paper.typ",
    "chars": 59,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [论文模板])\n"
  },
  {
    "path": "src/template/slides.typ",
    "chars": 64,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [演示文稿(PPT)])\n"
  },
  {
    "path": "src/topics/call-externals.typ",
    "chars": 80,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [在Typst内执行Js、Python、Typst等])\n"
  },
  {
    "path": "src/topics/mod.typ",
    "chars": 103,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\"\n\n#import \"../mod.typ\": code, exec-code, refs\n"
  },
  {
    "path": "src/topics/template-book.typ",
    "chars": 63,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制作一个书籍模板])\n"
  },
  {
    "path": "src/topics/template-cv.typ",
    "chars": 63,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制作一个CV模板])\n"
  },
  {
    "path": "src/topics/template-paper.typ",
    "chars": 65,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制作一个IEEE模板])\n"
  },
  {
    "path": "src/topics/writing-component-lib.typ",
    "chars": 62,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制作一个组件库])\n"
  },
  {
    "path": "src/topics/writing-math.typ",
    "chars": 63,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [编写一篇数学文档])\n"
  },
  {
    "path": "src/topics/writing-plugin-lib.typ",
    "chars": 63,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [制作一个外部插件])\n"
  },
  {
    "path": "src/tutorial/doc-modulize.typ",
    "chars": 11511,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [模块化(多文件)])\n\n我们接下来学习脚本剩余的所有知识。总结而言,每个源文件对应一个模块;每个模块导出多个「变量声明」和一个「文档(内"
  },
  {
    "path": "src/tutorial/doc-stateful.typ",
    "chars": 20556,
    "preview": "#import \"mod.typ\": *\n\n#import \"/typ/embedded-typst/lib.typ\": default-cjk-fonts, default-fonts, svg-doc\n\n#show: book.page"
  },
  {
    "path": "src/tutorial/figure-time-travel.typ",
    "chars": 10107,
    "preview": "#import \"@preview/cetz:0.3.4\"\n#import \"/typ/templates/page.typ\": main-color, is-light-theme\n\n#let std-scale = scale\n\n#le"
  },
  {
    "path": "src/tutorial/latex-look.typ",
    "chars": 353,
    "preview": "#let latex-look(content) = {\n  // #set page(margin: 1.75in)\n  set par(\n    leading: 0.55em,\n    first-line-indent: 0em,\n"
  },
  {
    "path": "src/tutorial/mod.typ",
    "chars": 1233,
    "preview": "#import \"/src/book.typ\"\n#import \"/typ/templates/page.typ\": is-web-target, main-color\n#import \"/typ/embedded-typst/lib.ty"
  },
  {
    "path": "src/tutorial/other-file.typ",
    "chars": 33,
    "preview": "\n一段文本\n#set text(fill: red)\n另一段文本\n"
  },
  {
    "path": "src/tutorial/packages/m1.typ",
    "chars": 55,
    "preview": "\nXXX\n#let add(x, y) = x + y\nYYY\n#let sub(x, y) = x - y\n"
  },
  {
    "path": "src/tutorial/reference-bibliography.typ",
    "chars": 71,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:导入和使用参考文献])\n"
  },
  {
    "path": "src/tutorial/reference-calculation.typ",
    "chars": 489,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:数值计算])\n\n#let table-lnk(name, ref, it, scope: (:), res: none, "
  },
  {
    "path": "src/tutorial/reference-color.typ",
    "chars": 3774,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:颜色、色彩渐变与模式])\n\n== RGB\n\nCreate an RGB(A) color. #ref-bookmark[`"
  },
  {
    "path": "src/tutorial/reference-counter-state.typ",
    "chars": 68,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:计数器和状态])\n"
  },
  {
    "path": "src/tutorial/reference-data-process.typ",
    "chars": 444,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:数据读写与数据处理])\n\n#let table-lnk(name, ref, it, scope: (:), res: n"
  },
  {
    "path": "src/tutorial/reference-date.typ",
    "chars": 656,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:时间类型])\n\n#let table-lnk(name, ref, it, scope: (:), res: none, "
  },
  {
    "path": "src/tutorial/reference-grammar.typ",
    "chars": 20093,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [参考:语法示例检索表])\n\n#let table-lnk(name, ref, it, scope: (:), res: none, ."
  },
  {
    "path": "src/tutorial/reference-layout.typ",
    "chars": 80,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:布局函数])\n\n已经移至《度量与布局》。\n"
  },
  {
    "path": "src/tutorial/reference-length.typ",
    "chars": 80,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:长度单位])\n\n已经移至《度量与布局》。\n"
  },
  {
    "path": "src/tutorial/reference-math-mode.typ",
    "chars": 66,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:数学模式])\n"
  },
  {
    "path": "src/tutorial/reference-math-symbols.typ",
    "chars": 6684,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [参考:常用数学符号])\n\n#set table(\n  stroke: none,\n  align: horizon + left,\n  "
  },
  {
    "path": "src/tutorial/reference-outline.typ",
    "chars": 66,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:文档大纲])\n"
  },
  {
    "path": "src/tutorial/reference-syntax-analysis.typ",
    "chars": 4158,
    "preview": "\n== variable identifier\n\n// `let`关键字后紧接着跟随一个#term(\"variable identifier\")。标识符是变量的“名称”。「变量声明」后续的位置都可以通过标识符引用该变量。\n\n// + 标识符"
  },
  {
    "path": "src/tutorial/reference-table.typ",
    "chars": 64,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:表格])\n"
  },
  {
    "path": "src/tutorial/reference-type-builtin.typ",
    "chars": 497,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:内置类型])\n\n== 空类型 <reference-type-none>\n\n== type <reference-type"
  },
  {
    "path": "src/tutorial/reference-typebase.typ",
    "chars": 16810,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:基本类型])\n\n#let glue-block = block.with(breakable: false)\n\n// =="
  },
  {
    "path": "src/tutorial/reference-utils.typ",
    "chars": 2038,
    "preview": "#import \"mod.typ\": *\n#import \"/typ/typst-meta/docs.typ\": typst-v11\n#import \"@preview/cmarker:0.1.0\": render as md\n\n#show"
  },
  {
    "path": "src/tutorial/reference-visualization.typ",
    "chars": 2199,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:图形与几何元素])\n\n== 直线\n\nA line from one point to another. #ref-book"
  },
  {
    "path": "src/tutorial/reference-wasm-plugin.typ",
    "chars": 68,
    "preview": "#import \"mod.typ\": *\n\n#show: book.ref-page.with(title: [参考:WASM插件])\n"
  },
  {
    "path": "src/tutorial/scripting-block-and-expression.typ",
    "chars": 6388,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"表达式\")\n\nTypst中绝大部分语法结构都可作表达式,可以说学习完了所有表达式,则学会了Typst所有语法。当然,其吸取了一定历史经验"
  },
  {
    "path": "src/tutorial/scripting-color.typ",
    "chars": 59,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"颜色类型\")\n"
  },
  {
    "path": "src/tutorial/scripting-composite.typ",
    "chars": 4375,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"复合类型\")\n\n学会了数组和字典,我们就解锁了各种新技能。\n\n== 数组字面量 <grammar-array-literal>\n\n脚本模"
  },
  {
    "path": "src/tutorial/scripting-content.typ",
    "chars": 7632,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"文档树\")\n\n#todo-box[本节处于校对阶段,所以可能存在不完整或错误。]\n\n== 「可折叠」的值(Foldable)\n\n先来看代"
  },
  {
    "path": "src/tutorial/scripting-control-flow.typ",
    "chars": 6943,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"控制流\")\n\n== `none`类型和`if`语句 <grammar-if>\n\n默认情况下,在逻辑上,Typst按照顺序执行执行你的代码"
  },
  {
    "path": "src/tutorial/scripting-layout.typ",
    "chars": 20657,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"长度与布局\")\n\n#todo-box[本节处于校对阶段,所以可能存在不完整或错误。]\n\n本章我们再度回到排版专题,拓宽制作文档的能力。\n"
  },
  {
    "path": "src/tutorial/scripting-literal.typ",
    "chars": 7068,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"基本类型\")\n\nTypst很快,并非因为它的#term(\"parser\")和#term(\"interpreter\")具有惊世的执行性能,"
  },
  {
    "path": "src/tutorial/scripting-main.typ",
    "chars": 6027,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"编译流程\")\n\n#todo-box[本节处于校对阶段,所以可能存在不完整或错误。]\n\n经过几节稍显枯燥的脚本教程,我们继续回到排版本身。"
  },
  {
    "path": "src/tutorial/scripting-shape.typ",
    "chars": 4909,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"图形排版\")\n\n#todo-box[本节处于校对阶段,所以可能存在不完整或错误。]\n\n== 颜色类型\n\nTypst只有一种颜色类型,其由"
  },
  {
    "path": "src/tutorial/scripting-style.typ",
    "chars": 11142,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"选择器与样式\")\n\n#todo-box[本节处于校对阶段,所以可能存在不完整或错误。]\n\n== 「样式化」内容\n\n当我们有一个`repr"
  },
  {
    "path": "src/tutorial/scripting-variable.typ",
    "chars": 6660,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"变量与函数\")\n\n== 变量声明 <grammar-var-decl>\n\n变量是存储“字面量”的一个个容器。它相当于为一个个字面量取名,"
  },
  {
    "path": "src/tutorial/stateful/q0.typ",
    "chars": 766,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/stateful/q1.typ",
    "chars": 1739,
    "preview": "\n#set text(size: 8pt)\n\n#let calc-headings(headings) = {\n  let max-page-num = calc.max(..headings.map(it => it.location()"
  },
  {
    "path": "src/tutorial/stateful/s1.typ",
    "chars": 1603,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let first-heading = state(\"first-heading\", (:))\n#"
  },
  {
    "path": "src/tutorial/stateful/s2.typ",
    "chars": 685,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/stateful/s3.typ",
    "chars": 704,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/stateful-v0.12.0/q0.typ",
    "chars": 785,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/stateful-v0.12.0/q1.typ",
    "chars": 1743,
    "preview": "\n#set text(size: 8pt)\n\n#let calc-headings(headings) = {\n  let max-page-num = calc.max(..headings.map(it => it.location()"
  },
  {
    "path": "src/tutorial/stateful-v0.12.0/s1.typ",
    "chars": 1598,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let first-heading = state(\"first-heading\", (:))\n#"
  },
  {
    "path": "src/tutorial/stateful-v0.12.0/s2.typ",
    "chars": 685,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/stateful-v0.12.0/s3.typ",
    "chars": 704,
    "preview": "\n#let curr-heading = state(\"curr-heading\", ())\n\n#set text(size: 8pt)\n\n#let set-heading(content) = {\n  show heading.where"
  },
  {
    "path": "src/tutorial/writing-chinese.typ",
    "chars": 1250,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"中文排版\")\n\n建议结合#link(\"https://typst-doc-cn.github.io/docs/chinese/\")[《T"
  },
  {
    "path": "src/tutorial/writing-markup.typ",
    "chars": 7888,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [标记模式])\n\nTypst是一门简明但强大的现代排版语言,你可以使用简洁直观的语法排版出好看的文档。\n\nTypst希望你总是尽可能少的配"
  },
  {
    "path": "src/tutorial/writing-math.typ",
    "chars": 68,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"数学排版\")\n\n== 数学排版\n"
  },
  {
    "path": "src/tutorial/writing-scripting.typ",
    "chars": 14751,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: [脚本模式])\n\n从现在开始,示例将会逐渐开始出现脚本。不要担心,它们都仅涉及脚本的简单用法。\n\n== 内容块 <grammar-cont"
  },
  {
    "path": "src/tutorial/writing.typ",
    "chars": 308,
    "preview": "#import \"mod.typ\": *\n\n#show: book.page.with(title: \"编写一篇进阶文档\")\n\n// document\n// list again\n// figure again\n// footnote\n//"
  },
  {
    "path": "typ/book/lib.typ",
    "chars": 10443,
    "preview": "\n// #import \"@preview/typst-ts-variables:0.1.0\": page-width, target\n\n#import \"variables.typ\": page-width, target\n\n// exp"
  },
  {
    "path": "typ/book/typst.toml",
    "chars": 195,
    "preview": "[package]\nname = \"book\"\nversion = \"0.2.3\"\nentrypoint = \"lib.typ\"\nauthors = [\"Myriad-Dreamin\"]\nlicense = \"Apache-2.0\"\ndes"
  },
  {
    "path": "typ/book/variables.typ",
    "chars": 110,
    "preview": "\n// It is in default A4 paper size\n#let page-width = 595.28pt\n\n// default target is \"pdf\"\n#let target = \"pdf\"\n"
  },
  {
    "path": "typ/embedded-typst/example.typ",
    "chars": 485,
    "preview": "\n#import \"lib.typ\": *\n\n#let doc = svg-doc(```\n#set page(header: [\n  #set text(size: 20pt)\n  The book compiled by embedde"
  },
  {
    "path": "typ/embedded-typst/lib.typ",
    "chars": 1772,
    "preview": "\n#let separator = \"\\n\\n\\n\\n\\n\\n\\n\\n\"\n\n#let allocate-fonts(data) = (kind: \"font\", hash: none, data: data)\n\n#let create-fo"
  },
  {
    "path": "typ/templates/ebook.typ",
    "chars": 4551,
    "preview": "#import \"@preview/shiroa:0.2.3\": *\n#import \"/typ/templates/page.typ\": project, part-style, dash-color\n#import \"/typ/temp"
  },
  {
    "path": "typ/templates/page.typ",
    "chars": 7577,
    "preview": "\n// This is important for typst-book to produce a responsive layout\n// and multiple targets.\n#import \"@preview/shiroa:0."
  },
  {
    "path": "typ/templates/side-notes.typ",
    "chars": 583,
    "preview": "\n#let side-attrs = state(\"tuturial-side-note-attrs\", (:))\n\n#let side-note(dy: -0.65em, content) = context {\n  let loc = "
  },
  {
    "path": "typ/templates/template-link.typ",
    "chars": 1176,
    "preview": "\n// #import \"supports-text.typ\": plain-text\n#import \"@preview/shiroa:0.2.3\": plain-text\n\n#let make-unique-label(it, disa"
  },
  {
    "path": "typ/templates/term.typ",
    "chars": 449,
    "preview": "\n#let term-state = state(\"term\", (:))\n#let reset-term-state = term-state.update(it => (:))\n\n#let _term(term-list, term, "
  },
  {
    "path": "typ/templates/theme-style.toml",
    "chars": 558,
    "preview": "\n[light]\ncolor-scheme = \"light\"\nmain-color = \"#000\"\ndash-color = \"#20609f\"\ncode-theme = \"\"\n\n[rust]\ncolor-scheme = \"light"
  },
  {
    "path": "typ/typst-meta/docs.typ",
    "chars": 1142,
    "preview": "\n\n#let iterate-scope(env, scope, belongs) = {\n  let p = (..scope.path, scope.name).join(\".\")\n  scope.insert(\"belongs\", b"
  }
]

About this extraction

This page contains the full source code of the typst-doc-cn/tutorial GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 134 files (486.1 KB), approximately 175.6k tokens, and a symbol index with 38 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!