init of repo

This commit is contained in:
2026-09-04 01:48:30 +08:00
parent d2776f71af
commit 8447db4693
4 changed files with 174 additions and 111 deletions
+59
View File
@@ -0,0 +1,59 @@
#import "../NLI-doc-template.typ": cover, conf
#let mark-unit = 1.2cm
#let mark-blue = rgb("#4FC3F7")
#let mark-letter(column, row, letter) = place(
top + left,
dx: (3.6 + column * 2.5) * mark-unit,
dy: row * mark-unit,
box(
width: 2.5 * mark-unit,
height: 3 * mark-unit,
inset: 0pt,
align(center + horizon, text(
font: "Source Code Pro",
size: 72pt,
weight: "medium",
fill: mark-blue,
)[#letter]),
),
)
#let nitrac-mark = {
mark-letter(0, 0, "T")
mark-letter(1, 1, "R")
mark-letter(2, 2, "A")
mark-letter(3, 3, "C")
}
#cover(
title: "荷城创新实时与控制系统",
title-en: "Nitload Realtime and Control",
logo: nitrac-mark,
number: "NITRAC-DOC-1B",
author: "Nitload Industry",
classification: "MID[中秘]SEC",
date: "2026 年 9 月",
)
#show: conf.with(number-pages: true)
= 第一章 总则
本文档为 NITRAC 系列标准文档第一册草案。
== 1.1 范围
本节规定文档的适用范围。
== 1.2 规范性引用文件
本节列出编制和实施本标准所需的规范性引用文件。
= 第二章 术语和定义
本节规定本文档使用的术语和定义。
= 第三章 技术要求
本节规定 NITRAC 的技术要求。
+115 -111
View File
@@ -50,12 +50,12 @@
title: none, // 主标题(中文) title: none, // 主标题(中文)
title-en: none, // 主标题(英文,Source Code Pro 自行排版) title-en: none, // 主标题(英文,Source Code Pro 自行排版)
subtitle: none, // 副标题 subtitle: none, // 副标题
logo: none, // 图片路径,如 image("logo.png") logo: none, // 图片路径,如 image("logo.png")
number: none, // 文档编号 number: none, // 文档编号
author: none, // 作者(可为单个字符串或数组) author: none, // 作者(可为单个字符串或数组)
classification: none, // 密级,如 "内部"、"秘密" classification: none, // 密级,如 "内部"、"秘密"
info: (:), // 附加信息字典,如 (学号: "123", 指导教师: "张三") info: (:), // 附加信息字典,如 (学号: "123", 指导教师: "张三")
date: none, // 日期 date: none, // 日期
fill: white, // 封面背景色 fill: white, // 封面背景色
decorate: true, // 是否绘制天蓝/暖橙网格装饰色块 decorate: true, // 是否绘制天蓝/暖橙网格装饰色块
) = { ) = {
@@ -69,6 +69,10 @@
) )
set text(font: (cover-latin, cover-cjk), lang: "zh") set text(font: (cover-latin, cover-cjk), lang: "zh")
if logo != none {
logo
}
// 网格装饰:NITLOAD 标识(坐标 (x, y) = (列, 行))。 // 网格装饰:NITLOAD 标识(坐标 (x, y) = (列, 行))。
if decorate { if decorate {
// 天蓝色实心单位正方形 // 天蓝色实心单位正方形
@@ -86,18 +90,18 @@
glyph(1, i, ch, if i == 0 { accent } else { sky }) glyph(1, i, ch, if i == 0 { accent } else { sky })
} }
// 主标题:中文逐字对齐网格,连续西文按实际字宽紧凑排布。 // 主标题:中文逐字对齐网格,连续西文按实际字宽紧凑排布。
let cs = if type(title) == str { title.clusters() } else { () } let cs = if type(title) == str { title.clusters() } else { () }
// 中文视觉重心偏大,整体右移 0.1 格、下移 0.2 格 // 中文视觉重心偏大,整体右移 0.1 格、下移 0.2 格
let cn-dx = 0.1 * unit let cn-dx = 0.1 * unit
let cn-dy = 0.2 * unit let cn-dy = 0.2 * unit
let is-narrow = c => str.to-unicode(c.codepoints().first()) < 0x2E80 let is-narrow = c => str.to-unicode(c.codepoints().first()) < 0x2E80
// 西文开头时使用更明确的 0.2 格左边距,与西文标题和信息区形成视觉对齐。 // 西文开头时使用更明确的 0.2 格左边距,与西文标题和信息区形成视觉对齐。
let title-start-pad = if cs.len() > 0 and is-narrow(cs.first()) { 0.2 * unit } else { cn-dx } let title-start-pad = if cs.len() > 0 and is-narrow(cs.first()) { 0.2 * unit } else { cn-dx }
let title-width = 21cm - unit - title-start-pad let title-width = 21cm - unit - title-start-pad
let en-left-pad = 0.2 * unit let en-left-pad = 0.2 * unit
let en-box-width = 21cm - unit let en-box-width = 21cm - unit
// 分段:连续西文合为一段,其余每字一段 // 分段:连续西文合为一段,其余每字一段
let segs = () let segs = ()
let run = "" let run = ""
@@ -110,66 +114,66 @@
} }
if run != "" { segs.push(run) } if run != "" { segs.push(run) }
context { context {
// CJK 固定占一格;连续西文使用字体测得的自然宽度,不额外预留左右空白。 // CJK 固定占一格;连续西文使用字体测得的自然宽度,不额外预留左右空白。
let cur-x = 0pt let cur-x = 0pt
let row = 0 let row = 0
for seg in segs { for seg in segs {
let latin = is-narrow(seg.first()) let latin = is-narrow(seg.first())
let segment = text( let segment = text(
font: if latin { (cover-latin, cover-cjk) } else { (cover-cjk, cover-latin) }, font: if latin { (cover-latin, cover-cjk) } else { (cover-cjk, cover-latin) },
size: glyph-size, size: glyph-size,
fill: black, fill: black,
)[#seg] )[#seg]
let segment-width = if latin { measure(segment).width } else { unit } let segment-width = if latin { measure(segment).width } else { unit }
if cur-x != 0pt and cur-x + segment-width > title-width { if cur-x != 0pt and cur-x + segment-width > title-width {
cur-x = 0pt cur-x = 0pt
row += 1 row += 1
} }
let segment-align = if latin { left + horizon } else { center + horizon } let segment-align = if latin { left + horizon } else { center + horizon }
place(top + left, place(top + left,
dx: unit + title-start-pad + cur-x, dx: unit + title-start-pad + cur-x,
dy: (7 + row) * unit + cn-dy, dy: (7 + row) * unit + cn-dy,
box( box(
width: segment-width, width: segment-width,
height: unit, height: unit,
inset: 0pt, inset: 0pt,
align(segment-align, segment), align(segment-align, segment),
)) ))
cur-x += segment-width cur-x += segment-width
} }
let cn-rows = if segs.len() == 0 { 0 } else { row + 1 } let cn-rows = if segs.len() == 0 { 0 } else { row + 1 }
// 英文:左对齐于中文下方;多行时行距对齐网格(行距 = unit),左/上边距相等。 // 英文:左对齐于中文下方;多行时行距对齐网格(行距 = unit),左/上边距相等。
let en-rows = 0 let en-rows = 0
let en-gap = if cn-rows > 0 and title-en != none { 0.25 * unit } else { 0pt } let en-gap = if cn-rows > 0 and title-en != none { 0.25 * unit } else { 0pt }
if title-en != none { if title-en != none {
let en1 = text(font: (cover-latin, cover-cjk), size: glyph-size, fill: black)[#title-en] let en1 = text(font: (cover-latin, cover-cjk), size: glyph-size, fill: black)[#title-en]
let lh = measure(en1).height let lh = measure(en1).height
let pad = (unit - lh) / 2 let pad = (unit - lh) / 2
let inner = { let inner = {
set par(leading: unit - lh) set par(leading: unit - lh)
en1 en1
} }
let h = measure(box(width: en-box-width - en-left-pad, inner)).height let h = measure(box(width: en-box-width - en-left-pad, inner)).height
en-rows = calc.max(1, int(calc.round((h - lh) / unit)) + 1) en-rows = calc.max(1, int(calc.round((h - lh) / unit)) + 1)
place(top + left, place(top + left,
dx: unit, dx: unit,
dy: (7 + cn-rows) * unit + en-gap, dy: (7 + cn-rows) * unit + en-gap,
box(width: en-box-width, inset: (left: en-left-pad, top: pad), inner)) box(width: en-box-width, inset: (left: en-left-pad, top: pad), inner))
} }
let title-rows = cn-rows + en-rows let title-rows = cn-rows + en-rows
let title-end-y = (7 + title-rows) * unit + en-gap let title-end-y = (7 + title-rows) * unit + en-gap
let metadata = () let metadata = ()
if number != none { metadata.push(("编号", number)) } if number != none { metadata.push(("编号", number)) }
if author != none { if author != none {
let author-text = if type(author) == array { author.join(" / ") } else { author } let author-text = if type(author) == array { author.join(" / ") } else { author }
metadata.push(("作者", author-text)) metadata.push(("作者", author-text))
} }
if date != none { metadata.push(("日期", date)) } if date != none { metadata.push(("日期", date)) }
if classification != none { metadata.push(("密级", classification)) } if classification != none { metadata.push(("密级", classification)) }
for (key, value) in info { for (key, value) in info {
if value != none { metadata.push((str(key), value)) } if value != none { metadata.push((str(key), value)) }
} }
let marker-height = 2 * unit let marker-height = 2 * unit
@@ -228,17 +232,17 @@
(unit, apex-y), (unit, apex-y),
(0pt, marker-height), (0pt, marker-height),
)) ))
let signature-line-length = 7 * unit let signature-line-length = 7 * unit
place(top + left, dx: unit, dy: meta-y + apex-y, place(top + left, dx: unit, dy: meta-y + apex-y,
line(length: signature-line-length, stroke: (paint: accent, thickness: 0.8pt))) line(length: signature-line-length, stroke: (paint: accent, thickness: 0.8pt)))
let signed-label = text( let signed-label = text(
font: cover-latin, size: 10pt, weight: "bold", fill: accent, font: cover-latin, size: 10pt, weight: "bold", fill: accent,
)[signed] )[signed]
let signed-size = measure(signed-label) let signed-size = measure(signed-label)
place(top + left, place(top + left,
dx: unit + signature-line-length - signed-size.width, dx: unit + signature-line-length - signed-size.width,
dy: meta-y + apex-y - signed-size.height - 0.04 * unit, dy: meta-y + apex-y - signed-size.height - 0.04 * unit,
signed-label) signed-label)
// 三角形保留在距页底七个单位的位置,作为独立的封面装饰。 // 三角形保留在距页底七个单位的位置,作为独立的封面装饰。
// 文档信息不再与三角形连线,而是跟随主标题实际高度,排列在标题正下方。 // 文档信息不再与三角形连线,而是跟随主标题实际高度,排列在标题正下方。
@@ -264,17 +268,17 @@
number-align: center, number-align: center,
header: none, // 正文页不使用装饰角标 header: none, // 正文页不使用装饰角标
) )
set text(font: (body-latin, body-cjk), lang: "zh", size: 12pt) set text(font: (body-latin, body-cjk), lang: "zh", size: 12pt)
set par(justify: true, leading: 1em, first-line-indent: (amount: 2em, all: true)) set par(justify: true, leading: 1em, first-line-indent: (amount: 2em, all: true))
// 无序列表整体缩进一个正文字符;圆点与正文仍使用 Typst 默认间距。 // 无序列表整体缩进一个正文字符;圆点与正文仍使用 Typst 默认间距。
set list(indent: 1em) set list(indent: 1em)
// 标题字体:中文黑体,英文 Source Code Pro // 标题字体:中文黑体,英文 Source Code Pro
show heading: set text(font: (cover-latin, cover-cjk)) show heading: set text(font: (cover-latin, cover-cjk))
// 代码块与行内代码:西文使用 Source Code Pro,中文显式回退到正文宋体。 // 代码块与行内代码:西文使用 Source Code Pro,中文显式回退到正文宋体。
// 避免 Source Code Pro 缺少中文字形时由系统选择到隶书等不合适字体。 // 避免 Source Code Pro 缺少中文字形时由系统选择到隶书等不合适字体。
show raw: set text(font: (mono-font, body-cjk)) show raw: set text(font: (mono-font, body-cjk))
// 块级代码:细边框、浅色背景与自动行号;行内代码不受影响。 // 块级代码:细边框、浅色背景与自动行号;行内代码不受影响。
show raw.where(block: true): code => { show raw.where(block: true): code => {
@@ -302,31 +306,31 @@
doc doc
} }
// ---- 模板结束 ---- // ---- 模板结束 ----
// Template file ended. // Template file ended.
/* /*
Legacy duplicated tail retained as an inert comment because this workspace's Legacy duplicated tail retained as an inert comment because this workspace's
Windows patch transport does not reliably truncate shortened files. Windows patch transport does not reliably truncate shortened files.
breakable: true, breakable: true,
code, code,
) )
} }
doc doc
} }
// ---- 模板结束 ---- // ---- 模板结束 ----
// Template file ended. // Template file ended.
}
doc
}
// ---- 模板结束 ----
// Template file ended.
*/
// End of file. }
doc
}
// ---- 模板结束 ----
// Template file ended.
*/
// End of file.