Add tech-report and travel-plan templates, replacing feasibility.
Introduce tech-report/ with cover page, custom TOC, and summary flow; add travel-plan/ for trip planning; update README, gitignore, and brand colors. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
91303740b8
commit
d83e6a99a9
6
.gitignore
vendored
6
.gitignore
vendored
@ -2,13 +2,15 @@
|
|||||||
*.pdf
|
*.pdf
|
||||||
!resume-bp/sample.pdf
|
!resume-bp/sample.pdf
|
||||||
!resume-career/sample.pdf
|
!resume-career/sample.pdf
|
||||||
!feasibility/sample.pdf
|
!tech-report/sample.pdf
|
||||||
!presentation/sample.pdf
|
!presentation/sample.pdf
|
||||||
|
!travel-plan/sample.pdf
|
||||||
|
|
||||||
# 本地定制简历(个人内容、照片、PDF,不提交)
|
# 本地定制(个人内容、照片、PDF,不提交)
|
||||||
resume-bp/local/*
|
resume-bp/local/*
|
||||||
!resume-bp/local/README.md
|
!resume-bp/local/README.md
|
||||||
resume-career/local/*
|
resume-career/local/*
|
||||||
|
travel-plan/local/*
|
||||||
|
|
||||||
# IDE / 编辑器本地配置
|
# IDE / 编辑器本地配置
|
||||||
.cursor/
|
.cursor/
|
||||||
|
|||||||
@ -6,8 +6,9 @@ GreLin 内部 Typst 模板库,按文档类型分目录维护。目录结构如
|
|||||||
|--------|------|----------|
|
|--------|------|----------|
|
||||||
| [`resume-bp/`](resume-bp/) | 融资 BP 团队简历(完整版,含证件照) | `cv.typ` |
|
| [`resume-bp/`](resume-bp/) | 融资 BP 团队简历(完整版,含证件照) | `cv.typ` |
|
||||||
| [`resume-career/`](resume-career/) | 求职 / 个人主页简历(精简一页) | `cv.typ`(内容 `data/config.typ`) |
|
| [`resume-career/`](resume-career/) | 求职 / 个人主页简历(精简一页) | `cv.typ`(内容 `data/config.typ`) |
|
||||||
| [`feasibility/`](feasibility/) | 可行性研究报告 | `report.typ`(正文编辑 `feasibility/content/report.md`) |
|
| [`tech-report/`](tech-report/) | 技术报告 | `report.typ`(正文编辑 `tech-report/content/report.md`) |
|
||||||
| [`presentation/`](presentation/) | PPT 演示文稿(16:9,待完善) | `deck.typ`(内容 `data/config.typ`) |
|
| [`presentation/`](presentation/) | PPT 演示文稿(16:9,待完善) | `deck.typ`(内容 `data/config.typ`) |
|
||||||
|
| [`travel-plan/`](travel-plan/) | 旅行计划(参考图、链接、行程) | `trips/<名>/` · 可选 `plan.typ` |
|
||||||
|
|
||||||
## 环境要求
|
## 环境要求
|
||||||
|
|
||||||
@ -16,8 +17,8 @@ GreLin 内部 Typst 模板库,按文档类型分目录维护。目录结构如
|
|||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
1. 用 VS Code / Cursor 打开本仓库,打开要编辑的入口文件,例如 `resume-bp/cv.typ`、`resume-career/cv.typ`、`presentation/deck.typ` 或 `feasibility/report.typ`
|
1. 用 VS Code / Cursor 打开本仓库,打开要编辑的入口文件,例如 `resume-bp/cv.typ`、`resume-career/cv.typ`、`presentation/deck.typ` 或 `tech-report/report.typ`
|
||||||
2. 可行性报告正文在 `feasibility/content/report.md` 用 Markdown 编写,无需改 Typst 代码
|
2. 技术报告正文在 `tech-report/content/report.md` 用 Markdown 编写,无需改 Typst 代码
|
||||||
3. 看效果(预览):`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果
|
3. 看效果(预览):`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果
|
||||||
4. 导出 PDF:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录
|
4. 导出 PDF:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// GreLin 品牌色板 — 全文档统一(resume-bp / resume-career / feasibility / presentation 等均 import 此文件)
|
// GreLin 品牌色板 — 全文档统一(resume-bp / resume-career / tech-report / presentation 等均 import 此文件)
|
||||||
|
|
||||||
#let color-ink = rgb("#08090B")
|
#let color-ink = rgb("#08090B")
|
||||||
#let color-body = rgb("#2D3135")
|
#let color-body = rgb("#2D3135")
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
# Feasibility Report · 可行性研究报告模板
|
|
||||||
|
|
||||||
GreLin 可行性报告 Typst 模板,面向矿石分选项目论证与客户交付。同事用 **Markdown** 写正文,模板负责封面、页眉页脚与图表排版。
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
1. 编辑 [`content/report.md`](content/report.md)(或从 [`content/report.template.md`](content/report.template.md) 复制)
|
|
||||||
2. 用 VS Code / Cursor 打开 [`report.typ`](report.typ)
|
|
||||||
3. `Ctrl+Shift+P` → **Typst Preview** 预览,或 **Typst Export PDF** 导出
|
|
||||||
|
|
||||||
仓库根目录编译(共享 `brand/colors.typ`):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
typst compile feasibility/report.typ feasibility/sample.pdf --root .
|
|
||||||
```
|
|
||||||
|
|
||||||
示例输出:[`sample.pdf`](sample.pdf)
|
|
||||||
|
|
||||||
## 工作流
|
|
||||||
|
|
||||||
| 文件 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| [`content/report.md`](content/report.md) | **主编辑入口**:YAML 元数据 + 正文 |
|
|
||||||
| [`content/assets/`](content/assets/) | 图片资源(支持 `.jpg` / `.png` / `.svg`) |
|
|
||||||
| [`data/config.typ`](data/config.typ) | 默认公司名、副标题等(YAML 未写时使用) |
|
|
||||||
| [`data/theme.typ`](data/theme.typ) | 设计 token(字号、间距、表格) |
|
|
||||||
| [`data/styling.typ`](data/styling.typ) | 标题 / 表格 / 图片 `#show` 规范 |
|
|
||||||
| [`data/layout.typ`](data/layout.typ) | 封面、摘要、页眉组件 |
|
|
||||||
| [`report.typ`](report.typ) | 编译入口(一般无需改动) |
|
|
||||||
|
|
||||||
## YAML 元数据
|
|
||||||
|
|
||||||
在 `report.md` 顶部填写:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 某某矿山智能分选可行性研究
|
|
||||||
brand: GreLin
|
|
||||||
company: 西安高岭绿能科技有限公司
|
|
||||||
date: 2026-06-22
|
|
||||||
version: v1.0
|
|
||||||
summary: |
|
|
||||||
摘要正文……
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
## Markdown 写法
|
|
||||||
|
|
||||||
- 章节:`# 项目概述`(自动编号为 1. / 1.1 / 1.1.1,无需手写「一、二、三」)
|
|
||||||
- 表格:标准 GFM 表格语法
|
|
||||||
- 图片:`` 或 `assets/chart.png`,文件放在 `content/assets/`
|
|
||||||
- 行内代码:`` `ONNX Runtime` ``(灰底、小圆角、品牌色文字)
|
|
||||||
- 代码块:` ```python ` 围栏 + 语言名,由 [codly](https://typst.app/universe/package/codly) 自动语法高亮并显示语言标签
|
|
||||||
- 下划线:`<u>文字</u>`(品牌色,线下移 5pt)
|
|
||||||
- Emoji:正文可直接写 🐱 等符号(需系统字体支持)
|
|
||||||
- 列表、加粗等均支持(基于 [cmarker](https://typst.app/universe/package/cmarker))
|
|
||||||
|
|
||||||
## 依赖包
|
|
||||||
|
|
||||||
| 包 | 用途 |
|
|
||||||
|----|------|
|
|
||||||
| [cmarker](https://typst.app/universe/package/cmarker) | Markdown → Typst 正文 |
|
|
||||||
| [codly](https://typst.app/universe/package/codly) + [codly-languages](https://typst.app/universe/package/codly-languages) | 代码块高亮与语言标签 |
|
|
||||||
|
|
||||||
可选扩展:[toutu](https://typst.app/universe/package/toutu)(目录)、[hydra](https://typst.app/universe/package/hydra)(页眉章节名)、[cetz](https://typst.app/universe/package/cetz)(矢量图表)。
|
|
||||||
|
|
||||||
## 环境要求
|
|
||||||
|
|
||||||
- **Typst ≥ 0.14.0**;请使用较新版本的 Tinymist 或 Typst CLI
|
|
||||||
- 首次编译会自动下载 `cmarker`、`codly`、`codly-languages`(需网络)
|
|
||||||
|
|
||||||
## 替换外部 MD
|
|
||||||
|
|
||||||
将同事发来的 `.md` 覆盖 `content/report.md`,图片放入 `content/assets/` 并修正文内路径,重新预览即可。
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
|
|
||||||
/// 点阵底纹
|
|
||||||
#let tech-dots(width: 100%, height: 100%, step: 10pt) = box(width: width, height: height, clip: true)[
|
|
||||||
#for x in range(40) {
|
|
||||||
for y in range(40) {
|
|
||||||
place(
|
|
||||||
left + top,
|
|
||||||
dx: x * step,
|
|
||||||
dy: y * step,
|
|
||||||
circle(radius: 0.35pt, fill: color-grid),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
/// 条形码条
|
|
||||||
#let tech-barcode(width, height, bars: 28) = box(width: width, height: height, clip: true)[
|
|
||||||
#for i in range(bars) {
|
|
||||||
let w = if calc.rem(i, 4) == 0 { 2.2pt } else if calc.rem(i, 2) == 0 { 1.4pt } else { 0.8pt }
|
|
||||||
place(
|
|
||||||
left + top,
|
|
||||||
dx: i * (width / bars),
|
|
||||||
box(width: w, height: 100%, fill: color-ink),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
/// 等宽标签
|
|
||||||
#let tech-label(body, fill: color-ink, size: 7pt) = text(
|
|
||||||
font: mono-font,
|
|
||||||
size: size,
|
|
||||||
fill: fill,
|
|
||||||
tracking: 0.14em,
|
|
||||||
)[#body]
|
|
||||||
|
|
||||||
/// 章节编号
|
|
||||||
#let section-tech-id(..nums) = {
|
|
||||||
let n = nums.pos()
|
|
||||||
let id = if n.len() == 1 {
|
|
||||||
let num = n.first()
|
|
||||||
if num < 10 { "0" + str(num) } else { str(num) }
|
|
||||||
} else if n.len() == 2 {
|
|
||||||
str(n.at(0)) + "." + str(n.at(1))
|
|
||||||
} else {
|
|
||||||
str(n.at(0)) + "." + str(n.at(1)) + "." + str(n.at(2))
|
|
||||||
}
|
|
||||||
box(fill: color-accent-surface, inset: (x: 5pt, y: 2pt))[
|
|
||||||
#text(font: mono-font, size: 7pt, weight: "bold", fill: color-ink)[#id]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
#import "logo.typ": grelin-logo, cover-index-badge
|
|
||||||
#import "decor.typ": tech-dots, tech-barcode, tech-label
|
|
||||||
|
|
||||||
#let format-cover-date(date) = {
|
|
||||||
let parts = date.split("-")
|
|
||||||
if parts.len() == 3 {
|
|
||||||
parts.at(0) + "." + parts.at(1) + "." + parts.at(2)
|
|
||||||
} else {
|
|
||||||
date
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-meta-strip(meta) = box(
|
|
||||||
width: 100%,
|
|
||||||
fill: color-ink,
|
|
||||||
inset: (x: 12pt, y: 8pt),
|
|
||||||
)[
|
|
||||||
#grid(
|
|
||||||
columns: (1fr, auto, 1fr, auto, 1fr),
|
|
||||||
column-gutter: 12pt,
|
|
||||||
align: horizon,
|
|
||||||
tech-label("VERSION", fill: color-accent, size: 6.5pt),
|
|
||||||
text(font: mono-font, size: 8pt, fill: white)[#meta.version],
|
|
||||||
tech-label("DATE", fill: color-accent, size: 6.5pt),
|
|
||||||
text(font: mono-font, size: 8pt, fill: white)[#format-cover-date(meta.date)],
|
|
||||||
align(right)[
|
|
||||||
tech-label("STATUS · DRAFT", fill: color-accent, size: 6.5pt)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#let cover-block(meta) = {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
block(width: 100%, below: space-chapter)[
|
|
||||||
#box(width: 100%, height: cover-block-height, fill: white)[
|
|
||||||
#place(top + left)[#grelin-logo()]
|
|
||||||
#place(top + right)[#cover-index-badge("01")]
|
|
||||||
|
|
||||||
#place(left + top, dy: 52pt)[#tech-barcode(14pt, 120pt, bars: 5)]
|
|
||||||
#place(right + top, dy: 72pt)[
|
|
||||||
#rotate(-90deg, reflow: true)[
|
|
||||||
#tech-label("FEASIBILITY REPORT", fill: color-caption, size: 6.5pt)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(left + top, dx: 28pt, dy: 100pt)[
|
|
||||||
#box(width: 88%, height: 130pt, clip: true)[#tech-dots(width: 100%, height: 100%, step: 11pt)]
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(left + top, dx: 24pt, dy: 168pt)[
|
|
||||||
#box(width: 92%, fill: color-accent-surface, inset: (x: 16pt, y: 18pt))[
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: size-cover-title,
|
|
||||||
weight: "black",
|
|
||||||
fill: color-ink,
|
|
||||||
hyphenate: false,
|
|
||||||
)[#meta.title]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(left + bottom, dy: -36pt)[
|
|
||||||
#box(width: 100%)[#cover-meta-strip(meta)]
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(left + bottom, dy: -8pt)[
|
|
||||||
#tech-barcode(100%, 10pt, bars: 48)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
pagebreak()
|
|
||||||
}
|
|
||||||
|
|
||||||
#let accent-line() = box(width: 100%, height: 2pt, fill: color-ink)
|
|
||||||
|
|
||||||
#let summary-block(meta) = {
|
|
||||||
if meta.summary != "" {
|
|
||||||
block(width: 100%, above: space-block, below: space-chapter)[
|
|
||||||
#box(
|
|
||||||
width: 100%,
|
|
||||||
fill: white,
|
|
||||||
stroke: 1.5pt + color-ink,
|
|
||||||
inset: summary-inset,
|
|
||||||
)[
|
|
||||||
#box(width: 100%, fill: color-accent-surface, inset: (x: 10pt, y: 5pt))[
|
|
||||||
#tech-label("ABSTRACT", fill: color-ink, size: 7pt)
|
|
||||||
]
|
|
||||||
#v(10pt)
|
|
||||||
#text(font: heading-font, size: size-h2, weight: "black", fill: color-ink)[摘要]
|
|
||||||
#v(space-block)
|
|
||||||
#set par(leading: leading-summary, justify: true)
|
|
||||||
#set text(size: size-body, fill: color-body)
|
|
||||||
#meta.summary
|
|
||||||
#v(space-section)
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr, auto, 1fr),
|
|
||||||
column-gutter: 8pt,
|
|
||||||
align: horizon,
|
|
||||||
tech-label("DATE", size: 6.5pt),
|
|
||||||
text(font: mono-font, size: size-meta, fill: color-body)[#meta.date],
|
|
||||||
tech-label("ORG", size: 6.5pt),
|
|
||||||
text(font: mono-font, size: size-meta, fill: color-body)[#meta.company],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let page-footer() = context {
|
|
||||||
grid(
|
|
||||||
columns: (auto, 1fr, auto),
|
|
||||||
align: horizon,
|
|
||||||
tech-barcode(36pt, 8pt, bars: 10),
|
|
||||||
box(width: 100%, height: 1pt, fill: color-ink),
|
|
||||||
box(fill: color-ink, inset: (x: 8pt, y: 3pt))[
|
|
||||||
#text(font: mono-font, size: 8pt, fill: color-accent)[
|
|
||||||
#counter(page).display("1")
|
|
||||||
#h(0.12em)
|
|
||||||
#sym.slash
|
|
||||||
#h(0.12em)
|
|
||||||
#counter(page).final().first()
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let page-accent-bar() = place(
|
|
||||||
left + top,
|
|
||||||
tech-barcode(page-accent-bar-width, 100%, bars: 4),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let page-header(meta) = [
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr, auto),
|
|
||||||
column-gutter: 8pt,
|
|
||||||
align: horizon,
|
|
||||||
box(fill: color-accent-surface, inset: (x: 6pt, y: 2pt))[
|
|
||||||
#text(font: mono-font, size: 7pt, weight: "bold", fill: color-ink)[#upper(meta.brand)]
|
|
||||||
],
|
|
||||||
box(width: 100%, height: 1pt, fill: color-ink),
|
|
||||||
align(right)[
|
|
||||||
#text(font: mono-font, size: 7pt, fill: color-caption)[#meta.title]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
#v(6pt)
|
|
||||||
#accent-line()
|
|
||||||
]
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
#import "decor.typ": tech-label
|
|
||||||
|
|
||||||
/// Logo:品牌蓝块 + 白色折线图形 + GreLin | Tech
|
|
||||||
#let grelin-logo(
|
|
||||||
primary: "GreLin",
|
|
||||||
secondary: "Tech",
|
|
||||||
) = grid(
|
|
||||||
columns: (auto, auto),
|
|
||||||
column-gutter: 10pt,
|
|
||||||
align: horizon,
|
|
||||||
box(width: 34pt, height: 34pt, fill: color-brand)[
|
|
||||||
#place(left + top, dx: 7pt, dy: 8pt, box(width: 14pt, height: 3pt, fill: white))
|
|
||||||
#place(left + top, dx: 7pt, dy: 14pt, box(width: 3pt, height: 14pt, fill: white))
|
|
||||||
#place(left + top, dx: 18pt, dy: 14pt, box(width: 9pt, height: 3pt, fill: white))
|
|
||||||
#place(left + top, dx: 18pt, dy: 17pt, box(width: 3pt, height: 11pt, fill: white))
|
|
||||||
],
|
|
||||||
grid(
|
|
||||||
columns: (auto, auto, auto),
|
|
||||||
column-gutter: 7pt,
|
|
||||||
align: horizon,
|
|
||||||
text(font: heading-font, size: 12pt, weight: "black", fill: color-ink, tracking: 0.04em)[#primary],
|
|
||||||
box(width: 1.2pt, height: 1em, fill: color-ink),
|
|
||||||
text(font: heading-font, size: 12pt, weight: "black", fill: color-ink, tracking: 0.16em)[#secondary],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let cover-index-badge(index) = box(
|
|
||||||
width: 58pt,
|
|
||||||
height: 58pt,
|
|
||||||
stroke: 2pt + color-ink,
|
|
||||||
fill: white,
|
|
||||||
)[
|
|
||||||
#align(center + horizon)[
|
|
||||||
#text(font: mono-font, size: size-cover-index, weight: "black", fill: color-ink)[#index]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
@ -1,160 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
#import "decor.typ": section-tech-id, tech-label
|
|
||||||
|
|
||||||
#let underline-accent(body) = underline(
|
|
||||||
body,
|
|
||||||
stroke: underline-stroke,
|
|
||||||
offset: underline-offset,
|
|
||||||
evade: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
#let heading-number(it) = {
|
|
||||||
if it.numbering != none {
|
|
||||||
counter(heading).display(it.numbering)
|
|
||||||
h(heading-number-gap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let report-heading-numbering(..nums) = {
|
|
||||||
let n = nums.pos()
|
|
||||||
if n.len() == 1 {
|
|
||||||
numbering("1.", n.first())
|
|
||||||
} else if n.len() == 2 {
|
|
||||||
numbering("1.1", n.at(0), n.at(1))
|
|
||||||
} else {
|
|
||||||
numbering("1.1.1", ..n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let grelin-h1(it) = block(
|
|
||||||
width: 100%,
|
|
||||||
above: space-chapter,
|
|
||||||
below: space-block,
|
|
||||||
)[
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
column-gutter: 8pt,
|
|
||||||
align: horizon,
|
|
||||||
context section-tech-id(..counter(heading).get()),
|
|
||||||
box(width: 100%, fill: color-accent-surface, inset: (x: 8pt, y: 4pt))[
|
|
||||||
#text(font: heading-font, size: size-h1, weight: "black", fill: color-ink)[
|
|
||||||
#heading-number(it)
|
|
||||||
#it.body
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-h2(it) = block(width: 100%, above: space-section, below: space-inline)[
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
column-gutter: 8pt,
|
|
||||||
align: horizon,
|
|
||||||
box(width: 3pt, height: 1em, fill: color-ink),
|
|
||||||
text(font: heading-font, size: size-h2, weight: "bold", fill: color-ink)[
|
|
||||||
#heading-number(it)
|
|
||||||
#it.body
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-h3(it) = block(width: 100%, above: space-block, below: space-micro)[
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
column-gutter: 6pt,
|
|
||||||
align: horizon,
|
|
||||||
tech-label("///", size: 6.5pt),
|
|
||||||
text(font: heading-font, size: size-h3, weight: "bold", fill: color-ink)[
|
|
||||||
#heading-number(it)
|
|
||||||
#it.body
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-image(it) = block(
|
|
||||||
width: 100%,
|
|
||||||
above: space-figure-before,
|
|
||||||
below: space-figure-after,
|
|
||||||
)[
|
|
||||||
#align(center)[
|
|
||||||
#box(width: image-max-width, stroke: 1pt + color-ink)[
|
|
||||||
#set image(width: 100%, fit: "contain")
|
|
||||||
#it
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-table(it) = block(
|
|
||||||
width: 100%,
|
|
||||||
above: space-figure-before,
|
|
||||||
below: space-figure-after,
|
|
||||||
)[
|
|
||||||
#it
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-figure(it) = block(
|
|
||||||
width: 100%,
|
|
||||||
above: space-figure-before,
|
|
||||||
below: space-figure-after,
|
|
||||||
)[
|
|
||||||
#align(center)[
|
|
||||||
#set image(width: image-max-width, fit: "contain")
|
|
||||||
#set text(size: size-caption, fill: color-caption)
|
|
||||||
#it
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-blockquote(it) = block(
|
|
||||||
width: 100%,
|
|
||||||
above: space-block,
|
|
||||||
below: space-block,
|
|
||||||
inset: (left: blockquote-inset),
|
|
||||||
stroke: (left: blockquote-stroke),
|
|
||||||
fill: white,
|
|
||||||
)[
|
|
||||||
#set par(leading: leading-body, justify: true)
|
|
||||||
#set text(fill: color-quote)
|
|
||||||
#it
|
|
||||||
]
|
|
||||||
|
|
||||||
#let grelin-inline-code(it) = box(
|
|
||||||
fill: code-inline-fill,
|
|
||||||
inset: code-inline-inset,
|
|
||||||
stroke: 0.8pt + color-ink,
|
|
||||||
)[
|
|
||||||
#set text(font: mono-font, size: size-body, fill: color-code-inline)
|
|
||||||
#it
|
|
||||||
]
|
|
||||||
|
|
||||||
#let apply-report-styling(body) = {
|
|
||||||
set heading(numbering: report-heading-numbering)
|
|
||||||
set text(size: size-table)
|
|
||||||
set table(
|
|
||||||
stroke: (x, y) => (
|
|
||||||
top: if y == 0 { 1.5pt + color-ink } else { none },
|
|
||||||
bottom: if y == 0 { 0.8pt + color-ink } else { none },
|
|
||||||
),
|
|
||||||
inset: table-inset,
|
|
||||||
align: (col, row) => if col == 0 { left + horizon } else { center + horizon },
|
|
||||||
fill: (col, row) => {
|
|
||||||
if row == 0 {
|
|
||||||
table-header-fill
|
|
||||||
} else if calc.rem(row, 2) == 0 {
|
|
||||||
table-zebra-fill
|
|
||||||
} else {
|
|
||||||
white
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
show heading.where(level: 1): grelin-h1
|
|
||||||
show heading.where(level: 2): grelin-h2
|
|
||||||
show heading.where(level: 3): grelin-h3
|
|
||||||
show image: grelin-image
|
|
||||||
show table.cell: set text(fill: table-data-text)
|
|
||||||
show table.cell.where(y: 0): set text(weight: "bold", fill: color-ink)
|
|
||||||
show table: grelin-table
|
|
||||||
show figure: grelin-figure
|
|
||||||
show quote.where(block: true): grelin-blockquote
|
|
||||||
show raw.where(block: false): grelin-inline-code
|
|
||||||
body
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
#import "../../brand/colors.typ": *
|
|
||||||
|
|
||||||
// 可行性报告配色:品牌蓝 · 纯黑 · 冷灰
|
|
||||||
#let color-accent = color-brand
|
|
||||||
#let color-accent-surface = color-brand-surface
|
|
||||||
#let color-heading = color-brand
|
|
||||||
#let color-accent-line = color-ink
|
|
||||||
#let color-divider = rgb(205, 205, 205)
|
|
||||||
#let color-caption = rgb(110, 110, 110)
|
|
||||||
#let color-quote = rgb(90, 90, 90)
|
|
||||||
#let color-code-lang = rgb(90, 90, 90)
|
|
||||||
#let color-code-inline = color-ink
|
|
||||||
#let color-header = color-ink
|
|
||||||
#let color-page = rgb(238, 238, 238)
|
|
||||||
#let color-bar-bg = rgb(248, 248, 248)
|
|
||||||
#let color-grid = rgb(220, 220, 220)
|
|
||||||
|
|
||||||
// 代码块语法高亮
|
|
||||||
#let code-token-keyword = color-ink
|
|
||||||
#let code-token-comment = rgb(130, 130, 130)
|
|
||||||
#let code-token-string = rgb(40, 40, 40)
|
|
||||||
#let code-token-number = rgb(70, 70, 70)
|
|
||||||
#let code-token-function = color-ink
|
|
||||||
#let code-token-operator = rgb(100, 100, 100)
|
|
||||||
|
|
||||||
#let heading-font = ("Microsoft YaHei", "Segoe UI", "Segoe UI Emoji")
|
|
||||||
#let body-font = ("Microsoft YaHei UI", "Microsoft YaHei", "Segoe UI", "Segoe UI Emoji")
|
|
||||||
#let mono-font = ("Consolas", "Cascadia Mono", "Microsoft YaHei UI")
|
|
||||||
|
|
||||||
// =====================================================================
|
|
||||||
// GreLin Feasibility Report · Design Tokens
|
|
||||||
// =====================================================================
|
|
||||||
|
|
||||||
// --- 字号 ---
|
|
||||||
#let size-title = 22pt
|
|
||||||
#let size-cover-title = 34pt
|
|
||||||
#let size-cover-index = 52pt
|
|
||||||
#let size-h1 = 14pt
|
|
||||||
#let size-h2 = 12pt
|
|
||||||
#let size-h3 = 11pt
|
|
||||||
#let size-body = 10.5pt
|
|
||||||
#let size-meta = 9pt
|
|
||||||
#let size-table = 9pt
|
|
||||||
#let size-caption = size-meta
|
|
||||||
|
|
||||||
// --- 行距 ---
|
|
||||||
#let leading-body = 12.5pt
|
|
||||||
#let leading-summary = leading-body
|
|
||||||
|
|
||||||
// --- 间距 ---
|
|
||||||
#let space-none = 0pt
|
|
||||||
#let space-micro = 4pt
|
|
||||||
#let space-inline = 6pt
|
|
||||||
#let space-block = 10pt
|
|
||||||
#let space-section = 12pt
|
|
||||||
#let space-chapter = 18pt
|
|
||||||
#let space-figure-before = space-block
|
|
||||||
#let space-figure-after = space-section
|
|
||||||
#let space-cover-line = 3pt
|
|
||||||
#let space-cover-title = 3pt
|
|
||||||
#let space-cover-meta = 6pt
|
|
||||||
#let cover-block-height = 19.5cm
|
|
||||||
|
|
||||||
// --- 线条 / 边框 ---
|
|
||||||
#let underline-stroke = 2pt + color-accent
|
|
||||||
#let underline-offset = 5pt
|
|
||||||
#let heading-number-gap = 0.35em
|
|
||||||
#let stroke-accent = 1.5pt + color-ink
|
|
||||||
#let summary-radius = 0pt
|
|
||||||
#let summary-inset = 14pt
|
|
||||||
|
|
||||||
// --- 页面 ---
|
|
||||||
#let page-margin = (
|
|
||||||
top: 2.5cm,
|
|
||||||
bottom: 2.5cm,
|
|
||||||
left: 2.5cm,
|
|
||||||
right: 2.5cm,
|
|
||||||
)
|
|
||||||
#let page-header-ascent = 1.0cm
|
|
||||||
#let page-footer-descent = 0.8cm
|
|
||||||
#let page-accent-bar-width = 10pt
|
|
||||||
|
|
||||||
// --- 表格 ---
|
|
||||||
#let table-zebra-fill = color-brand-tint
|
|
||||||
#let table-header-fill = color-brand-surface
|
|
||||||
#let table-data-text = rgb(50, 50, 50)
|
|
||||||
#let table-inset = (x: 10pt, y: 6pt)
|
|
||||||
|
|
||||||
// --- 图片 ---
|
|
||||||
#let image-max-width = 100%
|
|
||||||
|
|
||||||
// --- 代码 ---
|
|
||||||
#let code-block-inset = 10pt
|
|
||||||
#let code-block-radius = 0pt
|
|
||||||
#let code-block-fill = rgb(255, 255, 255)
|
|
||||||
#let code-inline-fill = rgb(255, 255, 255)
|
|
||||||
#let code-inline-inset = (x: 5pt, y: 0.12em)
|
|
||||||
#let code-inline-radius = 0pt
|
|
||||||
|
|
||||||
// --- 引用 ---
|
|
||||||
#let blockquote-inset = 10pt
|
|
||||||
#let blockquote-stroke = 3pt + color-accent
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
#import "data/config.typ": *
|
|
||||||
#import "data/theme.typ": *
|
|
||||||
#import "data/glossary.typ": init-glossary, print-glossary-block, register-report-glossary, gls-long, gls-short
|
|
||||||
#import "data/diagrams.typ": ore-sorting-flow
|
|
||||||
#import "data/code.typ": codly-init-rule, codly-config, code-token-highlight-init
|
|
||||||
#import "data/styling.typ": apply-report-styling
|
|
||||||
#import "data/layout.typ": cover-block, summary-block, page-header, page-footer, page-accent-bar
|
|
||||||
#import "data/md.typ": load-report-md
|
|
||||||
|
|
||||||
#show: codly-init-rule
|
|
||||||
#show: code-token-highlight-init
|
|
||||||
#show: init-glossary
|
|
||||||
#codly-config
|
|
||||||
|
|
||||||
#register-report-glossary()
|
|
||||||
|
|
||||||
#let report = load-report-md(
|
|
||||||
read(content-path),
|
|
||||||
source-path: content-path,
|
|
||||||
extra-scope: (
|
|
||||||
ore-sorting-flow: ore-sorting-flow,
|
|
||||||
gls-long: gls-long,
|
|
||||||
gls-short: gls-short,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
#let meta = report.metadata
|
|
||||||
|
|
||||||
#set page(
|
|
||||||
paper: "a4",
|
|
||||||
margin: page-margin,
|
|
||||||
header-ascent: page-header-ascent,
|
|
||||||
footer-descent: page-footer-descent,
|
|
||||||
fill: color-page,
|
|
||||||
background: page-accent-bar(),
|
|
||||||
header: context {
|
|
||||||
if counter(page).get().first() > 1 {
|
|
||||||
page-header(meta)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
footer: context {
|
|
||||||
if counter(page).get().first() > 1 {
|
|
||||||
page-footer()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
#set text(font: body-font, lang: "zh", size: size-body, fill: color-body)
|
|
||||||
#set par(leading: leading-body, justify: true)
|
|
||||||
|
|
||||||
#cover-block(meta)
|
|
||||||
#summary-block(meta)
|
|
||||||
#apply-report-styling(report.body)
|
|
||||||
#print-glossary-block()
|
|
||||||
51
tech-report/README.md
Normal file
51
tech-report/README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Tech Report · 技术报告模板
|
||||||
|
|
||||||
|
GreLin 技术报告 Typst 模板,正文版式参考 [metropole-report](https://typst.app/universe/package/metropole-report);**封面**为自定义深蓝渐变 + 光斑 / 波纹 / 斜向色带(见 `data/cover.typ`)。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. 编辑 [`content/report.md`](content/report.md)
|
||||||
|
2. 打开 [`report.typ`](report.typ) 预览或导出 PDF
|
||||||
|
|
||||||
|
```bash
|
||||||
|
typst compile tech-report/report.typ tech-report/sample.pdf --root .
|
||||||
|
```
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| [`content/report.md`](content/report.md) | **主编辑入口**:YAML 元数据 + 正文 |
|
||||||
|
| [`content/assets/`](content/assets/) | 图片资源 |
|
||||||
|
| [`data/config.typ`](data/config.typ) | 默认公司名、标题等 |
|
||||||
|
| [`data/theme.typ`](data/theme.typ) | 字号、行距、GreLin 品牌色 |
|
||||||
|
| [`data/cover.typ`](data/cover.typ) | 封面装饰与版式 |
|
||||||
|
| [`data/metropole-grelin.typ`](data/metropole-grelin.typ) | 正文 metropole 壳(跳过内联标题) |
|
||||||
|
| [`report.typ`](report.typ) | 编译入口 |
|
||||||
|
|
||||||
|
## YAML 元数据
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 某某矿山智能分选技术报告
|
||||||
|
brand: GreLin
|
||||||
|
company: 西安高岭绿能科技有限公司
|
||||||
|
date: 2026-06-22
|
||||||
|
version: v1.0
|
||||||
|
summary: |
|
||||||
|
摘要正文……
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
| 包 | 用途 |
|
||||||
|
|----|------|
|
||||||
|
| [metropole-report](https://typst.app/universe/package/metropole-report) | 报告版式(封面、标题、表格、列表) |
|
||||||
|
| [cmarker](https://typst.app/universe/package/cmarker) | Markdown → Typst |
|
||||||
|
| [codly](https://typst.app/universe/package/codly) | 代码块高亮 |
|
||||||
|
| [glossarium](https://typst.app/universe/package/glossarium) | 术语表 |
|
||||||
|
|
||||||
|
## 样式参考
|
||||||
|
|
||||||
|
整体风格对齐 `typst init @preview/metropole-report:0.1.0`;后续可引入 [grape-suite](https://typst.app/universe/package/grape-suite) 做更复杂的学术组件。
|
||||||
|
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 251 KiB |
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: 铝土矿可行性研究报告
|
title: 铝土矿智能分选技术报告
|
||||||
company: 西安高岭绿能科技有限公司
|
company: 西安高岭绿能科技有限公司
|
||||||
date: 2026-06-22
|
date: 2026-06-22
|
||||||
version: v1.0
|
version: v2.0
|
||||||
summary: |
|
summary: |
|
||||||
本项目拟在目标矿山建设智能矿石分选产线,以高光谱感知、深度学习推理与喷阀执行闭环为核心,实现铝土矿预选抛废与品位提升。经现场调研与算法验证,单线设计处理量 25 t/h,精矿 A/S 可达 4.0+,具备工程化落地条件。
|
本项目拟在目标矿山建设智能矿石分选产线,以高光谱感知、深度学习推理与喷阀执行闭环为核心,实现铝土矿预选抛废与品位提升。经现场调研与算法验证,单线设计处理量 25 t/h,精矿 A/S 可达 4.0+,具备工程化落地条件。
|
||||||
---
|
---
|
||||||
@ -1,10 +1,10 @@
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// 可行性报告 — 默认值(正文在 content/report.md,YAML 可覆盖下列字段)
|
// 技术报告 — 默认值(正文在 content/report.md,YAML 可覆盖下列字段)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
#let default-brand = "GreLin"
|
#let default-brand = "GreLin"
|
||||||
#let default-company = "西安高岭绿能科技有限公司"
|
#let default-company = "西安高岭绿能科技有限公司"
|
||||||
#let default-title = "智能矿石分选系统建设项目"
|
#let default-title = "智能矿石分选系统技术报告"
|
||||||
#let default-version = "v1.0"
|
#let default-version = "v1.0"
|
||||||
#let default-date = "2026 年 6 月"
|
#let default-date = "2026 年 6 月"
|
||||||
|
|
||||||
257
tech-report/data/cover.typ
Normal file
257
tech-report/data/cover.typ
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
#let format-cover-date(date, fallback) = {
|
||||||
|
if date != none {
|
||||||
|
date.display("[year].[month repr:numerical].[day]")
|
||||||
|
} else if type(fallback) == str {
|
||||||
|
fallback
|
||||||
|
} else {
|
||||||
|
str(fallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-title-lines(title) = {
|
||||||
|
let marker = "智能"
|
||||||
|
let m = title.match(regex(marker))
|
||||||
|
if m == none {
|
||||||
|
(title, none)
|
||||||
|
} else {
|
||||||
|
let end = m.end
|
||||||
|
let line-2 = title.slice(end)
|
||||||
|
if line-2.len() > 0 {
|
||||||
|
(title.slice(0, end), line-2)
|
||||||
|
} else {
|
||||||
|
(title, none)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-title-block(line-1, line-2) = {
|
||||||
|
block(breakable: false, spacing: 0pt)[
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: size-cover-title,
|
||||||
|
weight: "bold",
|
||||||
|
fill: cover-panel-title-color,
|
||||||
|
hyphenate: false,
|
||||||
|
top-edge: "cap-height",
|
||||||
|
bottom-edge: "baseline",
|
||||||
|
)[#line-1]
|
||||||
|
#if line-2 != none [
|
||||||
|
#move(dy: cover-panel-title-pull)[
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: size-cover-title-line2,
|
||||||
|
weight: "bold",
|
||||||
|
fill: cover-panel-title-color,
|
||||||
|
hyphenate: false,
|
||||||
|
top-edge: "cap-height",
|
||||||
|
bottom-edge: "baseline",
|
||||||
|
)[#line-2]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-logo() = {
|
||||||
|
let mark = cover-logo-size * 0.64
|
||||||
|
let offset = cover-logo-size * 0.36
|
||||||
|
box(width: cover-logo-size, height: cover-logo-size)[
|
||||||
|
#place(left + top)[
|
||||||
|
#rect(width: mark, height: mark, fill: color-primary)
|
||||||
|
]
|
||||||
|
#place(left + top, dx: offset, dy: offset)[
|
||||||
|
#rect(width: mark, height: mark, fill: none, stroke: 1.5pt + color-primary)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-quote-mark() = {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: cover-quote-size,
|
||||||
|
fill: cover-quote-color,
|
||||||
|
)[”]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-panel-footer(meta, date-text) = {
|
||||||
|
block(width: 100%, breakable: false)[
|
||||||
|
#text(font: heading-font, size: cover-panel-author-size, weight: "bold", fill: cover-panel-title-color)[
|
||||||
|
#meta.company
|
||||||
|
]
|
||||||
|
#v(cover-panel-text-gap * 0.25)
|
||||||
|
#text(font: body-font, size: cover-panel-role-size, fill: cover-panel-subtitle-color)[
|
||||||
|
技术报告 · #meta.version
|
||||||
|
]
|
||||||
|
#v(cover-panel-role-gap-before-line)
|
||||||
|
#block(width: 100%, breakable: false)[
|
||||||
|
#place(right + top)[
|
||||||
|
#cover-quote-mark()
|
||||||
|
]
|
||||||
|
#block(width: 100%, inset: (right: cover-quote-clearance))[
|
||||||
|
#line(length: cover-panel-footer-line-length, stroke: cover-panel-footer-rule-stroke + cover-panel-footer-line-color)
|
||||||
|
#v(cover-panel-meta-gap-after-line)
|
||||||
|
#grid(
|
||||||
|
columns: (auto, auto, auto),
|
||||||
|
column-gutter: cover-panel-meta-column-gap,
|
||||||
|
align: (left, center + horizon, left),
|
||||||
|
[
|
||||||
|
#text(font: body-font, size: cover-panel-meta-label, fill: cover-panel-meta-color)[
|
||||||
|
报告版本
|
||||||
|
]
|
||||||
|
#v(tw(0.5))
|
||||||
|
#text(font: body-font, size: cover-panel-meta-size, fill: cover-panel-title-color)[
|
||||||
|
#meta.version
|
||||||
|
]
|
||||||
|
],
|
||||||
|
box(width: cover-panel-meta-divider-width, height: tw(8), fill: cover-panel-footer-line-color),
|
||||||
|
[
|
||||||
|
#text(font: body-font, size: cover-panel-meta-label, fill: cover-panel-meta-color)[
|
||||||
|
发布日期
|
||||||
|
]
|
||||||
|
#v(tw(0.5))
|
||||||
|
#text(font: body-font, size: cover-panel-meta-size, fill: cover-panel-title-color)[
|
||||||
|
#date-text
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-panel-bottom(meta, date-text) = {
|
||||||
|
cover-panel-footer(meta, date-text)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-below-panel(meta, date-text) = {
|
||||||
|
block(height: cover-band-height)[
|
||||||
|
#pad(left: cover-footer-inset)[
|
||||||
|
#align(horizon)[
|
||||||
|
#grid(
|
||||||
|
columns: (auto, auto, auto),
|
||||||
|
column-gutter: cover-footer-column-gap,
|
||||||
|
align: bottom,
|
||||||
|
[
|
||||||
|
#text(font: heading-font, size: cover-footer-label, weight: "bold", fill: cover-footer-heading)[
|
||||||
|
单位
|
||||||
|
]
|
||||||
|
#v(cover-footer-line-gap)
|
||||||
|
#text(font: body-font, size: cover-footer-body, fill: cover-footer-text)[
|
||||||
|
#meta.company
|
||||||
|
]
|
||||||
|
#v(cover-footer-line-gap-tight)
|
||||||
|
#text(font: body-font, size: cover-footer-note, fill: cover-text-muted)[
|
||||||
|
智能矿石分选 · 技术方案与工程实施
|
||||||
|
]
|
||||||
|
],
|
||||||
|
box(width: 1pt, height: cover-footer-divider-height, fill: cover-footer-rule),
|
||||||
|
[
|
||||||
|
#text(font: heading-font, size: cover-footer-label, weight: "bold", fill: cover-footer-heading)[
|
||||||
|
信息
|
||||||
|
]
|
||||||
|
#v(cover-footer-line-gap)
|
||||||
|
#text(font: body-font, size: cover-footer-body, fill: cover-footer-text)[
|
||||||
|
文档类型 技术报告
|
||||||
|
]
|
||||||
|
#v(cover-footer-line-gap-tight)
|
||||||
|
#text(font: body-font, size: cover-footer-note, fill: cover-text-muted)[
|
||||||
|
#meta.brand · #meta.version · #date-text
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-page(meta, date: none) = {
|
||||||
|
let date-text = format-cover-date(date, meta.date)
|
||||||
|
let (title-line-1, title-line-2) = cover-title-lines(meta.title)
|
||||||
|
|
||||||
|
page(
|
||||||
|
paper: "a4",
|
||||||
|
margin: page-margin-cover,
|
||||||
|
fill: cover-bg,
|
||||||
|
header: none,
|
||||||
|
footer: none,
|
||||||
|
)[
|
||||||
|
#block(width: 100%, height: cover-body-height)[
|
||||||
|
#block(height: cover-band-height)[
|
||||||
|
#pad(left: cover-content-inset)[
|
||||||
|
#align(horizon)[
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
column-gutter: tw(3),
|
||||||
|
align: horizon,
|
||||||
|
cover-logo(),
|
||||||
|
[
|
||||||
|
#text(font: heading-font, size: cover-brand-size, weight: "bold", fill: cover-text)[
|
||||||
|
#meta.brand
|
||||||
|
]
|
||||||
|
#v(cover-footer-line-gap)
|
||||||
|
#text(font: body-font, size: cover-tagline-size, fill: cover-text-muted)[
|
||||||
|
#meta.company
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(cover-header-gap)
|
||||||
|
|
||||||
|
#pad(right: cover-panel-right-gap)[
|
||||||
|
#block(width: 100%, height: cover-panel-height, fill: cover-panel-fill)[
|
||||||
|
#pad(
|
||||||
|
left: cover-content-inset,
|
||||||
|
right: cover-margin-right,
|
||||||
|
top: cover-panel-inset-y,
|
||||||
|
bottom: cover-panel-inset-bottom-y,
|
||||||
|
)[
|
||||||
|
#block(width: 100%, height: 100%)[
|
||||||
|
#place(top + left)[
|
||||||
|
#block(width: 100%)[
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: cover-panel-kicker,
|
||||||
|
weight: "medium",
|
||||||
|
fill: cover-panel-kicker-color,
|
||||||
|
tracking: 0.08em,
|
||||||
|
)[TECHNICAL REPORT · 技术报告]
|
||||||
|
|
||||||
|
#v(cover-panel-title-outer-gap)
|
||||||
|
#cover-title-block(title-line-1, title-line-2)
|
||||||
|
|
||||||
|
#v(cover-panel-title-outer-gap)
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: size-cover-subtitle,
|
||||||
|
fill: cover-panel-subtitle-color,
|
||||||
|
tracking: 0.04em,
|
||||||
|
)[INTELLIGENT ORE SORTING · 智能矿石分选]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(left + horizon)[
|
||||||
|
#line(
|
||||||
|
length: cover-panel-rule-width,
|
||||||
|
stroke: cover-panel-accent-stroke + cover-panel-divider-color,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(bottom + left)[
|
||||||
|
#block(width: 100%, breakable: false)[
|
||||||
|
#cover-panel-bottom(meta, date-text)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(cover-below-gap)
|
||||||
|
#cover-below-panel(meta, date-text)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@
|
|||||||
stroke: 1pt + color-brand,
|
stroke: 1pt + color-brand,
|
||||||
)
|
)
|
||||||
content((x + w / 2, 0.5), align(center + horizon)[
|
content((x + w / 2, 0.5), align(center + horizon)[
|
||||||
#text(font: body-font, size: 8pt, fill: color-body)[#label]
|
#text(font: body-font, size: text-xs, fill: color-body)[#label]
|
||||||
])
|
])
|
||||||
if i < labels.len() - 1 {
|
if i < labels.len() - 1 {
|
||||||
line(
|
line(
|
||||||
@ -30,14 +30,3 @@
|
|||||||
#let register-report-glossary() = {
|
#let register-report-glossary() = {
|
||||||
register-glossary(glossary-entries)
|
register-glossary(glossary-entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let print-glossary-block() = {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
block(width: 100%, above: space-chapter)[
|
|
||||||
#box(width: 100%, fill: color-accent-surface, inset: (x: 10pt, y: 6pt))[
|
|
||||||
#text(font: heading-font, size: size-h1, weight: "black", fill: color-ink)[术语与缩写]
|
|
||||||
]
|
|
||||||
#v(space-block)
|
|
||||||
#print-glossary(glossary-entries, show-all: true)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
444
tech-report/data/metropole-grelin.typ
Normal file
444
tech-report/data/metropole-grelin.typ
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
#let transit-red = rgb("#c53a2f")
|
||||||
|
#let metro-blue = rgb("#005f9e")
|
||||||
|
#let deep-teal = rgb("#0f766e")
|
||||||
|
#let burnt-orange = rgb("#c96b2c")
|
||||||
|
#let emerald = rgb("#1f7a4f")
|
||||||
|
#let deep-violet = rgb("#5a4fcf")
|
||||||
|
|
||||||
|
#let page-numbering-started = state("page-numbering-started", false)
|
||||||
|
|
||||||
|
#let start-body-page-numbering() = {
|
||||||
|
page-numbering-started.update(true)
|
||||||
|
counter(page).update(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let metropole(
|
||||||
|
// -- Metadata --
|
||||||
|
title: none,
|
||||||
|
subtitle: none,
|
||||||
|
author: none,
|
||||||
|
date: none,
|
||||||
|
// -- Document --
|
||||||
|
paper-size: "a4",
|
||||||
|
language: "en",
|
||||||
|
date-format: "[day] [month repr:long] [year]",
|
||||||
|
cover-page: false,
|
||||||
|
inline-title: true,
|
||||||
|
// -- Page margins (override metropole defaults) --
|
||||||
|
margin-x: none,
|
||||||
|
margin-y: none,
|
||||||
|
header-skip: none,
|
||||||
|
// -- Fonts --
|
||||||
|
font-size: 11pt,
|
||||||
|
leading-ratio: 1.75,
|
||||||
|
body-font: "Source Serif 4",
|
||||||
|
heading-font: "Source Sans 3",
|
||||||
|
raw-font: "Source Code Pro",
|
||||||
|
// -- Colors --
|
||||||
|
background-color: rgb("#ffffff"),
|
||||||
|
foreground-color: rgb("000000"),
|
||||||
|
accent-color: transit-red,
|
||||||
|
// -- Body --
|
||||||
|
body,
|
||||||
|
) = {
|
||||||
|
// ── Type scale (major third × 1.25) --
|
||||||
|
let scale = 1.25
|
||||||
|
let fine-size = font-size * calc.pow(scale, -2) // ~7pt
|
||||||
|
let caption-size = font-size * calc.pow(scale, -1) // ~8.8pt
|
||||||
|
let lead-size = font-size * calc.pow(scale, 1) // ~13.75pt
|
||||||
|
let heading-size = font-size * calc.pow(scale, 2) // ~17.2pt
|
||||||
|
let display-size = font-size * calc.pow(scale, 3) // ~21.5pt
|
||||||
|
let title-size = font-size * calc.pow(scale, 4) // ~26.8pt
|
||||||
|
|
||||||
|
// ── Derived colors --
|
||||||
|
let secondary-content-color = color.mix(
|
||||||
|
(foreground-color, 5),
|
||||||
|
(background-color, 3),
|
||||||
|
space: oklab,
|
||||||
|
)
|
||||||
|
let secondary-accent-color = color.mix(
|
||||||
|
(accent-color, 2),
|
||||||
|
(background-color, 1),
|
||||||
|
space: oklab,
|
||||||
|
)
|
||||||
|
let block-bg-color = color.mix(
|
||||||
|
(background-color, 20),
|
||||||
|
(foreground-color, 1),
|
||||||
|
space: oklab,
|
||||||
|
)
|
||||||
|
let link-color = color.mix(
|
||||||
|
(accent-color, 3),
|
||||||
|
(foreground-color, 1),
|
||||||
|
space: oklab,
|
||||||
|
)
|
||||||
|
|
||||||
|
// ── Baseline grid --
|
||||||
|
let line-height = font-size * leading-ratio
|
||||||
|
|
||||||
|
// ── Spatial system (multiples of line-height) --
|
||||||
|
let margin-vertical = if margin-y != none { margin-y } else { line-height * 2.2 }
|
||||||
|
let margin-horizontal = if margin-x != none { margin-x } else { line-height * 2.8 }
|
||||||
|
let header-gap = if header-skip != none { header-skip } else { line-height * 1.1 }
|
||||||
|
|
||||||
|
// ── Configure metadata --
|
||||||
|
set document(title: title, date: date)
|
||||||
|
if author != none {
|
||||||
|
set document(author: author)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Configure text --
|
||||||
|
set text(
|
||||||
|
font: body-font,
|
||||||
|
size: font-size,
|
||||||
|
fill: foreground-color,
|
||||||
|
ligatures: true,
|
||||||
|
discretionary-ligatures: true,
|
||||||
|
lang: language,
|
||||||
|
)
|
||||||
|
show raw: set text(font: raw-font)
|
||||||
|
|
||||||
|
// ── Configure paragraphs --
|
||||||
|
set par(
|
||||||
|
leading: line-height - font-size,
|
||||||
|
spacing: line-height,
|
||||||
|
justify: true,
|
||||||
|
justification-limits: (
|
||||||
|
spacing: (
|
||||||
|
min: 100% * 2 / 3,
|
||||||
|
max: 100% * 3 / 2,
|
||||||
|
),
|
||||||
|
tracking: (
|
||||||
|
min: -0.01em,
|
||||||
|
max: 0.01em,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// ── Configure page --
|
||||||
|
set page(
|
||||||
|
paper: paper-size,
|
||||||
|
fill: background-color,
|
||||||
|
margin: (
|
||||||
|
x: margin-horizontal,
|
||||||
|
top: margin-vertical,
|
||||||
|
bottom: margin-vertical,
|
||||||
|
),
|
||||||
|
header: context {
|
||||||
|
if counter(page).get().first() > 1 {
|
||||||
|
v(header-gap)
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr),
|
||||||
|
align(left, text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
weight: "medium",
|
||||||
|
if author != none { author } else { "" },
|
||||||
|
)),
|
||||||
|
align(right, text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
weight: "medium",
|
||||||
|
title,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
v(line-height / 2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
header-ascent: line-height / 2,
|
||||||
|
footer: context {
|
||||||
|
v(line-height / 2)
|
||||||
|
if page-numbering-started.at(here()) {
|
||||||
|
align(right, text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
counter(page).display("1 / 1", both: true),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
footer-descent: line-height,
|
||||||
|
)
|
||||||
|
|
||||||
|
// ── Configure headings --
|
||||||
|
show heading.where(level: 1): it => context {
|
||||||
|
v(line-height * 2, weak: true)
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: heading-size,
|
||||||
|
weight: "bold",
|
||||||
|
fill: accent-color,
|
||||||
|
it.body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 2): it => context {
|
||||||
|
v(line-height * 2, weak: true)
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: lead-size,
|
||||||
|
weight: "bold",
|
||||||
|
fill: foreground-color,
|
||||||
|
it.body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
show heading.where(level: 3): it => {
|
||||||
|
v(line-height, weak: true)
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: font-size,
|
||||||
|
weight: "bold",
|
||||||
|
fill: foreground-color,
|
||||||
|
it.body,
|
||||||
|
)
|
||||||
|
v(line-height / 2, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Configure lists --
|
||||||
|
set list(
|
||||||
|
indent: 0pt,
|
||||||
|
body-indent: line-height / 2,
|
||||||
|
marker: (
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
fill: accent-color,
|
||||||
|
weight: "bold",
|
||||||
|
)[•],
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
fill: accent-color,
|
||||||
|
weight: "bold",
|
||||||
|
)[‣],
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
fill: accent-color,
|
||||||
|
weight: "bold",
|
||||||
|
)[–],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
set enum(
|
||||||
|
indent: 0pt,
|
||||||
|
body-indent: line-height / 2,
|
||||||
|
numbering: (..nums) => text(
|
||||||
|
font: heading-font,
|
||||||
|
fill: accent-color,
|
||||||
|
weight: "medium",
|
||||||
|
numbering("1.a.i.", ..nums),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
set terms(
|
||||||
|
indent: 0pt,
|
||||||
|
separator: h(0.5em, weak: true),
|
||||||
|
)
|
||||||
|
show terms.item: it => par({
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
weight: "medium",
|
||||||
|
fill: accent-color,
|
||||||
|
it.term,
|
||||||
|
)
|
||||||
|
h(0.5em)
|
||||||
|
it.description
|
||||||
|
})
|
||||||
|
|
||||||
|
// -- Configure block quotes --
|
||||||
|
show quote.where(block: true): it => {
|
||||||
|
v(line-height, weak: true)
|
||||||
|
block(width: 100%)[
|
||||||
|
#place(left + top, dy: -line-height / 2, text(
|
||||||
|
font: heading-font,
|
||||||
|
size: display-size * 2,
|
||||||
|
fill: block-bg-color,
|
||||||
|
weight: "bold",
|
||||||
|
["],
|
||||||
|
))
|
||||||
|
#pad(left: lead-size)[
|
||||||
|
#text(font: body-font, style: "italic", it.body)
|
||||||
|
#if it.attribution != none {
|
||||||
|
v(line-height / 2, weak: true)
|
||||||
|
align(right, text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
[— #it.attribution],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
v(line-height, weak: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Configure tables --
|
||||||
|
set table(
|
||||||
|
stroke: none,
|
||||||
|
inset: (x: line-height / 2, y: line-height / 2),
|
||||||
|
fill: (x, y) => if y == 0 {
|
||||||
|
accent-color
|
||||||
|
} else if calc.odd(y) {
|
||||||
|
block-bg-color
|
||||||
|
} else {
|
||||||
|
none
|
||||||
|
},
|
||||||
|
)
|
||||||
|
show table.cell.where(y: 0): it => {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
weight: "bold",
|
||||||
|
size: caption-size,
|
||||||
|
fill: background-color,
|
||||||
|
it,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Configure code --
|
||||||
|
show raw.where(block: true): block.with(
|
||||||
|
inset: (x: line-height, y: line-height / 2),
|
||||||
|
width: 100%,
|
||||||
|
fill: block-bg-color,
|
||||||
|
)
|
||||||
|
show raw.where(block: true): set par(justify: false)
|
||||||
|
show raw.where(block: false): box.with(
|
||||||
|
inset: (x: 3pt, y: 0pt),
|
||||||
|
outset: (y: 3pt),
|
||||||
|
fill: block-bg-color,
|
||||||
|
)
|
||||||
|
|
||||||
|
// ── Configure links --
|
||||||
|
show link: it => {
|
||||||
|
if type(it.dest) != str {
|
||||||
|
it
|
||||||
|
} else {
|
||||||
|
text(fill: link-color, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Title --
|
||||||
|
if cover-page {
|
||||||
|
// Full cover page
|
||||||
|
page(
|
||||||
|
margin: 0pt,
|
||||||
|
header: none,
|
||||||
|
footer: none,
|
||||||
|
)[
|
||||||
|
#place(left + top, rect(
|
||||||
|
width: line-height,
|
||||||
|
height: 100%,
|
||||||
|
fill: accent-color,
|
||||||
|
))
|
||||||
|
#pad(
|
||||||
|
left: line-height + margin-horizontal,
|
||||||
|
right: margin-horizontal,
|
||||||
|
top: margin-vertical * 2,
|
||||||
|
bottom: margin-vertical,
|
||||||
|
)[
|
||||||
|
#v(1fr)
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: title-size,
|
||||||
|
weight: "bold",
|
||||||
|
upper(title),
|
||||||
|
)
|
||||||
|
#v(line-height)
|
||||||
|
#if subtitle != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: heading-size,
|
||||||
|
weight: "light",
|
||||||
|
subtitle,
|
||||||
|
)
|
||||||
|
v(line-height)
|
||||||
|
}
|
||||||
|
#v(2fr)
|
||||||
|
#if author != none {
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr),
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
weight: "medium",
|
||||||
|
author,
|
||||||
|
),
|
||||||
|
align(right, if date != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
date.display(date-format),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if date != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
date.display(date-format),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
} else if inline-title {
|
||||||
|
// Inline title block on first page
|
||||||
|
// Accent bar bleeding to page edges
|
||||||
|
place(
|
||||||
|
left + top,
|
||||||
|
dx: -margin-horizontal,
|
||||||
|
dy: -margin-vertical,
|
||||||
|
rect(
|
||||||
|
width: line-height,
|
||||||
|
height: 100% + margin-vertical * 2,
|
||||||
|
fill: accent-color,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// Title block
|
||||||
|
v(line-height)
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: display-size,
|
||||||
|
weight: "bold",
|
||||||
|
upper(title),
|
||||||
|
)
|
||||||
|
v(line-height / 2)
|
||||||
|
if subtitle != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: lead-size,
|
||||||
|
weight: "light",
|
||||||
|
subtitle,
|
||||||
|
)
|
||||||
|
v(line-height / 2)
|
||||||
|
}
|
||||||
|
if author != none {
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr),
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
weight: "medium",
|
||||||
|
author,
|
||||||
|
),
|
||||||
|
align(right, if date != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
date.display("[day] [month repr:long] [year]"),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if date != none {
|
||||||
|
text(
|
||||||
|
font: heading-font,
|
||||||
|
size: caption-size,
|
||||||
|
fill: secondary-content-color,
|
||||||
|
date.display("[day] [month repr:long] [year]"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
v(line-height * 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Body --
|
||||||
|
body
|
||||||
|
}
|
||||||
8
tech-report/data/styling.typ
Normal file
8
tech-report/data/styling.typ
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
#let underline-accent(body) = underline(
|
||||||
|
body,
|
||||||
|
stroke: 1.5pt + color-accent,
|
||||||
|
offset: 4pt,
|
||||||
|
evade: true,
|
||||||
|
)
|
||||||
28
tech-report/data/tailwind.typ
Normal file
28
tech-report/data/tailwind.typ
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Tailwind CSS v3 默认刻度(1rem = 12pt,用于 Typst 印刷排版)
|
||||||
|
#let tw-rem = 12pt
|
||||||
|
|
||||||
|
// spacing:scale × 0.25rem(等同 Tailwind p-*, m-*, gap-*)
|
||||||
|
#let tw(scale) = scale * 0.25 * tw-rem
|
||||||
|
|
||||||
|
// font-size(等同 Tailwind text-*)
|
||||||
|
#let text-xs = 0.75 * tw-rem
|
||||||
|
#let text-sm = 0.875 * tw-rem
|
||||||
|
#let text-base = 1 * tw-rem
|
||||||
|
#let text-lg = 1.125 * tw-rem
|
||||||
|
#let text-xl = 1.25 * tw-rem
|
||||||
|
#let text-2xl = 1.5 * tw-rem
|
||||||
|
#let text-3xl = 1.875 * tw-rem
|
||||||
|
#let text-4xl = 2.25 * tw-rem
|
||||||
|
#let text-5xl = 3 * tw-rem
|
||||||
|
#let text-6xl = 3.75 * tw-rem
|
||||||
|
#let text-7xl = 4.5 * tw-rem
|
||||||
|
#let text-8xl = 6 * tw-rem
|
||||||
|
#let text-9xl = 8 * tw-rem
|
||||||
|
|
||||||
|
// line-height(等同 Tailwind leading-*,值为倍数)
|
||||||
|
#let leading-none = 1
|
||||||
|
#let leading-tight = 1.25
|
||||||
|
#let leading-snug = 1.375
|
||||||
|
#let leading-normal = 1.5
|
||||||
|
#let leading-relaxed = 1.625
|
||||||
|
#let leading-loose = 2
|
||||||
157
tech-report/data/theme.typ
Normal file
157
tech-report/data/theme.typ
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#import "../../brand/colors.typ": *
|
||||||
|
#import "tailwind.typ": *
|
||||||
|
|
||||||
|
// 技术报告 · 主色 #3052c8
|
||||||
|
#let color-primary = rgb("#3052c8")
|
||||||
|
#let color-accent = color-primary
|
||||||
|
#let color-accent-surface = color-primary.lighten(88%)
|
||||||
|
#let color-heading = color-ink
|
||||||
|
#let color-caption = rgb(110, 110, 110)
|
||||||
|
#let color-quote = rgb(90, 90, 90)
|
||||||
|
#let color-code-inline = color-ink
|
||||||
|
#let color-page = white
|
||||||
|
#let color-block-bg = color.mix(
|
||||||
|
(white, 20),
|
||||||
|
(color-ink, 1),
|
||||||
|
space: oklab,
|
||||||
|
)
|
||||||
|
|
||||||
|
#let code-token-keyword = color-ink
|
||||||
|
#let code-token-comment = rgb(130, 130, 130)
|
||||||
|
#let code-token-string = rgb(40, 40, 40)
|
||||||
|
#let code-token-number = rgb(70, 70, 70)
|
||||||
|
#let code-token-function = color-ink
|
||||||
|
#let code-token-operator = rgb(100, 100, 100)
|
||||||
|
|
||||||
|
// 字体:微软雅黑
|
||||||
|
#let report-font = ("Microsoft YaHei", "Microsoft YaHei UI")
|
||||||
|
#let heading-font = report-font
|
||||||
|
#let body-font = report-font
|
||||||
|
#let mono-font = report-font
|
||||||
|
|
||||||
|
// 正文(text-base · leading-normal)
|
||||||
|
#let size-body = text-base
|
||||||
|
#let leading-ratio = leading-normal
|
||||||
|
#let leading-body = size-body * leading-ratio - size-body
|
||||||
|
|
||||||
|
#let size-h1 = text-2xl
|
||||||
|
#let size-caption = text-sm
|
||||||
|
|
||||||
|
#let space-micro = tw(1)
|
||||||
|
#let space-block = tw(4)
|
||||||
|
#let space-section = tw(6)
|
||||||
|
#let space-chapter = tw(12)
|
||||||
|
|
||||||
|
#let image-max-width = 100%
|
||||||
|
|
||||||
|
#let code-block-fill = color-block-bg
|
||||||
|
#let code-block-radius = 0pt
|
||||||
|
#let code-inline-fill = color-block-bg
|
||||||
|
|
||||||
|
// --- 页面边距(A4 常用 2.5 cm)---
|
||||||
|
#let page-margin-a4 = 2.5cm
|
||||||
|
#let page-margin-x = page-margin-a4
|
||||||
|
#let page-margin-y = page-margin-a4
|
||||||
|
|
||||||
|
// --- 封面页边距(色块左贴边 · 上下等距)---
|
||||||
|
#let cover-margin-y = tw(8)
|
||||||
|
#let cover-margin-right = tw(8)
|
||||||
|
#let cover-content-inset = tw(11)
|
||||||
|
#let cover-footer-inset = cover-content-inset
|
||||||
|
#let cover-band-height = tw(24)
|
||||||
|
#let cover-header-est = cover-band-height
|
||||||
|
#let cover-footer-est = cover-band-height
|
||||||
|
#let cover-footer-line-gap-tight = tw(0.5)
|
||||||
|
#let cover-footer-line-gap = tw(0.75)
|
||||||
|
#let cover-footer-column-gap = tw(16)
|
||||||
|
#let cover-panel-right-gap = tw(24)
|
||||||
|
#let page-margin-cover = (
|
||||||
|
top: cover-margin-y,
|
||||||
|
bottom: cover-margin-y,
|
||||||
|
left: 0pt,
|
||||||
|
right: cover-margin-right,
|
||||||
|
)
|
||||||
|
|
||||||
|
// --- 封面(Proposal 色块布局 · 蓝色系)---
|
||||||
|
#let cover-bg = white
|
||||||
|
#let cover-text = color-ink
|
||||||
|
#let cover-text-muted = color-muted
|
||||||
|
#let cover-logo-size = tw(10)
|
||||||
|
#let cover-brand-size = text-base
|
||||||
|
#let cover-tagline-size = text-sm
|
||||||
|
#let cover-body-height = 25.7cm
|
||||||
|
#let cover-panel-gap-y = tw(6)
|
||||||
|
#let cover-header-gap = cover-panel-gap-y + cover-footer-est - cover-header-est
|
||||||
|
#let cover-below-gap = cover-panel-gap-y
|
||||||
|
#let cover-panel-fill = color-primary
|
||||||
|
#let cover-panel-height = cover-body-height - cover-header-est - cover-footer-est - cover-header-gap - cover-below-gap
|
||||||
|
#let cover-panel-inset-y = tw(18)
|
||||||
|
#let cover-panel-inset-bottom-y = tw(16)
|
||||||
|
#let cover-panel-text-gap = tw(4)
|
||||||
|
#let cover-panel-title-outer-gap = tw(5)
|
||||||
|
#let cover-panel-title-pull = -tw(8)
|
||||||
|
#let cover-quote-column-width = tw(40)
|
||||||
|
#let cover-panel-footer-rule-stroke = 2pt
|
||||||
|
#let cover-panel-meta-divider-width = 2pt
|
||||||
|
#let cover-panel-kicker = text-sm
|
||||||
|
#let cover-panel-kicker-color = white.transparentize(18%)
|
||||||
|
#let cover-panel-title-color = white
|
||||||
|
#let cover-panel-subtitle-color = white.transparentize(12%)
|
||||||
|
#let cover-panel-divider-color = white
|
||||||
|
#let cover-panel-accent-stroke = 3.5pt
|
||||||
|
#let cover-panel-line-color = white.transparentize(45%)
|
||||||
|
#let cover-panel-footer-line-color = white.transparentize(15%)
|
||||||
|
#let cover-panel-rule-width = tw(22)
|
||||||
|
#let cover-panel-meta-column-gap = tw(8)
|
||||||
|
#let cover-panel-author-size = text-base
|
||||||
|
#let cover-panel-role-size = text-sm
|
||||||
|
#let cover-panel-meta-size = text-sm
|
||||||
|
#let cover-panel-meta-label = text-xs
|
||||||
|
#let cover-panel-meta-color = white.transparentize(12%)
|
||||||
|
#let cover-quote-size = 16 * tw-rem
|
||||||
|
#let cover-quote-color = white.transparentize(8%)
|
||||||
|
#let cover-quote-clearance = cover-quote-column-width
|
||||||
|
#let cover-quote-offset-y = tw(0)
|
||||||
|
#let cover-panel-role-gap-before-line = tw(4)
|
||||||
|
#let cover-panel-meta-gap-after-line = tw(3)
|
||||||
|
#let cover-panel-footer-line-length = 78%
|
||||||
|
#let cover-footer-divider-height = tw(7.5)
|
||||||
|
#let cover-footer-label = text-sm
|
||||||
|
#let cover-footer-body = text-sm
|
||||||
|
#let cover-footer-note = text-xs
|
||||||
|
#let cover-footer-heading = color-ink
|
||||||
|
#let cover-footer-text = color-body
|
||||||
|
#let cover-footer-rule = color-muted.transparentize(55%)
|
||||||
|
#let size-cover-title = text-6xl
|
||||||
|
#let size-cover-title-line2 = text-7xl
|
||||||
|
#let size-cover-subtitle = text-lg
|
||||||
|
|
||||||
|
// --- 目录页 ---
|
||||||
|
#let toc-head-gap = tw(18)
|
||||||
|
#let toc-content-indent = tw(12)
|
||||||
|
#let summary-top-offset = tw(10)
|
||||||
|
#let summary-body-gap = tw(8)
|
||||||
|
#let toc-head-zh = text-4xl
|
||||||
|
#let toc-l2-color = color-muted.lighten(28%)
|
||||||
|
#let toc-head-color = toc-l2-color
|
||||||
|
#let toc-classification-label = "C3 Confidential"
|
||||||
|
#let toc-classification-size = text-xs
|
||||||
|
#let toc-classification-color = toc-l2-color
|
||||||
|
#let toc-classification-dx = -page-margin-x + tw(3)
|
||||||
|
#let toc-classification-dy = page-margin-y - tw(7)
|
||||||
|
#let toc-l1-number-width = tw(14)
|
||||||
|
#let toc-l1-number-title-gap = tw(11)
|
||||||
|
#let toc-l1-number-size = text-5xl
|
||||||
|
#let toc-l1-number-color = color-primary
|
||||||
|
#let toc-l1-size = text-base
|
||||||
|
#let toc-l2-size = text-sm
|
||||||
|
#let toc-page-size = text-sm
|
||||||
|
#let toc-l1-color = color-primary
|
||||||
|
#let toc-l1-leader-color = color-primary.lighten(22%)
|
||||||
|
#let toc-l2-leader-color = toc-l2-color.transparentize(35%)
|
||||||
|
#let toc-leader-dot-size = text-xs
|
||||||
|
#let toc-leader-gap = tw(0.5)
|
||||||
|
#let toc-l1-gap-above = tw(6)
|
||||||
|
#let toc-l1-gap-below = tw(2.5)
|
||||||
|
#let toc-l2-gap-above = tw(2.5)
|
||||||
|
#let toc-l2-gap-below = tw(2)
|
||||||
142
tech-report/data/toc.typ
Normal file
142
tech-report/data/toc.typ
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
#let toc-unnumbered-bodies = ([摘要], [术语与缩写], [术语与缩略语])
|
||||||
|
#let toc-chapter-counter = counter("toc-chapter")
|
||||||
|
|
||||||
|
#let toc-is-unnumbered(body) = {
|
||||||
|
toc-unnumbered-bodies.contains(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-register-chapter-counter() = doc => {
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
if not toc-is-unnumbered(it.body) {
|
||||||
|
toc-chapter-counter.step()
|
||||||
|
}
|
||||||
|
it
|
||||||
|
}
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-leader(leader-color) = {
|
||||||
|
box(
|
||||||
|
width: 1fr,
|
||||||
|
height: 0.9em,
|
||||||
|
clip: true,
|
||||||
|
align(horizon + left)[
|
||||||
|
#repeat[#text(size: toc-leader-dot-size, fill: leader-color)[·#h(toc-leader-gap)]]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-format-num(n) = {
|
||||||
|
if n < 10 {
|
||||||
|
"0" + str(n)
|
||||||
|
} else {
|
||||||
|
str(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-l1-chapter-num(entry) = {
|
||||||
|
toc-format-num(toc-chapter-counter.at(entry.element.location()).first())
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-number-cell(skip-number, entry) = {
|
||||||
|
box(width: toc-l1-number-width)[
|
||||||
|
#align(left)[
|
||||||
|
#if not skip-number [
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: toc-l1-number-size,
|
||||||
|
weight: "bold",
|
||||||
|
fill: toc-l1-number-color,
|
||||||
|
)[#toc-l1-chapter-num(entry)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-entry-show(it) = {
|
||||||
|
if it.level == 1 and toc-unnumbered-bodies.contains(it.body()) {
|
||||||
|
[]
|
||||||
|
} else if it.level == 1 {
|
||||||
|
let skip-number = toc-unnumbered-bodies.contains(it.body())
|
||||||
|
block(width: 100%, above: toc-l1-gap-above, below: toc-l1-gap-below)[
|
||||||
|
#grid(
|
||||||
|
columns: (toc-l1-number-width, toc-l1-number-title-gap, auto, 1fr, auto),
|
||||||
|
column-gutter: tw(2),
|
||||||
|
align: (left + horizon, left, left + horizon, horizon, horizon),
|
||||||
|
toc-number-cell(skip-number, it),
|
||||||
|
[],
|
||||||
|
text(font: heading-font, size: toc-l1-size, weight: "bold", fill: toc-l1-color)[
|
||||||
|
#it.body()
|
||||||
|
],
|
||||||
|
toc-leader(toc-l1-leader-color),
|
||||||
|
text(font: heading-font, size: toc-page-size, weight: "bold", fill: toc-l1-color)[
|
||||||
|
#it.page()
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
} else if it.level == 2 {
|
||||||
|
block(width: 100%, above: toc-l2-gap-above, below: toc-l2-gap-below)[
|
||||||
|
#grid(
|
||||||
|
columns: (toc-l1-number-width, toc-l1-number-title-gap, auto, 1fr, auto),
|
||||||
|
column-gutter: tw(2),
|
||||||
|
align: horizon,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
text(font: body-font, size: toc-l2-size, weight: "regular", fill: toc-l2-color)[
|
||||||
|
#it.body()
|
||||||
|
],
|
||||||
|
toc-leader(toc-l2-leader-color),
|
||||||
|
text(font: body-font, size: toc-page-size, fill: toc-l2-color)[#it.page()],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-classification-mark() = {
|
||||||
|
place(left + bottom, dx: toc-classification-dx, dy: toc-classification-dy)[
|
||||||
|
#text(
|
||||||
|
font: body-font,
|
||||||
|
size: toc-classification-size,
|
||||||
|
fill: toc-classification-color,
|
||||||
|
tracking: 0.04em,
|
||||||
|
)[
|
||||||
|
#rotate(-90deg, reflow: true)[#toc-classification-label]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let toc-page(meta) = {
|
||||||
|
let _ = meta
|
||||||
|
pagebreak(weak: true)
|
||||||
|
|
||||||
|
page(
|
||||||
|
header: none,
|
||||||
|
footer: none,
|
||||||
|
margin: (
|
||||||
|
top: page-margin-y,
|
||||||
|
bottom: page-margin-y,
|
||||||
|
left: page-margin-x,
|
||||||
|
right: page-margin-x,
|
||||||
|
),
|
||||||
|
)[
|
||||||
|
#block(width: 100%, height: 100%)[
|
||||||
|
#toc-classification-mark()
|
||||||
|
#block(width: 100%, below: space-chapter)[
|
||||||
|
#text(font: heading-font, size: toc-head-zh, weight: "bold", fill: toc-head-color)[
|
||||||
|
报告目录
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(toc-head-gap)
|
||||||
|
|
||||||
|
#pad(left: toc-content-indent)[
|
||||||
|
#show outline.entry: toc-entry-show
|
||||||
|
#outline(depth: 2, indent: 0pt, title: none)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
}
|
||||||
90
tech-report/report.typ
Normal file
90
tech-report/report.typ
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#import "data/config.typ": *
|
||||||
|
#import "data/theme.typ": *
|
||||||
|
#import "data/cover.typ": cover-page
|
||||||
|
#import "data/toc.typ": toc-page, toc-register-chapter-counter
|
||||||
|
#import "data/metropole-grelin.typ": metropole, start-body-page-numbering
|
||||||
|
#import "data/glossary.typ": init-glossary, register-report-glossary, print-glossary, glossary-entries, gls-long, gls-short
|
||||||
|
#import "data/diagrams.typ": ore-sorting-flow
|
||||||
|
#import "data/code.typ": codly-init-rule, codly-config, code-token-highlight-init
|
||||||
|
#import "data/md.typ": load-report-md
|
||||||
|
|
||||||
|
#show: codly-init-rule
|
||||||
|
#show: code-token-highlight-init
|
||||||
|
#show: init-glossary
|
||||||
|
#codly-config
|
||||||
|
|
||||||
|
#register-report-glossary()
|
||||||
|
|
||||||
|
#let report = load-report-md(
|
||||||
|
read(content-path),
|
||||||
|
source-path: content-path,
|
||||||
|
extra-scope: (
|
||||||
|
ore-sorting-flow: ore-sorting-flow,
|
||||||
|
gls-long: gls-long,
|
||||||
|
gls-short: gls-short,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
#let meta = report.metadata
|
||||||
|
|
||||||
|
#let parse-report-date(raw) = {
|
||||||
|
if type(raw) == datetime {
|
||||||
|
raw
|
||||||
|
} else if type(raw) == str {
|
||||||
|
let parts = raw.split("-")
|
||||||
|
if parts.len() == 3 {
|
||||||
|
datetime(
|
||||||
|
year: int(parts.at(0)),
|
||||||
|
month: int(parts.at(1)),
|
||||||
|
day: int(parts.at(2)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
none
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let report-date = parse-report-date(meta.date)
|
||||||
|
|
||||||
|
#cover-page(meta, date: report-date)
|
||||||
|
|
||||||
|
#show: metropole.with(
|
||||||
|
title: meta.title,
|
||||||
|
subtitle: none,
|
||||||
|
author: meta.brand,
|
||||||
|
date: report-date,
|
||||||
|
language: "zh",
|
||||||
|
paper-size: "a4",
|
||||||
|
cover-page: false,
|
||||||
|
inline-title: false,
|
||||||
|
accent-color: color-primary,
|
||||||
|
body-font: body-font,
|
||||||
|
heading-font: heading-font,
|
||||||
|
raw-font: mono-font,
|
||||||
|
font-size: size-body,
|
||||||
|
leading-ratio: leading-ratio,
|
||||||
|
margin-x: page-margin-x,
|
||||||
|
margin-y: page-margin-y,
|
||||||
|
)
|
||||||
|
|
||||||
|
#set heading(numbering: "1.1.1")
|
||||||
|
#show: toc-register-chapter-counter()
|
||||||
|
|
||||||
|
#toc-page(meta)
|
||||||
|
|
||||||
|
#if meta.summary != "" [
|
||||||
|
#v(summary-top-offset, weak: false)
|
||||||
|
#text(font: heading-font, size: size-h1, weight: "bold", fill: color-heading)[摘要]
|
||||||
|
#v(tw(3))
|
||||||
|
#meta.summary
|
||||||
|
#v(summary-body-gap)
|
||||||
|
]
|
||||||
|
|
||||||
|
#start-body-page-numbering()
|
||||||
|
|
||||||
|
#report.body
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
|
#heading(outlined: false, level: 1)[术语与缩写]
|
||||||
|
#print-glossary(glossary-entries, show-all: true)
|
||||||
File diff suppressed because it is too large
Load Diff
56
travel-plan/README.md
Normal file
56
travel-plan/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Travel Plan · 旅行计划
|
||||||
|
|
||||||
|
存放行程参考图、链接与笔记;后续可导出为 Typst/PDF 时间轴版式(见截图参考)。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
travel-plan/
|
||||||
|
├── plan.typ # 入口(排版占位,待完善)
|
||||||
|
├── data/
|
||||||
|
│ ├── config.typ # 行程结构(天 / 时段 / 地点)
|
||||||
|
│ └── theme.typ # 样式 token
|
||||||
|
├── trips/ # ★ 每次旅行一个子文件夹
|
||||||
|
│ └── <trip-name>/
|
||||||
|
│ ├── links.md # 参考链接(地图、攻略、订房等)
|
||||||
|
│ ├── notes.md # 可选:文字备忘
|
||||||
|
│ └── refs/ # 参考图,按地点分子目录
|
||||||
|
│ ├── donggang/
|
||||||
|
│ ├── xiaogang/
|
||||||
|
│ └── ...
|
||||||
|
└── local/ # 个人行程(gitignore,不提交)
|
||||||
|
```
|
||||||
|
|
||||||
|
| 放什么 | 路径 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 参考链接 | `trips/<名>/links.md` | Markdown 链接列表,按天或地点分组 |
|
||||||
|
| 参考图 | `trips/<名>/refs/<地点>/` | 文件名建议 `01-简短说明.jpg` |
|
||||||
|
| 文字备忘 | `trips/<名>/notes.md` | 穿搭、机位、tips |
|
||||||
|
| 个人私密行程 | `local/<名>/` | 整目录不提交 Git |
|
||||||
|
|
||||||
|
## 新建一次旅行
|
||||||
|
|
||||||
|
1. 复制 `trips/_example/` 为 `trips/dalian-2026/`(名字自定)
|
||||||
|
2. 在 `refs/` 下按地点建文件夹,把参考图丢进去
|
||||||
|
3. 在 `links.md` 里补地图、小红书、订房链接等
|
||||||
|
4. 需要出 PDF 时再改 `data/config.typ` 并编译 `plan.typ`
|
||||||
|
|
||||||
|
## 参考图命名建议
|
||||||
|
|
||||||
|
```
|
||||||
|
refs/xiaogang/
|
||||||
|
├── 01-亲海栈道主视觉.jpg
|
||||||
|
├── 02-慢走背影感.jpg
|
||||||
|
└── 03-双人构图参考.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
## 编译(占位)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
typst compile --root . travel-plan/plan.typ travel-plan/sample.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
## 版式参考
|
||||||
|
|
||||||
|
- **日程页**:D1 标题 + 摘要 + 左侧时间轴 + 卡片(时段 / 活动 / tips)
|
||||||
|
- **地点页**:地点标题 + 时段 + 说明 + 参考图网格(带 caption)
|
||||||
35
travel-plan/data/config.typ
Normal file
35
travel-plan/data/config.typ
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 指向 trips/ 下某次旅行;排版完善后从 refs/ 读取参考图
|
||||||
|
#let trip-id = "_example"
|
||||||
|
|
||||||
|
#let trip = (
|
||||||
|
title: "大连 · 示例行程",
|
||||||
|
subtitle: "落地放行李,中午就开始玩",
|
||||||
|
)
|
||||||
|
|
||||||
|
#let days = (
|
||||||
|
(
|
||||||
|
id: "D1",
|
||||||
|
title: "西安飞大连 · 东港 / 小岗开场",
|
||||||
|
summary: "第一天主打东港、亲海栈道、蓝调海边和夜景。",
|
||||||
|
stops: (
|
||||||
|
(
|
||||||
|
time: "06:40–08:55",
|
||||||
|
title: "西安飞大连",
|
||||||
|
note: "可在飞机上化妆,落地后酒店再补状态。",
|
||||||
|
active: true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
time: "10:00–12:00",
|
||||||
|
title: "酒店放行李 + 收拾状态",
|
||||||
|
note: "建议住中山区 / 东港附近,晚上动线更顺。",
|
||||||
|
active: false,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
time: "14:00–16:30",
|
||||||
|
title: "东港商务区",
|
||||||
|
note: "先拍现代建筑和海边步道,建立「大连城市感」。",
|
||||||
|
active: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
33
travel-plan/data/theme.typ
Normal file
33
travel-plan/data/theme.typ
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#import "/brand/colors.typ": *
|
||||||
|
|
||||||
|
#let color-primary = color-brand
|
||||||
|
#let color-heading = color-ink
|
||||||
|
#let color-text = color-body
|
||||||
|
#let color-text-light = color-muted
|
||||||
|
#let color-meta = rgb("#9ca3af")
|
||||||
|
#let color-card-border = rgb("#e5e7eb")
|
||||||
|
#let color-timeline = rgb("#d1d5db")
|
||||||
|
|
||||||
|
#let body-font = ("Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei")
|
||||||
|
#let heading-font = body-font
|
||||||
|
#let mono-font = ("Consolas", "Cascadia Mono")
|
||||||
|
|
||||||
|
#let size-label = 8pt
|
||||||
|
#let size-day = 22pt
|
||||||
|
#let size-title = 16pt
|
||||||
|
#let size-body = 10.5pt
|
||||||
|
#let size-time = 9pt
|
||||||
|
#let size-caption = 8.5pt
|
||||||
|
|
||||||
|
#let leading-body = size-body * 1.45
|
||||||
|
#let space-section = 18pt
|
||||||
|
#let space-card = 10pt
|
||||||
|
#let card-radius = 6pt
|
||||||
|
#let card-inset = 12pt
|
||||||
|
|
||||||
|
#let page-margin = (
|
||||||
|
top: 1.8cm,
|
||||||
|
bottom: 1.8cm,
|
||||||
|
left: 2cm,
|
||||||
|
right: 2cm,
|
||||||
|
)
|
||||||
101
travel-plan/plan.typ
Normal file
101
travel-plan/plan.typ
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#import "data/config.typ": *
|
||||||
|
#import "data/theme.typ": *
|
||||||
|
|
||||||
|
#set page(paper: "a4", margin: page-margin, fill: white)
|
||||||
|
#set text(font: body-font, size: size-body, fill: color-text, lang: "zh")
|
||||||
|
#set par(leading: leading-body, spacing: 0pt, justify: false)
|
||||||
|
|
||||||
|
#let schedule-label() = {
|
||||||
|
text(font: mono-font, size: size-label, fill: color-meta, tracking: 0.08em)[DETAILED SCHEDULE]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let day-badge(id) = {
|
||||||
|
box(
|
||||||
|
width: 1.35em,
|
||||||
|
height: 1.35em,
|
||||||
|
radius: 50%,
|
||||||
|
fill: color-heading,
|
||||||
|
inset: 0pt,
|
||||||
|
)[
|
||||||
|
#align(center + horizon)[
|
||||||
|
#text(font: heading-font, size: 11pt, weight: "bold", fill: white)[#id]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let timeline-dot(active: false) = {
|
||||||
|
box(
|
||||||
|
width: if active { 8pt } else { 6pt },
|
||||||
|
height: if active { 8pt } else { 6pt },
|
||||||
|
radius: 50%,
|
||||||
|
fill: if active { color-heading } else { color-timeline },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let stop-card(stop) = {
|
||||||
|
box(
|
||||||
|
width: 100%,
|
||||||
|
stroke: 0.6pt + color-card-border,
|
||||||
|
radius: card-radius,
|
||||||
|
inset: card-inset,
|
||||||
|
)[
|
||||||
|
#text(font: mono-font, size: size-time, fill: color-meta)[#stop.time]
|
||||||
|
#v(0.35em)
|
||||||
|
#text(font: heading-font, size: size-title, weight: "bold", fill: color-heading)[#stop.title]
|
||||||
|
#if stop.note != "" [
|
||||||
|
#v(0.45em)
|
||||||
|
#text(fill: color-text-light)[#stop.note]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#let day-section(day) = block(breakable: true, below: space-section)[
|
||||||
|
#schedule-label()
|
||||||
|
#v(0.6em)
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
column-gutter: 0.55em,
|
||||||
|
align: horizon,
|
||||||
|
day-badge(day.id),
|
||||||
|
text(font: heading-font, size: size-day, weight: "bold", fill: color-heading)[#day.title],
|
||||||
|
)
|
||||||
|
#v(0.45em)
|
||||||
|
#text(fill: color-text-light)[#day.summary]
|
||||||
|
#v(0.9em)
|
||||||
|
#for (i, stop) in day.stops.enumerate() [
|
||||||
|
#grid(
|
||||||
|
columns: (16pt, 1fr),
|
||||||
|
column-gutter: 10pt,
|
||||||
|
align: (center, top),
|
||||||
|
box(width: 16pt)[
|
||||||
|
#align(center)[
|
||||||
|
#timeline-dot(active: stop.active)
|
||||||
|
#if i < day.stops.len() - 1 [
|
||||||
|
#v(-0.2em)
|
||||||
|
#box(width: 1pt, height: 4.2em, fill: color-timeline)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
stop-card(stop),
|
||||||
|
)
|
||||||
|
#if i < day.stops.len() - 1 [#v(space-card)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#align(left)[
|
||||||
|
#text(font: heading-font, size: 20pt, weight: "bold", fill: color-primary)[#trip.title]
|
||||||
|
#v(0.3em)
|
||||||
|
#text(fill: color-text-light)[#trip.subtitle]
|
||||||
|
#v(1.2em)
|
||||||
|
]
|
||||||
|
|
||||||
|
#for day in days [
|
||||||
|
#day-section(day)
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1em)
|
||||||
|
#align(left)[
|
||||||
|
#text(size: size-caption, fill: color-meta)[
|
||||||
|
参考图与链接见 #raw("trips/" + trip-id + "/") — 排版占位,地点图区待接 refs/
|
||||||
|
]
|
||||||
|
]
|
||||||
837
travel-plan/sample.pdf
Normal file
837
travel-plan/sample.pdf
Normal file
@ -0,0 +1,837 @@
|
|||||||
|
%PDF-1.7
|
||||||
|
%€€€€
|
||||||
|
|
||||||
|
1 0 obj
|
||||||
|
<</Type/Pages/Count 1/Kids[67 0 R]>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<</Type/StructTreeRoot/RoleMap<</Datetime/Span/Terms/Part/Title/P/Strong/Span/Em/Span>>/K[33 0 R]/ParentTree<</Nums[0 3 0 R]>>/ParentTreeNextKey 1>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
[4 0 R 4 0 R 4 0 R 5 0 R 6 0 R 7 0 R 9 0 R 9 0 R 9 0 R 9 0 R 9 0 R 12 0 R 14 0 R 15 0 R 16 0 R 20 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 26 0 R 27 0 R 28 0 R 32 0 R 32 0 R 31 0 R 32 0 R 32 0 R 32 0 R 32 0 R]
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 33 0 R/K[0 1 2]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 33 0 R/K[3]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 33 0 R/K[4]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 8 0 R/K[5]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 11 0 R/K[7 0 R]>>
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<</Type/StructElem/S/Span/P 10 0 R/A[<</O/Layout/Placement/Block>>]/K[6 7 8 9 10]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
10 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 11 0 R/K[9 0 R]>>
|
||||||
|
endobj
|
||||||
|
11 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 33 0 R/K[8 0 R 10 0 R]>>
|
||||||
|
endobj
|
||||||
|
12 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 33 0 R/K[11]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
13 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 18 0 R/K[]>>
|
||||||
|
endobj
|
||||||
|
14 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 17 0 R/K[12]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
15 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 17 0 R/K[13]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
16 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 17 0 R/K[14]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
17 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 18 0 R/K[14 0 R 15 0 R 16 0 R]>>
|
||||||
|
endobj
|
||||||
|
18 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 33 0 R/K[13 0 R 17 0 R]>>
|
||||||
|
endobj
|
||||||
|
19 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 24 0 R/K[]>>
|
||||||
|
endobj
|
||||||
|
20 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 23 0 R/K[15]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
21 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 23 0 R/K[16 17 18]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
22 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 23 0 R/K[19 20 21]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
23 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 24 0 R/K[20 0 R 21 0 R 22 0 R]>>
|
||||||
|
endobj
|
||||||
|
24 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 33 0 R/K[19 0 R 23 0 R]>>
|
||||||
|
endobj
|
||||||
|
25 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 30 0 R/K[]>>
|
||||||
|
endobj
|
||||||
|
26 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 29 0 R/K[22]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
27 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 29 0 R/K[23]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
28 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 29 0 R/K[24]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
29 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 30 0 R/K[26 0 R 27 0 R 28 0 R]>>
|
||||||
|
endobj
|
||||||
|
30 0 obj
|
||||||
|
<</Type/StructElem/S/Div/P 33 0 R/K[25 0 R 29 0 R]>>
|
||||||
|
endobj
|
||||||
|
31 0 obj
|
||||||
|
<</Type/StructElem/S/Code/P 32 0 R/Lang(en)/K[27]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
32 0 obj
|
||||||
|
<</Type/StructElem/S/P/P 33 0 R/K[25 26 31 0 R 28 29 30 31]/Pg 67 0 R>>
|
||||||
|
endobj
|
||||||
|
33 0 obj
|
||||||
|
<</Type/StructElem/S/Document/P 2 0 R/K[4 0 R 5 0 R 6 0 R 11 0 R 12 0 R 18 0 R 24 0 R 30 0 R 32 0 R]>>
|
||||||
|
endobj
|
||||||
|
34 0 obj
|
||||||
|
[/ICCBased 99 0 R]
|
||||||
|
endobj
|
||||||
|
35 0 obj
|
||||||
|
[/ICCBased 100 0 R]
|
||||||
|
endobj
|
||||||
|
36 0 obj
|
||||||
|
<</ProcSet[/PDF/Text/ImageC/ImageB]/ColorSpace<</c0 34 0 R/c1 35 0 R>>/Font<</f0 37 0 R/f1 40 0 R/f2 43 0 R/f3 46 0 R/f4 49 0 R/f5 52 0 R/f6 55 0 R/f7 58 0 R/f8 61 0 R/f9 64 0 R>>>>
|
||||||
|
endobj
|
||||||
|
37 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/KBDGOZ+MicrosoftYaHeiUI-Bold/Encoding/Identity-H/DescendantFonts[38 0 R]/ToUnicode 69 0 R>>
|
||||||
|
endobj
|
||||||
|
38 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/KBDGOZ+MicrosoftYaHeiUI-Bold/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 39 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 697.2656 1 26 1000]>>
|
||||||
|
endobj
|
||||||
|
39 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/KBDGOZ+MicrosoftYaHeiUI-Bold/Flags 131076/FontBBox[2.9296875 -137.20703 996.09375 837.40234]/ItalicAngle 0/Ascent 812.0117/Descent -253.41797/CapHeight 756.34766/StemV 168.6/CIDSet 68 0 R/FontFile2 70 0 R>>
|
||||||
|
endobj
|
||||||
|
40 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/EOVZXV+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[41 0 R]/ToUnicode 72 0 R>>
|
||||||
|
endobj
|
||||||
|
41 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/EOVZXV+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 42 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 642.08984 1 1 260.2539 2 2 267.57812]>>
|
||||||
|
endobj
|
||||||
|
42 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/EOVZXV+SegoeUIVariable/Flags 131076/FontBBox[42.96875 0 562.5 682.6172]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 71 0 R/FontFile2 73 0 R>>
|
||||||
|
endobj
|
||||||
|
43 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/XZKLJD+MicrosoftYaHeiUI/Encoding/Identity-H/DescendantFonts[44 0 R]/ToUnicode 75 0 R>>
|
||||||
|
endobj
|
||||||
|
44 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/XZKLJD+MicrosoftYaHeiUI/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 45 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 697.2656 1 84 1000]>>
|
||||||
|
endobj
|
||||||
|
45 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/XZKLJD+MicrosoftYaHeiUI/Flags 131076/FontBBox[1.953125 -143.0664 997.0703 843.2617]/ItalicAngle 0/Ascent 812.0117/Descent -253.41797/CapHeight 756.34766/StemV 95.4/CIDSet 74 0 R/FontFile2 76 0 R>>
|
||||||
|
endobj
|
||||||
|
46 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/WXVVVC+Consolas/Encoding/Identity-H/DescendantFonts[47 0 R]/ToUnicode 78 0 R>>
|
||||||
|
endobj
|
||||||
|
47 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/WXVVVC+Consolas/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 48 0 R/DW 0/CIDToGIDMap/Identity/W[0 21 549.8047]>>
|
||||||
|
endobj
|
||||||
|
48 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/WXVVVC+Consolas/Flags 131077/FontBBox[4.8828125 -8.7890625 544.9219 646.97266]/ItalicAngle 0/Ascent 742.6758/Descent -257.32422/CapHeight 638.1836/StemV 95.4/CIDSet 77 0 R/FontFile2 79 0 R>>
|
||||||
|
endobj
|
||||||
|
49 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/BAYDIT+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[50 0 R]/ToUnicode 81 0 R>>
|
||||||
|
endobj
|
||||||
|
50 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/BAYDIT+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 51 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 645.5078 1 1 737.3047 2 2 435.0586]>>
|
||||||
|
endobj
|
||||||
|
51 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/BAYDIT+SegoeUIVariable/Flags 131076/FontBBox[4.8828125 0 701.1719 715.8203]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 80 0 R/FontFile2 82 0 R>>
|
||||||
|
endobj
|
||||||
|
52 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/VEVAMH+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[53 0 R]/ToUnicode 84 0 R>>
|
||||||
|
endobj
|
||||||
|
53 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/VEVAMH+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 54 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 641.1133 1 1 257.32422 2 2 266.60156 3 3 448.2422]>>
|
||||||
|
endobj
|
||||||
|
54 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/VEVAMH+SegoeUIVariable/Flags 131076/FontBBox[-6.3476562 -99.609375 562.0117 700.1953]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 83 0 R/FontFile2 85 0 R>>
|
||||||
|
endobj
|
||||||
|
55 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/FZYZJG+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[56 0 R]/ToUnicode 87 0 R>>
|
||||||
|
endobj
|
||||||
|
56 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/FZYZJG+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 57 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 643.5547 1 1 267.08984 2 2 705.0781]>>
|
||||||
|
endobj
|
||||||
|
57 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/FZYZJG+SegoeUIVariable/Flags 131076/FontBBox[80.078125 0 590.33203 682.6172]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 86 0 R/FontFile2 88 0 R>>
|
||||||
|
endobj
|
||||||
|
58 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/XWXGBP+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[59 0 R]/ToUnicode 90 0 R>>
|
||||||
|
endobj
|
||||||
|
59 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/XWXGBP+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 60 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 645.5078 1 1 273.92578 2 2 389.64844]>>
|
||||||
|
endobj
|
||||||
|
60 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/XWXGBP+SegoeUIVariable/Flags 131076/FontBBox[-3.90625 -104.00391 564.4531 700.1953]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 89 0 R/FontFile2 91 0 R>>
|
||||||
|
endobj
|
||||||
|
61 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/UBLLTL+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[62 0 R]/ToUnicode 93 0 R>>
|
||||||
|
endobj
|
||||||
|
62 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/UBLLTL+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 63 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 653.3203 1 1 273.92578 2 2 1007.8125 3 3 363.76953 4 4 540.03906 5 5 328.125 6 6 439.45312 7 7 400.39062]>>
|
||||||
|
endobj
|
||||||
|
63 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/UBLLTL+SegoeUIVariable/Flags 131076/FontBBox[-1.953125 -104.98047 1003.90625 751.9531]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 92 0 R/FontFile2 94 0 R>>
|
||||||
|
endobj
|
||||||
|
64 0 obj
|
||||||
|
<</Type/Font/Subtype/Type0/BaseFont/SDHMZN+DejaVuSansMono/Encoding/Identity-H/DescendantFonts[65 0 R]/ToUnicode 96 0 R>>
|
||||||
|
endobj
|
||||||
|
65 0 obj
|
||||||
|
<</Type/Font/Subtype/CIDFontType2/BaseFont/SDHMZN+DejaVuSansMono/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 66 0 R/DW 0/CIDToGIDMap/Identity/W[0 12 602.0508]>>
|
||||||
|
endobj
|
||||||
|
66 0 obj
|
||||||
|
<</Type/FontDescriptor/FontName/SDHMZN+DejaVuSansMono/Flags 131077/FontBBox[0 -235.83984 602.0508 765.1367]/ItalicAngle 0/Ascent 759.7656/Descent -240.23438/CapHeight 759.7656/StemV 95.4/CIDSet 95 0 R/FontFile2 97 0 R>>
|
||||||
|
endobj
|
||||||
|
67 0 obj
|
||||||
|
<</Type/Page/Resources 36 0 R/MediaBox[0 0 595.2756 841.8898]/StructParents 0/Parent 1 0 R/Contents 98 0 R>>
|
||||||
|
endobj
|
||||||
|
68 0 obj
|
||||||
|
<</Length 12/Filter/FlateDecode>>
|
||||||
|
stream
|
||||||
|
xœûÿÿÿ | ||||||