dexin-content
v0.3.2
Published
Open content toolchain — Markdown → LessonAST/ContentPackage compiler, CLI and validator (dexinlabs ecosystem).
Maintainers
Readme
dexin-content
得心实验室的结构化内容编译与运行时 package。
负责与具体业务领域无关的通用内容管线:
- Compile:将带 frontmatter 的 Markdown 编译成中性 Content AST,再经宿主注入的
DomainParser产出稳定的 PositiveArtifact - Store:Artifact 与索引(ContentIndex)的 FS/Memory 抽象
- Query:按 id / URL path / collection / 条件过滤对 Artifact 做只读查询
- Collection:集合声明、发现、批量编译与增量变化检测
- Diff:Canonical JSON 序列化与对象级差异原语(Golden/Regress 管线使用)
为内容作者
- 格式规范:docs/content-format.md —— 目录结构、front-matter、块/容器/数学语法、错误码、自检命令、投稿 SOP(§14)
- 示例课:example/ —— 可直接编译通过的最小内容仓样例
- 社区投稿:proposals/ —— 课程稿件投放区,PR + 门禁校验(
npm run validate:proposals)+ 人审后迁入私有成品仓
目录范围
dexin-content 是通用层:
core/编译核心(types / compiler / parser / artifact)domains/lesson/内置 lesson 域 parser(其余域由宿主自行注入)cli/flow 编排(flowBuild/flowPackage/flowValidate/flowCheck/flowServe库 API;CLI 子命令仅有build与help,其余 flow 经子路径作库消费)browser/浏览器宿主入口(compileLesson,零 Node API;见./compile)scripts/仓内脚本(不在发布包 files 内,仅供本地开发/测试;也不作为公开 API)
宿主应用负责域扩展(DomainParser)、编排脚本与内容文件所有权,通过 exports 里的子路径消费本 package。
安装
需要 Node.js ≥ 20。Package 以 TypeScript 源码形式分发(
*.ts),宿主应通过tsx、Nuxt/Vite 等支持 TS 解析的工具链使用。
npm install dexin-content公开 API 边界
唯一公共 API 边界是 package.json 中 exports 字段。只使用下列路径:
| 子路径 | 暴露内容 |
|---|---|
| . | 门面:核心类型 + DomainParserRegistry / compile + ArtifactStore / ContentQuery + defineCollection / resolveCollections / discover / compileCollections |
| ./core/types | 类型:Inline 家族(TextInline / BoldInline / ItalicInline / CodeInline / LinkInline / FormulaInline) / Identity / DocumentIdentity / StructuredIdentity / Meta / PositiveArtifact / Artifact / ParseError / ParseContext / Schema / DomainParser / DomainName(LessonAST 块类型在 ./core/types/lessonAST) |
| ./core/compiler | compile、CompileInput、CompileResult、DomainParserRegistry |
| ./core/discovery | buildDocumentIdentity / buildStructuredIdentity / normaliseRel / readSourceFile / IdentityKind / CollectionConfig / SourceFile |
| ./core/frontmatter | splitFrontmatter / parseFrontmatter / validateSchema / projectMeta |
| ./store | ArtifactStore 接口 + createFsArtifactStore / createMemoryArtifactStore + ContentIndex / IndexEntry |
| ./collection | defineCollection / resolveCollections / compileCollections / recompileChanged / createLocalSource / createMemorySource / SourceAdapter / ResolvedCollection / CollectionDefinition |
| ./query | ContentQuery (byId / byPath / list / collection) + QueryOptions |
| ./diff | toCanonicalJSON / sortKeysDeep / stripUnderscoreKeysGolden / underscorePrefixedPaths / firstDiff / shortStr |
| ./core/markdown | Markdown → 中性 AST 解析(parseDocument 等);插件组可经 setMarkdownPluginSet 注入(浏览器宿主用) |
| ./compile | 浏览器宿主入口:compileLesson(md, {file?}) → CompileResult(静态导入 unified/remark 插件组,与 CLI 编译语义同源;零 Node API) |
| ./core/types/lessonAST | LessonAST 类型与常量 |
| ./domains/lesson | 内置 lesson 域:lessonParser / buildLessonIdentity / mapBlocks |
| ./cli/build | flowBuild(目录发现 → compile → Artifact Store + index.json) |
| ./cli/package | flowPackage(按 manifest 打包 ContentPackage) |
| ./cli/validate | flowValidate |
| ./cli/check | flowCheck |
| ./cli/serve | flowServe(dev preview HTTP 服务) |
任何未列入上表的内部路径均不保证稳定。
快速示例
最简用法是走 CLI(仅编译内置 lesson 域):
# 单文件:AST 打印到 stdout,失败非零退出
npx dexin-content build example/lessons/getting-started/hello-lesson/minimal.md --domain lesson
# 整树:编译 + 按 manifest 打包 ContentPackage
npx dexin-content build example --manifest example/content-manifest.json --out /tmp/dexin-out库 API(宿主自行编排时)用内置 lessonParser 经 DomainParserRegistry 注入:
import { DomainParserRegistry, compile } from 'dexin-content/core/compiler'
import { lessonParser } from 'dexin-content/domains/lesson'
import { buildLessonIdentity } from 'dexin-content/domains/lesson'
const registry = new DomainParserRegistry()
registry.register(lessonParser)
const result = compile(
{
fixture: 'getting-started/hello-lesson/minimal',
domain: 'lesson',
identity: buildLessonIdentity('minimal', 'getting-started', 'hello-lesson', 'lessons/getting-started/hello-lesson/minimal.md'),
source: '---\ntitle: 最小的一节课\norder: 1\n---\n\n## 这就是全部了\n',
file: 'lessons/getting-started/hello-lesson/minimal.md',
},
registry,
)
if (result.kind === 'error') throw result.error
else console.log(result.artifact.content.blocks)compile() 永不抛异常,失败以 { kind: 'error', error } 返回。域扩展由宿主注入其它 DomainParser。
开发
# 依赖
npm install
# 类型检查(唯一静态门禁)
npm run typecheck
# 仓内自检测(脚本自建临时 fixture,无需任何本地产物)
npm run runtime:check
# 预发布 tarball 内容检查
npm run packLicense
Apache-2.0 © 得心实验室。详见 LICENSE。
