Initialize local Tabularium documentation monorepo
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
node_modules/
|
||||
.next/
|
||||
out/
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.egg-info/
|
||||
*.tsbuildinfo
|
||||
.DS_Store
|
||||
.env*
|
||||
!.env.example
|
||||
@@ -0,0 +1,10 @@
|
||||
# Tabularium working agreements
|
||||
|
||||
- 本仓库专门维护 Endor 文档与制图脚本。所有开发、构建、制图、检查在本地执行,不添加远程 CI、部署、托管或容器运行流程。
|
||||
- Web 技术栈为 TypeScript、React、Tailwind CSS、Next.js Pages Router;不要切换到 App Router。
|
||||
- 使用 pnpm 管理 JavaScript workspace,使用 uv 管理 `tools/figures` 的 Python 项目,保留两套锁文件。
|
||||
- Markdown 正文放在 `content/docs`,Python 图形源码放在 `tools/figures/src/endor_figures`,可复现的 SVG 输出放在 `apps/docs/public/figures`。
|
||||
- 未确认的架构提议明确标注为草案,不能表述为现有实现。
|
||||
- 开发与预览服务只监听 `127.0.0.1`。
|
||||
- 对 gitea.entroia.com 仅使用 codex-bot,提交身份为 Codex Bot <codex-bot@gitea.entroia.local>。SSH 使用隔离配置:`ssh -F /dev/null -o IdentitiesOnly=yes -i /Users/zzyang/.codex/credentials/gitea-entroia/codex_entroia_ed25519 -p 22222`。
|
||||
- 每个可验证阶段完成后提交并推送当前远程分支;远程尚未创建时保留本地提交并说明原因。不借用其他账户、不强推。
|
||||
@@ -0,0 +1,41 @@
|
||||
# Endor · Tabularium
|
||||
|
||||
Endor 文档与制图 monorepo。Tabularium 取古罗马档案馆之意。
|
||||
|
||||
## 本地开发
|
||||
|
||||
需要 Node.js 22.13+(推荐 LTS)、pnpm 11.25、Python 3.11+ 和 uv。
|
||||
首次安装依赖需要访问软件包源;站点、制图和检查均在本机运行。
|
||||
|
||||
```sh
|
||||
pnpm install --frozen-lockfile
|
||||
uv sync --project tools/figures --locked
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
访问 http://127.0.0.1:3000 。站点无外部字体或 CDN 资源。
|
||||
|
||||
```text
|
||||
apps/docs/ Next.js Pages Router + React + TypeScript + Tailwind CSS
|
||||
content/docs/ Markdown 文档源,文件名成为 /docs/<slug> 路由
|
||||
tools/figures/ 独立 Python 项目,使用 drawsvg 编程制图
|
||||
```
|
||||
|
||||
## 命令
|
||||
|
||||
- `pnpm dev`:本地开发,修改 Markdown 后刷新页面即可读取新内容。
|
||||
- `pnpm figures`:运行 Python 制图,更新 `apps/docs/public/figures`。
|
||||
- `pnpm lint` / `pnpm typecheck`:前端静态检查。
|
||||
- `pnpm build`:构建文档站。
|
||||
- `pnpm start`:在本地预览已构建站点。
|
||||
- `pnpm check`:依次执行 lint、类型检查、制图与构建。
|
||||
|
||||
文档标题取首个 `# 标题`,文档排序按文件名。普通 Markdown 与 GFM 表格可用,嵌入图使用 `/figures/<name>.svg`。不解析原始 HTML。
|
||||
|
||||
生产构建会生成文档路由;新增或修改文档后重新运行 build。开发模式按请求读取内容。
|
||||
所有工作流只在本地执行,不配置 CI 或部署。远程 Git 仅用于保存和同步源码。
|
||||
|
||||
## Git 远程
|
||||
|
||||
请创建空仓库 `endorphin-tabularium-docs`,不要初始化 README 或许可证。
|
||||
得到实际仓库地址后再添加 origin 并推送。不要假定仓库所有者或使用其他用户凭据。
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defineConfig, globalIgnores } from "eslint/config";
|
||||
import nextVitals from "eslint-config-next/core-web-vitals";
|
||||
import nextTs from "eslint-config-next/typescript";
|
||||
|
||||
export default defineConfig([
|
||||
...nextVitals,
|
||||
...nextTs,
|
||||
globalIgnores([".next/**", "out/**", "next-env.d.ts"]),
|
||||
]);
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/types/routes.d.ts";
|
||||
import "./.next/types/root-params.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const config: NextConfig = {
|
||||
reactStrictMode: true,
|
||||
poweredByHeader: false,
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@endor/docs",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "NEXT_TELEMETRY_DISABLED=1 next dev --hostname 127.0.0.1",
|
||||
"build": "NEXT_TELEMETRY_DISABLED=1 next build",
|
||||
"start": "NEXT_TELEMETRY_DISABLED=1 next start --hostname 127.0.0.1",
|
||||
"lint": "eslint . --max-warnings=0",
|
||||
"typecheck": "NEXT_TELEMETRY_DISABLED=1 next typegen && tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "16.4.3",
|
||||
"react": "19.3.1",
|
||||
"react-dom": "19.3.1",
|
||||
"react-markdown": "10.1.0",
|
||||
"remark-gfm": "4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "4.3.3",
|
||||
"@tailwindcss/typography": "0.5.20",
|
||||
"@types/node": "22.20.5",
|
||||
"@types/react": "19.3.0",
|
||||
"@types/react-dom": "19.3.0",
|
||||
"eslint": "^9.39.5",
|
||||
"eslint-config-next": "16.4.3",
|
||||
"postcss": "8.5.31",
|
||||
"tailwindcss": "4.3.3",
|
||||
"typescript": "~5.9.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
const config = { plugins: { "@tailwindcss/postcss": {} } };
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="960" height="240" viewBox="0 0 960 240">
|
||||
<defs>
|
||||
</defs>
|
||||
<title>Local figure workflow</title>
|
||||
<rect x="0" y="0" width="960" height="240" fill="#f5f5f0" rx="16" />
|
||||
<text x="32" y="42" font-size="16" fill="#57534e" font-family="sans-serif">TABULARIUM / FIGURE WORKFLOW</text>
|
||||
<rect x="32" y="80" width="272" height="120" rx="12" fill="#ffffff" stroke="#a8a29e" />
|
||||
<text x="50" y="126" font-size="20" fill="#134e4a" font-family="sans-serif">Python source</text>
|
||||
<text x="50" y="164" font-size="14" fill="#57534e" font-family="monospace">tools/figures</text>
|
||||
<path d="M312,140 L334,140" stroke="#0f766e" stroke-width="2" />
|
||||
<path d="M329,135 L334,140 L329,145" fill="none" stroke="#0f766e" stroke-width="2" />
|
||||
<rect x="344" y="80" width="272" height="120" rx="12" fill="#ffffff" stroke="#a8a29e" />
|
||||
<text x="362" y="126" font-size="20" fill="#134e4a" font-family="sans-serif">SVG asset</text>
|
||||
<text x="362" y="164" font-size="14" fill="#57534e" font-family="monospace">apps/docs/public/figures</text>
|
||||
<path d="M624,140 L646,140" stroke="#0f766e" stroke-width="2" />
|
||||
<path d="M641,135 L646,140 L641,145" fill="none" stroke="#0f766e" stroke-width="2" />
|
||||
<rect x="656" y="80" width="272" height="120" rx="12" fill="#ffffff" stroke="#a8a29e" />
|
||||
<text x="674" y="126" font-size="20" fill="#134e4a" font-family="sans-serif">Local documentation</text>
|
||||
<text x="674" y="164" font-size="14" fill="#57534e" font-family="monospace">content/docs</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,25 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const directory = path.resolve(process.cwd(), "../../content/docs");
|
||||
const validSlug = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
||||
|
||||
export type DocLink = { slug: string; title: string };
|
||||
export type Doc = DocLink & { content: string };
|
||||
|
||||
export async function readDoc(slug: string): Promise<Doc> {
|
||||
if (!validSlug.test(slug)) throw new Error("Invalid document slug");
|
||||
const content = await fs.readFile(path.join(directory, `${slug}.md`), "utf8");
|
||||
const title = content.match(/^# (.+)$/m)?.[1]?.trim() ?? slug;
|
||||
return { slug, title, content };
|
||||
}
|
||||
|
||||
export async function listDocs(): Promise<DocLink[]> {
|
||||
const files = (await fs.readdir(directory)).filter((file) =>
|
||||
file.endsWith(".md") && validSlug.test(file.slice(0, -3)),
|
||||
).sort();
|
||||
return Promise.all(files.map(async (file) => {
|
||||
const { slug, title } = await readDoc(file.slice(0, -3));
|
||||
return { slug, title };
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { AppProps } from "next/app";
|
||||
import "@/styles/globals.css";
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Html, Head, Main, NextScript } from "next/document";
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="zh-CN">
|
||||
<Head />
|
||||
<body><Main /><NextScript /></body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next";
|
||||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { listDocs, readDoc, type Doc, type DocLink } from "@/lib/docs";
|
||||
|
||||
type Props = { doc: Doc; docs: DocLink[] };
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => ({
|
||||
paths: (await listDocs()).map(({ slug }) => ({ params: { slug } })),
|
||||
fallback: false,
|
||||
});
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
|
||||
const slug = params?.slug;
|
||||
if (typeof slug !== "string") return { notFound: true };
|
||||
const docs = await listDocs();
|
||||
if (!docs.some((doc) => doc.slug === slug)) return { notFound: true };
|
||||
return { props: { doc: await readDoc(slug), docs } };
|
||||
};
|
||||
|
||||
export default function DocPage({ doc, docs }: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return (
|
||||
<>
|
||||
<Head><title>{doc.title} · Tabularium</title></Head>
|
||||
<div className="mx-auto max-w-7xl px-6 py-8">
|
||||
<header className="border-b border-stone-200 pb-6"><Link href="/" className="text-sm font-semibold tracking-widest">ENDOR / TABULARIUM</Link></header>
|
||||
<a href="#content" className="sr-only focus:not-sr-only">跳到正文</a>
|
||||
<div className="grid gap-10 py-10 md:grid-cols-[220px_minmax(0,1fr)] md:gap-16">
|
||||
<nav aria-label="文档导航" className="flex flex-wrap gap-2 self-start md:sticky md:top-8 md:flex-col">
|
||||
{docs.map((item) => <Link key={item.slug} href={`/docs/${item.slug}`} aria-current={item.slug === doc.slug ? "page" : undefined} className={`rounded-lg px-3 py-2 text-sm ${item.slug === doc.slug ? "bg-teal-50 font-medium text-teal-900" : "text-stone-600 hover:bg-stone-100"}`}>{item.title}</Link>)}
|
||||
</nav>
|
||||
<main id="content" className="min-w-0 max-w-3xl">
|
||||
<article className="prose prose-stone max-w-none prose-headings:tracking-tight prose-a:text-teal-800 prose-pre:bg-stone-900 prose-img:rounded-xl">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>{doc.content}</ReactMarkdown>
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { GetStaticProps, InferGetStaticPropsType } from "next";
|
||||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import { listDocs, type DocLink } from "@/lib/docs";
|
||||
|
||||
export const getStaticProps: GetStaticProps<{ docs: DocLink[] }> = async () => ({
|
||||
props: { docs: await listDocs() },
|
||||
});
|
||||
|
||||
export default function Home({ docs }: InferGetStaticPropsType<typeof getStaticProps>) {
|
||||
return (
|
||||
<>
|
||||
<Head><title>Tabularium · Endor 文档</title><meta name="description" content="Endor 的本地文档、架构设计与制图档案。" /></Head>
|
||||
<main className="mx-auto max-w-5xl px-6 py-16 md:py-24">
|
||||
<div className="flex items-center justify-between border-b border-stone-200 pb-6 text-sm">
|
||||
<span className="font-semibold tracking-widest">ENDOR / TABULARIUM</span>
|
||||
<span className="rounded-full border border-stone-200 px-3 py-1 text-stone-500">本地文档工作台</span>
|
||||
</div>
|
||||
<p className="mt-16 text-sm tracking-widest text-teal-800">文档 · 设计 · 图形</p>
|
||||
<h1 className="mt-4 text-5xl font-semibold tracking-tight md:text-7xl">Endor 的知识档案。</h1>
|
||||
<p className="mt-6 max-w-2xl text-lg leading-8 text-stone-600">记录系统概念、架构讨论和开发约定,让文字与图形一起演进。</p>
|
||||
<div className="mt-14 grid gap-4 md:grid-cols-2">
|
||||
{docs.map((doc, index) => (
|
||||
<Link key={doc.slug} href={`/docs/${doc.slug}`} className="group rounded-xl border border-stone-200 bg-white p-6 transition hover:border-teal-700 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-teal-700">
|
||||
<span className="font-mono text-xs text-stone-400">{String(index + 1).padStart(2, "0")}</span>
|
||||
<h2 className="mt-4 text-xl font-medium group-hover:text-teal-800">{doc.title} <span aria-hidden="true">↗</span></h2>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
@theme {
|
||||
--font-sans: ui-sans-serif, system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
body { background: #fafaf8; color: #292524; }
|
||||
::selection { background: #ccfbf1; }
|
||||
.prose table { display: block; overflow-x: auto; }
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# 开始使用
|
||||
|
||||
Tabularium 是 Endor 的本地文档工作台。文档与图形源码都保存在同一个仓库。
|
||||
|
||||
## 启动
|
||||
|
||||
在仓库根目录运行:
|
||||
|
||||
```sh
|
||||
pnpm install --frozen-lockfile
|
||||
uv sync --project tools/figures --locked
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
浏览器打开 http://127.0.0.1:3000 。
|
||||
|
||||
## 添加文档
|
||||
|
||||
在 `content/docs` 下添加 Markdown 文件,例如 `04-runtime.md`。文件名使用小写字母、数字和连字符;第一个一级标题是导航标题。该文件对应 `/docs/04-runtime`。
|
||||
|
||||
开发模式下刷新页面读取修改;本地生产预览需要重新构建。
|
||||
|
||||
## 检查
|
||||
|
||||
```sh
|
||||
pnpm check
|
||||
pnpm start
|
||||
```
|
||||
|
||||
所有命令都在本地运行。Git 远程只负责源码同步,不承担构建或部署。
|
||||
@@ -0,0 +1,25 @@
|
||||
# 节点与对象挂载(草案)
|
||||
|
||||
> 状态:讨论草案。以下记录当前设计方向,不代表协议已经实现或接口已经定稿。
|
||||
|
||||
## 设计方向
|
||||
|
||||
每一个 Aster VM 是一个节点。实例之间可以通过统一接入协议挂载对象。
|
||||
|
||||
接入对象来源包含 Endor 官方配件,例如 Tessera GUI,以及通过 Endor Python、C、Go、JavaScript 等 SDK 接入的第三方程序。这两类接入采用同一套协议。
|
||||
|
||||
## 待确认的术语
|
||||
|
||||
| 概念 | 当前提议 | 状态 |
|
||||
| --- | --- | --- |
|
||||
| Node | 一个 Aster VM | 用户提出的模型 |
|
||||
| Endpoint | 统一协议的连接端点 | 术语提议 |
|
||||
| Export Root | 对外导出的顶级对象入口 | 术语提议 |
|
||||
| Tessera 顶级对象 | 协议层称 root,挂载名可为 tessera | 尚未确定 |
|
||||
|
||||
## 后续设计问题
|
||||
|
||||
- 对象的导出、身份、远程引用与生命周期。
|
||||
- 方法调用、属性访问和事件传播的语义。
|
||||
- 授权、断连、错误与重新连接。
|
||||
- 官方配件和不同语言 SDK 的共同协议边界。
|
||||
@@ -0,0 +1,17 @@
|
||||
# 图形与脚本
|
||||
|
||||
Python 绘图项目位于 `tools/figures`,使用 drawsvg 输出可编辑 SVG。脚本与输出都保留在 Git 中。
|
||||
|
||||
```sh
|
||||
pnpm figures
|
||||
```
|
||||
|
||||
下图是制图工作流的最小示例,用于验证从 Python 源码到文档图片的完整链路。
|
||||
|
||||

|
||||
|
||||
## 扩展方式
|
||||
|
||||
在 `tools/figures/src/endor_figures` 下保留各张图的生成逻辑,并在 CLI 中调用。输出目录通过源码位置计算,不依赖运行命令时所在的目录。
|
||||
|
||||
图形应使用本地字体与资源,并明确标注草案状态。未来可按具体需求加入自动布局、PNG 转换或 TypeScript SVG 工具。
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "endorphin-tabularium-docs",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@11.25.0",
|
||||
"engines": {
|
||||
"node": ">=22.13.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "pnpm --filter @endor/docs run dev",
|
||||
"build": "pnpm --filter @endor/docs run build",
|
||||
"start": "pnpm --filter @endor/docs run start",
|
||||
"lint": "pnpm --filter @endor/docs run lint",
|
||||
"typecheck": "pnpm --filter @endor/docs run typecheck",
|
||||
"figures": "uv run --locked --project tools/figures endor-figures",
|
||||
"check": "pnpm run lint && pnpm run typecheck && pnpm run figures && pnpm run build"
|
||||
}
|
||||
}
|
||||
Generated
+5111
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
packages:
|
||||
- apps/*
|
||||
saveExact: true
|
||||
allowBuilds:
|
||||
unrs-resolver: true
|
||||
@@ -0,0 +1,13 @@
|
||||
[project]
|
||||
name = "endor-figures"
|
||||
version = "0.1.0"
|
||||
description = "Local, reproducible Endor documentation figures"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["drawsvg>=2.4,<3"]
|
||||
|
||||
[project.scripts]
|
||||
endor-figures = "endor_figures.cli:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling>=1.27,<2"]
|
||||
build-backend = "hatchling.build"
|
||||
@@ -0,0 +1 @@
|
||||
"""Reproducible figures for the Endor documentation."""
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Generate local SVG assets without external fonts or rendering services."""
|
||||
from pathlib import Path
|
||||
import drawsvg as draw
|
||||
|
||||
|
||||
def main() -> None:
|
||||
root = Path(__file__).resolve().parents[4]
|
||||
output = root / "apps/docs/public/figures/workflow.svg"
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
diagram = draw.Drawing(960, 240)
|
||||
diagram.append_title("Local figure workflow")
|
||||
diagram.append(draw.Rectangle(0, 0, 960, 240, fill="#f5f5f0", rx=16))
|
||||
diagram.append(draw.Text("TABULARIUM / FIGURE WORKFLOW", 16, 32, 42,
|
||||
fill="#57534e", font_family="sans-serif"))
|
||||
for index, (title, subtitle) in enumerate([
|
||||
("Python source", "tools/figures"),
|
||||
("SVG asset", "apps/docs/public/figures"),
|
||||
("Local documentation", "content/docs"),
|
||||
]):
|
||||
x = 32 + index * 312
|
||||
diagram.append(draw.Rectangle(x, 80, 272, 120, rx=12,
|
||||
fill="#ffffff", stroke="#a8a29e"))
|
||||
diagram.append(draw.Text(title, 20, x + 18, 126,
|
||||
fill="#134e4a", font_family="sans-serif"))
|
||||
diagram.append(draw.Text(subtitle, 14, x + 18, 164,
|
||||
fill="#57534e", font_family="monospace"))
|
||||
if index < 2:
|
||||
diagram.append(draw.Line(x + 280, 140, x + 302, 140,
|
||||
stroke="#0f766e", stroke_width=2))
|
||||
diagram.append(draw.Lines(x + 297, 135, x + 302, 140,
|
||||
x + 297, 145, fill="none",
|
||||
stroke="#0f766e", stroke_width=2))
|
||||
diagram.save_svg(str(output))
|
||||
print(f"Generated {output.relative_to(root)}")
|
||||
Generated
+23
@@ -0,0 +1,23 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.11"
|
||||
|
||||
[[package]]
|
||||
name = "drawsvg"
|
||||
version = "2.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/86/ec/a88a29dc4e380c6283fa6922a21c715ec40bf40f7b53859f8a104a7cbe26/drawsvg-2.4.2.tar.gz", hash = "sha256:5efd8bcdc2c2400425e7fb71b4b80d8fdd83b1dc810f790f58a165df33ddd303", size = 733210, upload-time = "2026-08-12T03:24:43.679Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/15/5a/c47c10de42c49a3a9957123d77e5692b56b4fbc342b55285b52c41a8f1c1/drawsvg-2.4.2-py3-none-any.whl", hash = "sha256:b1c101e187aa395cb13c039549e4f26fb7b7ee03974f53dc9798436463781bf1", size = 44175, upload-time = "2026-08-12T03:24:42.531Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endor-figures"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "drawsvg" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "drawsvg", specifier = ">=2.4,<3" }]
|
||||
Reference in New Issue
Block a user