diff --git a/README.ja.md b/README.ja.md index 08cc837f..5e7ff54b 100644 --- a/README.ja.md +++ b/README.ja.md @@ -180,7 +180,7 @@ curl -fsSL https://edgeever.org/install.sh | bash ### Telegram コミュニティ -EdgeEver の使い方、AI Agent の実例、費用対効果の高い / 無料の AI 資源、自動化の流れを話す場です。 +EdgeEver コミュニティへようこそ。Vibe Coding や AI を探求する仲間が集まり、最先端の AI 生産性と個人ナレッジベースのベストプラクティスを共有しています。 👉 [EdgeEver の Telegram グループに参加](https://t.me/+wwUx1BYLrIdiZjY1) @@ -287,6 +287,7 @@ EdgeEver は無料のオープンソースプロジェクトです。クロス - ノート製品の設計は、[Evernote](https://evernote.com/) や [Notion](https://www.notion.com/) など成熟したノートツールの公開されている製品体験も参考にしています。関連機能は EdgeEver が独自に設計し、実装しています。 - マインドマップと視覚的な図のノートは、[XMind](https://xmind.com/) と [ProcessOn](https://www.processon.com/) の公開されている製品体験を参考にしています。関連機能は EdgeEver が独自に設計し、実装しています。 +- EdgeEver のポスターデザイン機能は、向阳乔木(joeseesun)の [Qiaomu Design](https://github.com/joeseesun/qiaomu-cover-design) を参考にし、MIT ライセンスに基づいてテンプレートと文字組みエンジンを改変して利用しています。 ## 商標とブランド diff --git a/README.md b/README.md index f72014ea..b3cf4a43 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ The instance administrator can create, disable, or reset member accounts in **Pr ### Telegram Community -Welcome to the EdgeEver community. Join us to discuss the EdgeEver experience, real-world AI Agent applications, cost-effective or free AI resources, and automation workflows. +Welcome to the EdgeEver community, bringing together developers and creators exploring vibe coding and AI. Join us to discuss cutting-edge AI productivity and best practices for personal knowledge bases. 👉 [Join the EdgeEver Telegram group](https://t.me/+wwUx1BYLrIdiZjY1) @@ -288,6 +288,7 @@ EdgeEver is a free and open-source project. Sustaining cross-platform client dev - EdgeEver's note-taking product design was also informed by the publicly available product experiences of mature note-taking tools such as [Evernote](https://evernote.com/) and [Notion](https://www.notion.com/). The related features were independently designed and implemented by EdgeEver. - The product design of mind-map and visual-diagram notes was informed by the publicly available product experiences of [XMind](https://xmind.com/) and [ProcessOn](https://www.processon.com/). These features were independently designed and implemented by EdgeEver. +- EdgeEver's poster design workspace draws inspiration from [Qiaomu Design](https://github.com/joeseesun/qiaomu-cover-design) by 向阳乔木 (joeseesun), and adapts its templates and typography engine under the MIT license. ## Trademark and Brand Use diff --git a/README.pl-PL.md b/README.pl-PL.md index 41416134..9c084dc3 100644 --- a/README.pl-PL.md +++ b/README.pl-PL.md @@ -177,7 +177,7 @@ Jedna instancja obsługuje wiele kont. Administrator może tworzyć i wyłącza ### Społeczność na Telegramie -Zapraszamy do rozmów o korzystaniu z EdgeEver, agentach AI, niedrogich lub darmowych usługach AI i automatyzacji. +Zapraszamy do społeczności EdgeEver, skupiającej twórców i pasjonatów vibe codingu oraz AI. Rozmawiajmy o nowoczesnej produktywności opartej na AI i sprawdzonych praktykach budowania osobistej bazy wiedzy. 👉 [Dołącz do grupy na Telegramie](https://t.me/+wwUx1BYLrIdiZjY1) @@ -284,6 +284,7 @@ EdgeEver jest darmowym projektem o otwartym kodzie. Rozwijanie aplikacji na ró - Przy projektowaniu EdgeEver wzorowano się na publicznie dostępnych rozwiązaniach dojrzałych aplikacji do notatek, takich jak [Evernote](https://evernote.com/) i [Notion](https://www.notion.com/). Powiązane funkcje zostały zaprojektowane i zaimplementowane niezależnie przez EdgeEver. - Inspiracją dla notatek z mapami myśli i diagramami były publicznie dostępne funkcje [XMind](https://xmind.com/) i [ProcessOn](https://www.processon.com/). Funkcje te zostały zaprojektowane i zaimplementowane niezależnie przez EdgeEver. +- Narzędzie do projektowania plakatów w EdgeEver czerpie inspirację z [Qiaomu Design](https://github.com/joeseesun/qiaomu-cover-design) autorstwa 向阳乔木 (joeseesun) i wykorzystuje dostosowane szablony oraz silnik typograficzny udostępnione na licencji MIT. ## Znak towarowy i użycie marki diff --git a/README.zh-CN.md b/README.zh-CN.md index b3329c9f..8e3d3651 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -181,7 +181,7 @@ curl -fsSL https://edgeever.org/install.sh | bash

微信交流群

-欢迎加入 EdgeEver AI 交流群,这里聚集了大量 Vibe Coding 与 AI 玩家。一起交流 EdgeEver 体验、AI Agent 实战落地、高性价比/免费 AI 资源及自动化工作流。 +欢迎加入 EdgeEver AI 交流群,这里聚集了大量 Vibe Coding 与 AI 玩家。一起交流前沿 AI 生产力与个人知识库的最佳实践。 > 扫描下方二维码或添加微信 `m1245207870`(备注“EdgeEver 进群”),群主将手动邀请入群。 @@ -291,6 +291,7 @@ EdgeEver 是免费开源项目。保持跨平台客户端(macOS、Windows、Li - EdgeEver 的笔记产品设计也参考了 [Evernote(印象笔记)](https://evernote.com/)、[Notion](https://www.notion.com/) 等成熟笔记工具的公开产品体验。相关功能由 EdgeEver 独立设计与实现。 - 思维导图与可视化图表笔记的产品设计参考了 [XMind](https://xmind.com/) 和 [ProcessOn](https://www.processon.com/) 等图表工具的公开产品体验。相关功能由 EdgeEver 独立设计与实现。 +- EdgeEver 的海报设计工作台借鉴了向阳乔木(joeseesun)的 [Qiaomu Design](https://github.com/joeseesun/qiaomu-cover-design),并基于其 MIT 开源许可改编了模板与字体排版引擎。 ## 商标与品牌使用 diff --git a/README.zh-TW.md b/README.zh-TW.md index 5be83f34..0827de39 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -179,7 +179,7 @@ curl -fsSL https://edgeever.org/install.sh | bash

微信交流群

-歡迎加入 EdgeEver AI 交流群,這裡聚集了大量 Vibe Coding 與 AI 玩家。一起交流 EdgeEver 體驗、AI Agent 實戰落地、高性價比/免費 AI 資源及自動化工作流程。 +歡迎加入 EdgeEver AI 交流群,這裡聚集了大量 Vibe Coding 與 AI 玩家。一起交流前沿 AI 生產力與個人知識庫的最佳實踐。 > 掃描下方 QR Code 或加入微信 `m1245207870`(備註「EdgeEver 進群」),群主將手動邀請入群。 @@ -289,6 +289,7 @@ EdgeEver 是免費開源專案。保持跨平台用戶端(macOS、Windows、Li - EdgeEver 的筆記產品設計也參考了 [Evernote(印象筆記)](https://evernote.com/)、[Notion](https://www.notion.com/) 等成熟筆記工具的公開產品體驗。相關功能由 EdgeEver 獨立設計與實作。 - 心智圖與視覺化圖表筆記的產品設計參考了 [XMind](https://xmind.com/) 和 [ProcessOn](https://www.processon.com/) 等圖表工具的公開產品體驗。相關功能由 EdgeEver 獨立設計與實作。 +- EdgeEver 的海報設計工作台借鑑了向阳乔木(joeseesun)的 [Qiaomu Design](https://github.com/joeseesun/qiaomu-cover-design),並基於其 MIT 開源授權改編了範本與字型排版引擎。 ## 商標與品牌使用 diff --git a/apps/api/src/companion-agent-tools.ts b/apps/api/src/companion-agent-tools.ts index 901df5bd..dd747732 100644 --- a/apps/api/src/companion-agent-tools.ts +++ b/apps/api/src/companion-agent-tools.ts @@ -124,6 +124,8 @@ const TOOL_HINTS: Record = { add_table_record: " Add one requested record to a structured table. First call get_table_records, then use its field IDs and latest revision. Do not invent factual records to fill a new table.", create_diagram_memo: " Create an editable visual diagram note. kind=mind-map for 思维导图/mind map, flowchart for 流程图, architecture for 架构图. Never use this for 信息图/infographic; call create_infographic_memo. Omit edge ids; EdgeEver generates them. For mind maps, give a root and children with parentId; omit node type. If the user did not name a notebook, omit notebookId. The diagram is saved in the inbox (等待分类). Do not ask which notebook, and do not use the open notebook unless the user named it. Build nodes from the open note body in Focus DATA when the user refers to this note.", create_infographic_memo: " Create an AntV infographic note (信息图). A share, proportion, or 占比 uses template chart-pie-donut-plain-text and numeric data.values, not a mind map. If the user did not supply the figures, say in data.desc that they are illustrative and are not an official disclosure. If the user did not name a notebook, omit notebookId. The infographic is saved in the inbox (等待分类). Do not ask which notebook, and do not use the open notebook unless the user named it.", + get_poster: " Read the existing poster canvas and elements before editing. Do not use raw Markdown for posters.", + update_poster: " Edit poster text, colors, typography and positions after get_poster. Preserve unmentioned and locked elements. Pass the revision you read.", get_diagram: " Read an existing editable diagram as a semantic graph. Call this before update_diagram. Do not use get_memo when you only need the diagram structure.", update_diagram: " Edit an existing diagram after get_diagram. Pass expectedRevision from get_diagram. Use add_node, update_node, remove_node, add_edge, update_edge, or remove_edge. Do not create a new diagram unless the user asked for a new note.", use_note_template: " Create a new memo from a template. If the user did not name a notebook, omit notebookId. The note is saved in the inbox (等待分类). Do not ask which notebook.", @@ -258,6 +260,7 @@ export function createCompanionTools(args: { db: DatabaseAdapter; scope: Compani if (!args.input.allowNotes || !args.context) return {}; const session = args.session ?? emptyCompanionAgentSession(); const inspected = new Map(Object.entries(session.inspected)); + const posterReads = new Map(); const persistSession = () => { session.inspected = Object.fromEntries(inspected); }; @@ -356,15 +359,15 @@ export function createCompanionTools(args: { db: DatabaseAdapter; scope: Compani } parameters_.expectedRevision = memo.revision; } - if (autoApply && parameters_.dryRun !== true && (definition.name === "update_memo" || definition.name === "update_diagram" || definition.name === "restore_memo_revision")) { + if (autoApply && parameters_.dryRun !== true && (definition.name === "update_memo" || definition.name === "update_diagram" || definition.name === "update_poster" || definition.name === "restore_memo_revision")) { const memo = await getMemoDetail(args.db, args.scope.workspaceId, String(parameters_.memoId)); - if (!memo || inspected.get(memo.id) !== memo.revision) { + if (!memo || inspected.get(memo.id) !== memo.revision || (definition.name === "update_poster" && posterReads.get(memo.id) !== memo.revision)) { throw new AppError("companion_action_unread", definition.name === "update_diagram" ? "Call get_diagram on this note before changing it." : "Read the complete source notes before changing their content.", 400); } - if (definition.name === "update_diagram") parameters_.expectedRevision = memo.revision; + if (definition.name === "update_diagram" || definition.name === "update_poster") parameters_.expectedRevision = memo.revision; } if (autoApply && parameters_.dryRun !== true && definition.name === "merge_memos") { const memoIds = Array.isArray(parameters_.memoIds) ? parameters_.memoIds.map(String) : []; @@ -375,7 +378,7 @@ export function createCompanionTools(args: { db: DatabaseAdapter; scope: Compani } } } - if ((definition.name === "get_memo" || definition.name === "get_diagram") && inspected.has(String(parameters_.memoId))) { + if ((definition.name === "get_memo" || definition.name === "get_diagram" || (definition.name === "get_poster" && posterReads.get(String(parameters_.memoId)) === inspected.get(String(parameters_.memoId)))) && inspected.has(String(parameters_.memoId))) { // The original full result remains in this run's model messages. Only // reuse it after authorization/context/cursor checks, never across runs. return done({ id: parameters_.memoId, revision: inspected.get(String(parameters_.memoId)), alreadyRead: true, @@ -447,7 +450,7 @@ export function createCompanionTools(args: { db: DatabaseAdapter; scope: Compani changes: updated.changes, }); } - if (definition.name === "update_memo") { + if (definition.name === "update_memo" || definition.name === "update_poster") { const updated = (result as { memo: MemoDetail }).memo; const receipt = await done({ applied: true, id: updated.id, title: updated.title, notebookId: updated.notebookId, revision: updated.revision }); @@ -463,15 +466,16 @@ export function createCompanionTools(args: { db: DatabaseAdapter; scope: Compani return done({ applied: true, ...(typeof result === "object" && result ? result as object : { result }) }); } if (current !== await companionWorkspaceCursor(args.db, args.scope.workspaceId)) return done({ error: "Notes changed during this read. Start a fresh request." }); - if (definition.name === "get_diagram") { - const payload = result as { memo: { id: string; title: string | null; revision: number }; diagram: { kind?: string; nodes?: unknown[] } }; + if (definition.name === "get_diagram" || definition.name === "get_poster") { + const payload = result as { memo: { id: string; title: string | null; revision: number; notebookId?: string }; diagram: { kind?: string; nodes?: unknown[] } }; inspected.set(payload.memo.id, payload.memo.revision); + if (definition.name === "get_poster") posterReads.set(payload.memo.id, payload.memo.revision); const known = args.sources.find(source => source.id === payload.memo.id); remember({ id: payload.memo.id, title: payload.memo.title, revision: payload.memo.revision, - notebookId: known?.notebookId || "", + notebookId: known?.notebookId || payload.memo.notebookId || "", }); return done(payload); } diff --git a/apps/api/src/companion-prepare.ts b/apps/api/src/companion-prepare.ts index 1c188d31..e8f86cd7 100644 --- a/apps/api/src/companion-prepare.ts +++ b/apps/api/src/companion-prepare.ts @@ -49,6 +49,7 @@ When the user refers to this note, 这篇, 当前, or the open note, use the Ope When the user asks for a mind map, 思维导图, flowchart, 流程图, architecture diagram, or 架构图 of the open note, build it from that body (or get_memo/get_diagram first). To create a new diagram note, call create_diagram_memo. Do not use create_memo, Markdown outlines, or Mermaid. Preserve an explicitly requested type exactly: 思维导图/mind map means kind=mind-map, 流程图/flowchart means kind=flowchart, and 架构图/architecture diagram means kind=architecture. For mind maps, supply a root node and children with parentId; omit node type. If the user did not name a notebook, omit notebookId so it is saved in the inbox notebook (等待分类). Do not ask which notebook, and do not use the open notebook unless the user named it. Reply with the new note link. When the user asks for an infographic, 信息图, 資訊圖, or インフォグラフィック, call create_infographic_memo. Do not use create_diagram_memo, create_memo, Markdown, or Mermaid for that request. A share, proportion, or 占比 is a pie infographic: template chart-pie-donut-plain-text and numeric data.values, not a mind map. If the user did not supply the figures, say in data.desc that they are illustrative and are not an official disclosure. If the user did not name a notebook, omit notebookId. Reply with the new note link. When the user asks for a 多维表格, 多維表格, or structured table, call create_table_memo with explicit fields. Do not use create_memo or a Markdown table. If no records were supplied or requested, leave it empty. If records were requested, call get_table_records for the new table's field IDs and revision before add_table_record. Omit notebookId when no notebook was named. Reply with the new note link. +To change a poster/海报, call get_poster then update_poster. Edit only requested text, colors, typography or positions; preserve other elements and locked elements. Never replace poster content with update_memo. To change an existing diagram, call get_diagram then update_diagram. Do not create a second diagram unless the user asked for a new note. Do not use update_memo or Mermaid for diagrams. A structured table cannot be replaced with update_memo. Use get_table_records to read its structure and records. Do not rewrite its Markdown. You can list, create, update, use, and delete note templates, and list, create, update, and delete AI instructions. use_note_template creates a memo immediately. You cannot empty the trash, share notes, or upload files. Do not claim those tools exist. diff --git a/apps/api/src/companion-tool-actions.test.mjs b/apps/api/src/companion-tool-actions.test.mjs index 0fb7e64a..c0b4d8bd 100644 --- a/apps/api/src/companion-tool-actions.test.mjs +++ b/apps/api/src/companion-tool-actions.test.mjs @@ -5,7 +5,7 @@ import { Hono } from "hono"; import { createSelfHostedStorageAdapter } from "./self-hosted-storage-adapter.ts"; import { registerCompanionRoutes } from "./companion-routes.ts"; import { beginCompanionTurn, checkpointCompanionTurn, clearCompanionHistory, saveCompanionMemory } from "./companion-service.ts"; -import { createDefaultTableDocument, parseDiagramDocument, parseInfographicDocument, parseTableDocument, serializeTableDocument } from "@edgeever/shared"; +import { createPosterDocument, serializePosterDocument, parsePosterDocument, createDefaultTableDocument, parseDiagramDocument, parseInfographicDocument, parseTableDocument, serializeTableDocument } from "@edgeever/shared"; import { createMemoRecord, getMemoDetail, normalizeSearchTimeBound, updateMemoRecord } from "./memo-service.ts"; import { companionWorkspaceCursor, proposeCompanionToolAction } from "./companion-tool-actions.ts"; import { getCompanionAction, applyCompanionAction, dismissCompanionAction } from "./companion-actions.ts"; @@ -49,7 +49,7 @@ async function setup() { describe("shared companion MCP adapter", () => { test("reuses the exact reviewed MCP definitions, with no administration or upload tools", () => { - expect(COMPANION_MCP_TOOLS).toHaveLength(47); + expect(COMPANION_MCP_TOOLS).toHaveLength(49); for (const definition of COMPANION_MCP_TOOLS) expect(MCP_TOOLS.includes(definition)).toBe(true); for (const name of ["upload_memo_image", "upload_memo_attachment", "empty_trash", "share_memo"]) { expect(() => validateCompanionTool(name, {})).toThrow(); @@ -115,13 +115,26 @@ describe("shared companion MCP adapter", () => { test("read and dry-run tools reuse MCP without writing or requiring a proposal", async () => { const f = await setup(); const tools = createCompanionTools({ ...f, scope, signal: new AbortController().signal, assertActive: async () => {}, sources: [] }); - expect(Object.keys(tools)).toHaveLength(49); + expect(Object.keys(tools)).toHaveLength(51); expect(await tools.get_memo.execute({ memoId: f.notes[0].id })).toMatchObject({ content: "One original content" }); expect(await tools.trash_memos.execute({ memoIds: [f.notes[0].id], dryRun: true })).toMatchObject({ dryRun: true }); expect(await getMemoDetail(f.db, scope.workspaceId, f.notes[0].id)).not.toBeNull(); expect(f.sqlite.query("SELECT COUNT(*) AS n FROM companion_actions").get().n).toBe(0); expect(createCompanionTools({ ...f, scope, input: { ...f.input, allowNotes: false } })).toEqual({}); }); + test("poster changes use the shared agent execution path with read and revision guards", async () => { + const f = await setup(); + const created = await createMemoRecord(f.db, scope.workspaceId, { notebookId: "ideas", title: "Poster", contentMarkdown: serializePosterDocument(createPosterDocument("Hello")), tags: [] }, actor, "owner"); + const tools = createCompanionTools({ ...f, scope, signal: new AbortController().signal, assertActive: async () => {}, sources: [] }); + await expect(tools.update_poster.execute({ memoId: created.id, expectedRevision: created.revision, background: "#16A06E" })).rejects.toMatchObject({ code: "companion_action_unread" }); + await tools.get_memo.execute({ memoId: created.id }); + const read = await tools.get_poster.execute({ memoId: created.id }); + expect(read.poster.elements.length).toBeGreaterThan(0); + const updated = await tools.update_poster.execute({ memoId: created.id, expectedRevision: read.memo.revision, background: "#16A06E" }); + expect(updated).toMatchObject({ applied: true, id: created.id }); + expect(parsePosterDocument((await getMemoDetail(f.db, scope.workspaceId, created.id)).contentMarkdown).background).toBe("#16A06E"); + expect(f.sqlite.query("SELECT COUNT(*) AS n FROM companion_actions").get().n).toBe(0); + }); test("read-only note access keeps MCP reads and omits write tools", async () => { const f = await setup(); const tools = createCompanionTools({ @@ -134,6 +147,8 @@ describe("shared companion MCP adapter", () => { expect(tools.create_diagram_memo).toBeUndefined(); expect(tools.update_diagram).toBeUndefined(); expect(tools.get_diagram).toBeTruthy(); + expect(tools.get_poster).toBeTruthy(); + expect(tools.update_poster).toBeUndefined(); expect(tools.update_memo).toBeUndefined(); expect(tools.merge_memos).toBeUndefined(); expect(tools.list_note_templates).toBeTruthy(); diff --git a/apps/api/src/companion-tool-actions.ts b/apps/api/src/companion-tool-actions.ts index 862223a5..96222669 100644 --- a/apps/api/src/companion-tool-actions.ts +++ b/apps/api/src/companion-tool-actions.ts @@ -27,7 +27,7 @@ export async function proposeCompanionToolAction(db: DatabaseAdapter, scope: Com for (const id of new Set([...ids, ...evidenceIds])) { const memo = await getMemoDetail(db, scope.workspaceId, id, toolName === "restore_memos"); if (!memo) throw stale(); - if ((toolName === "update_memo" || toolName === "merge_memos") && inspected.get(id) !== memo.revision) { + if ((toolName === "update_memo" || toolName === "update_poster" || toolName === "merge_memos") && inspected.get(id) !== memo.revision) { throw new AppError("companion_action_unread", "Read the complete source notes before changing their content or merging them.", 400); } notes.push({ id, title: memo.title ?? "", revision: memo.revision, notebookId: memo.notebookId, diff --git a/apps/api/src/companion-tool-catalog.ts b/apps/api/src/companion-tool-catalog.ts index 194fe1d4..ef46246a 100644 --- a/apps/api/src/companion-tool-catalog.ts +++ b/apps/api/src/companion-tool-catalog.ts @@ -6,7 +6,7 @@ import { AppError } from "./app-error"; // capabilities must be reviewed rather than silently acquiring user authority. const allowed = new Set([ "get_current_user", "search_memos", "list_memos", "get_memo", "create_memo", "create_table_memo", "get_table_records", "add_table_record", "create_diagram_memo", "create_infographic_memo", "get_diagram", - "update_diagram", + "update_diagram", "get_poster", "update_poster", "import_memos", "update_memo", "trash_memos", "restore_memos", "move_memos", "add_tags_to_memos", "remove_tags_from_memos", "rename_tag", "delete_tag", "merge_memos", "list_memo_resources", "list_resources", diff --git a/apps/api/src/companion-tool-receipts.ts b/apps/api/src/companion-tool-receipts.ts index 25aab91e..37fd5aad 100644 --- a/apps/api/src/companion-tool-receipts.ts +++ b/apps/api/src/companion-tool-receipts.ts @@ -33,13 +33,13 @@ export function describeCompanionTool( const memos = Array.isArray(record?.memos) ? record.memos : []; return memos.slice(0, 5).map(item => effect("listed", asMemo(item))); } - if (name === "get_memo" || name === "get_diagram" || name === "get_table_records") { + if (name === "get_memo" || name === "get_diagram" || name === "get_poster" || name === "get_table_records") { return [effect("read", memo ?? { id: String(args.memoId ?? record?.memoId ?? record?.id ?? "") })]; } if (name === "create_memo" || name === "create_table_memo" || name === "create_diagram_memo" || name === "create_infographic_memo" || name === "use_note_template") { return [effect("created", memo)]; } - if (name === "update_memo" || name === "update_diagram" || name === "restore_memo_revision") { + if (name === "update_memo" || name === "update_diagram" || name === "update_poster" || name === "restore_memo_revision") { const id = memo?.id ?? String(args.memoId ?? ""); const before = prior(id); return [effect("updated", memo ?? { id, title: before?.title }, { previousRevision: before?.revision })]; diff --git a/apps/api/src/database-write-optimizations.test.mjs b/apps/api/src/database-write-optimizations.test.mjs index 8607a559..8293f240 100644 --- a/apps/api/src/database-write-optimizations.test.mjs +++ b/apps/api/src/database-write-optimizations.test.mjs @@ -1,7 +1,7 @@ import { Database } from "bun:sqlite"; import { describe, expect, test } from "bun:test"; import { globSync, readFileSync } from "node:fs"; -import { addTableField, createDefaultTableDocument, serializeTableDocument, updateTableCell } from "@edgeever/shared"; +import { createPosterDocument, serializePosterDocument, parsePosterDocument, markdownToDoc, addTableField, createDefaultTableDocument, serializeTableDocument, updateTableCell } from "@edgeever/shared"; import { acquireMaintenanceLease, createMemoEditSession, @@ -211,6 +211,21 @@ describe("database write optimizations", () => { sqlite.close(); }); + test("protects new poster source from legacy contentJson edits and stale revisions", async () => { + const { database, sqlite } = createDatabase(); + const memo = getSeedMemo(sqlite), actor = { actorType: "user", actorId: "user_owner" }; + const first = await updateMemoRecord(database, memo.workspace_id, memo.id, { contentMarkdown: serializePosterDocument(createPosterDocument("Poster")) }, actor, "owner"); + expect(parsePosterDocument(first.memo.contentMarkdown)).not.toBeNull(); + const legacy = await updateMemoRecord(database, memo.workspace_id, memo.id, { contentJson: markdownToDoc("legacy editor changed preview") }, actor, "owner"); + expect(legacy.error).toBe("poster_update_required"); + const next = await updateMemoRecord(database, memo.workspace_id, memo.id, { expectedRevision: first.memo.revision, expectedContentHash: first.memo.contentHash, contentMarkdown: serializePosterDocument(createPosterDocument("New design")) }, actor, "owner"); + expect(parsePosterDocument(next.memo.contentMarkdown).elements[1].text).toBe("New design"); + const stale = await updateMemoRecord(database, memo.workspace_id, memo.id, { expectedRevision: first.memo.revision, expectedContentHash: first.memo.contentHash, contentMarkdown: first.memo.contentMarkdown }, actor, "owner"); + expect(stale.error).toBeTruthy(); + expect(parsePosterDocument(sqlite.query("SELECT content_markdown FROM memo_contents WHERE memo_id = ?").get(memo.id).content_markdown).elements[1].text).toBe("New design"); + sqlite.close(); + }); + test("allows only one live maintenance lease owner", async () => { const { database, sqlite } = createDatabase(); const first = await acquireMaintenanceLease(database, "demo-reset-test", 60_000); diff --git a/apps/api/src/mcp-management-tools.test.mjs b/apps/api/src/mcp-management-tools.test.mjs index 201c8276..03b41edc 100644 --- a/apps/api/src/mcp-management-tools.test.mjs +++ b/apps/api/src/mcp-management-tools.test.mjs @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { globSync, readFileSync } from "node:fs"; import { Database } from "bun:sqlite"; import { callMcpTool } from "./index.ts"; -import { addTableField, parseDiagramDocument, parseInfographicDocument, parseTableDocument, serializeTableDocument, createDefaultTableDocument } from "@edgeever/shared"; +import { createPosterDocument, serializePosterDocument, parsePosterDocument, addTableField, parseDiagramDocument, parseInfographicDocument, parseTableDocument, serializeTableDocument, createDefaultTableDocument } from "@edgeever/shared"; class SqliteD1PreparedStatement { constructor(db, sql, bindings = []) { @@ -72,6 +72,26 @@ const createFixture = (scopes = ["read:memos", "write:memos"]) => { }; describe("MCP template and AI instruction management", () => { + test("poster tools preserve untouched elements, previews, scopes and revision guards", async () => { + const { sqlite, auth, context } = createFixture(); + sqlite.query("INSERT INTO notebooks (id, workspace_id, name) VALUES (?, ?, ?)").run("nb_posters", "ws_mcp", "Posters"); + const poster = { ...createPosterDocument("Original"), previewResourceId: "old_preview" }; + const created = await callMcpTool(context, auth, "create_memo", { notebookId: "nb_posters", title: "Poster", contentMarkdown: serializePosterDocument(poster) }); + const read = await callMcpTool(context, auth, "get_poster", { memoId: created.memo.id }); + const heading = read.poster.elements.find(element => element.type === "text"); + const input = { memoId: created.memo.id, expectedRevision: read.memo.revision, edits: [{ id: heading.id, patch: { text: "Updated", fill: "#16A06E" } }] }; + const preview = await callMcpTool(context, auth, "update_poster", { ...input, dryRun: true }); + expect(preview.poster.elements.find(element => element.id === heading.id).text).toBe("Updated"); + expect((await callMcpTool(context, auth, "get_poster", { memoId: created.memo.id })).poster.previewResourceId).toBe("old_preview"); + await expect(callMcpTool(context, { ...auth, scopes: ["read:memos"] }, "update_poster", input)).rejects.toThrow(); + await expect(callMcpTool(context, { ...auth, workspaceId: "ws_other" }, "get_poster", { memoId: created.memo.id })).rejects.toThrow(); + const result = await callMcpTool(context, auth, "update_poster", input); + expect(result.poster.previewResourceId).toBeUndefined(); + expect(result.poster.elements.filter(element => element.id !== heading.id)).toEqual(read.poster.elements.filter(element => element.id !== heading.id)); + expect(parsePosterDocument(result.memo.contentMarkdown).elements.find(element => element.id === heading.id).text).toBe("Updated"); + await expect(callMcpTool(context, auth, "update_poster", input)).rejects.toThrow(); + await expect(callMcpTool(context, auth, "update_poster", { ...input, expectedRevision: result.memo.revision, edits: [{ id: "missing", patch: { text: "Bad" } }] })).rejects.toThrow(); + }); test.each([ ["mind-map", [ { id: "root", label: "Root" }, diff --git a/apps/api/src/mcp-poster-tools.test.mjs b/apps/api/src/mcp-poster-tools.test.mjs new file mode 100644 index 00000000..f3de0d7d --- /dev/null +++ b/apps/api/src/mcp-poster-tools.test.mjs @@ -0,0 +1,26 @@ +import { expect, test } from "bun:test"; +import { createPosterDocument } from "@edgeever/shared"; +import { applyPosterEdits } from "./mcp-poster-tools"; + +test("poster edits reject locked elements, duplicate IDs, unknown patch keys and invalid geometry", () => { + const poster = createPosterDocument("Hello"); + const element = poster.elements.find(element => element.type === "text"); + const input = patch => ({ memoId: "memo", expectedRevision: 1, edits: [{ id: element.id, patch }] }); + expect(() => applyPosterEdits(input({ text: "Bad" }), { ...poster, elements: poster.elements.map(item => item.id === element.id ? { ...item, locked: true } : item) })).toThrow(); + expect(() => applyPosterEdits({ ...input({ text: "Bad" }), edits: [input({ text: "One" }).edits[0], input({ text: "Two" }).edits[0]] }, poster)).toThrow(); + expect(() => applyPosterEdits(input({ resourceId: "other" }), poster)).toThrow(); + expect(() => applyPosterEdits(input({ width: -1 }), poster)).toThrow(); + expect(() => applyPosterEdits({ memoId: "memo", expectedRevision: 1 }, poster)).toThrow(); +}); + +test("poster edits update canonical copy, support background changes and retain a preview on no-op", () => { + const poster = { ...createPosterDocument("Hello"), previewResourceId: "preview" }; + const title = poster.elements.find(element => element.type === "text"); + const changed = applyPosterEdits({ memoId: "memo", expectedRevision: 1, background: "#16A06E", edits: [{ id: title.id, patch: { text: "New heading" } }] }, poster); + expect(changed.document.background).toBe("#16A06E"); + expect(changed.document.elements.find(element => element.id === title.id).sourceText).toBe("New heading"); + expect(changed.document.previewResourceId).toBeUndefined(); + const unchanged = applyPosterEdits({ memoId: "memo", expectedRevision: 1, background: poster.background }, poster); + expect(unchanged.changed).toBe(false); + expect(unchanged.document.previewResourceId).toBe("preview"); +}); diff --git a/apps/api/src/mcp-poster-tools.ts b/apps/api/src/mcp-poster-tools.ts new file mode 100644 index 00000000..742ca534 --- /dev/null +++ b/apps/api/src/mcp-poster-tools.ts @@ -0,0 +1,66 @@ +import { z } from "zod"; +import { PosterDocumentSchema, PosterGradientSchema, type PosterDocument } from "@edgeever/shared"; +import { AppError } from "./app-error"; + +const patch = z.object({ + text: z.string().max(8000).optional(), + fill: z.string().regex(/^#[0-9a-f]{6}$/i).optional(), + fontSize: z.number().finite().min(4).max(8192).optional(), + fontWeight: z.enum(["normal", "bold"]).optional(), + textAlign: z.enum(["left", "center", "right"]).optional(), + x: z.number().finite().min(-8192).max(8192).optional(), + y: z.number().finite().min(-8192).max(8192).optional(), + width: z.number().finite().min(1).max(8192).optional(), + height: z.number().finite().min(1).max(8192).optional(), + rotation: z.number().finite().min(-360).max(360).optional(), + opacity: z.number().finite().min(0).max(1).optional(), +}).strict().refine(value => Object.keys(value).length > 0); +const request = z.object({ + memoId: z.string().min(1), + expectedRevision: z.number().int().nonnegative(), + dryRun: z.boolean().optional(), + background: z.string().regex(/^#[0-9a-f]{6}$/i).optional(), + backgroundGradient: PosterGradientSchema.nullable().optional(), + edits: z.array(z.object({ id: z.string().min(1), patch }).strict()).max(100).optional(), +}).strict().refine(value => Boolean(value.edits?.length || value.background || value.backgroundGradient !== undefined)); + +export function applyPosterEdits(input: unknown, current: PosterDocument) { + const parsed = request.safeParse(input); + if (!parsed.success) throw new AppError("invalid_params", "Invalid poster edits", 400); + const args = parsed.data; + const edits = args.edits ?? []; + if (new Set(edits.map(edit => edit.id)).size !== edits.length) throw new AppError("invalid_params", "Duplicate poster element IDs", 400); + for (const edit of edits) { + const element = current.elements.find(element => element.id === edit.id); + if (!element || element.locked) throw new AppError("invalid_params", "Poster element is missing or locked", 400); + if (element.type !== "text" && ["text", "fontSize", "fontWeight", "textAlign"].some(key => key in edit.patch)) { + throw new AppError("invalid_params", "Typography edits require a text element", 400); + } + if (element.type === "image" && edit.patch.fill !== undefined) throw new AppError("invalid_params", "Image elements do not have a fill", 400); + } + const next = PosterDocumentSchema.safeParse({ + ...current, + ...(args.background !== undefined ? { background: args.background } : {}), + ...(args.backgroundGradient !== undefined ? { backgroundGradient: args.backgroundGradient ?? undefined } : {}), + elements: current.elements.map(element => { + const edit = edits.find(edit => edit.id === element.id); + if (!edit) return element; + return { ...element, ...edit.patch, ...(edit.patch.text !== undefined ? { sourceText: edit.patch.text } : {}) }; + }), + }); + if (!next.success) throw new AppError("invalid_params", "Poster edits exceed document limits", 400); + const document = next.data; + if (edits.some(edit => edit.patch.text !== undefined)) { + document.copy = { + title: current.copy?.title ?? "", subtitle: current.copy?.subtitle ?? "", badge: current.copy?.badge ?? "", + }; + for (const role of ["title", "subtitle", "badge"] as const) { + if (!edits.some(edit => edit.patch.text !== undefined && current.elements.some(element => element.id === edit.id && element.role === role))) continue; + document.copy[role] = [...new Set(document.elements.filter(element => element.type === "text" && element.role === role) + .map(element => element.type === "text" ? element.sourceText ?? element.text : ""))].join("\n"); + } + } + const changed = JSON.stringify(document) !== JSON.stringify(PosterDocumentSchema.parse(current)); + if (changed) document.previewResourceId = undefined; + return { document, changed }; +} diff --git a/apps/api/src/mcp-tool-service.ts b/apps/api/src/mcp-tool-service.ts index ea242c23..1c98cf0d 100644 --- a/apps/api/src/mcp-tool-service.ts +++ b/apps/api/src/mcp-tool-service.ts @@ -1,3 +1,5 @@ +import { applyPosterEdits } from "./mcp-poster-tools"; +import { hasPosterDocumentMarker, parsePosterDocument, serializePosterDocument } from "@edgeever/shared"; import { AiPromptTemplateCreateSchema, AiPromptTemplateUpdateSchema, @@ -508,6 +510,30 @@ export const callMcpTool = async ( diagram: diagramSemanticGraph(document), }; } + case "get_poster": { + assertScope(auth, "read:memos"); + const memo = await getMemoDetail(c.env.storage.db, auth.workspaceId, getRequiredString(args.memoId, "memoId")); + if (!memo) throw new AppError("not_found", "Memo not found", 404); + const poster = parsePosterDocument(memo.contentMarkdown); + if (!poster) throw new AppError("not_poster", "Memo is not an editable poster", 400); + return { memo: { id: memo.id, title: memo.title, notebookId: memo.notebookId, revision: memo.revision }, poster }; + } + case "update_poster": { + assertScope(auth, "write:memos"); + const memoId = getRequiredString(args.memoId, "memoId"); + const memo = await getMemoDetail(c.env.storage.db, auth.workspaceId, memoId); + if (!memo) throw new AppError("not_found", "Memo not found", 404); + if (memo.revision !== args.expectedRevision) throw new AppError("revision_conflict", "Poster changed. Read it again before editing.", 409); + const current = parsePosterDocument(memo.contentMarkdown); + if (!current) throw new AppError("not_poster", "Memo is not an editable poster", 400); + const mutation = applyPosterEdits(args, current); + if (args.dryRun === true || !mutation.changed) return { dryRun: args.dryRun === true, memo, poster: mutation.document, changed: mutation.changed }; + const result = await updateMemoRecord(c.env.storage.db, auth.workspaceId, memoId, { + expectedRevision: args.expectedRevision, contentMarkdown: serializePosterDocument(mutation.document), + }, getAuditActor(c), getActorLabel(c)); + if (result.error !== undefined) throw new AppError(result.error, result.message, result.status ?? 400); + return { memo: result.memo, poster: mutation.document, changed: true }; + } case "get_diagram": { assertScope(auth, "read:memos"); const memoId = getRequiredString(args.memoId, "memoId"); @@ -585,6 +611,9 @@ export const callMcpTool = async ( 400, ); } + if (existing && hasPosterDocumentMarker(existing.contentMarkdown)) { + throw new AppError("poster_update_required", "Poster content cannot be replaced through update_memo. Use get_poster then update_poster.", 400); + } if (existing && hasInfographicDocumentMarker(existing.contentMarkdown)) { throw new AppError( "infographic_update_required", diff --git a/apps/api/src/mcp-tools.ts b/apps/api/src/mcp-tools.ts index d0c6d1ce..59e64397 100644 --- a/apps/api/src/mcp-tools.ts +++ b/apps/api/src/mcp-tools.ts @@ -363,6 +363,37 @@ const MCP_TOOL_DEFINITIONS = [ }, }, }, + { + name: "get_poster", + description: "Read an editable poster's canvas, element IDs, text, colors and geometry. Read before update_poster; never decode or replace poster Markdown.", + inputSchema: { type: "object", required: ["memoId"], additionalProperties: false, properties: { memoId: { type: "string", minLength: 1 } } }, + }, + { + name: "update_poster", + description: "Edit an existing poster's text, colors, typography and element positions. Preserve unmentioned elements and locked elements. Read get_poster first and pass its expectedRevision. Use dryRun to preview. After changes the editor regenerates the preview image.", + inputSchema: { + type: "object", required: ["memoId", "expectedRevision"], additionalProperties: false, + properties: { + memoId: { type: "string", minLength: 1 }, expectedRevision: { type: "integer", minimum: 0 }, dryRun: { type: "boolean" }, + background: { type: "string", pattern: "^#[0-9a-fA-F]{6}$" }, + backgroundGradient: { type: ["object", "null"], additionalProperties: false, required: ["kind", "from", "to"], properties: { + kind: { type: "string", enum: ["linear", "radial"] }, from: { type: "string", pattern: "^#[0-9a-fA-F]{6}$" }, to: { type: "string", pattern: "^#[0-9a-fA-F]{6}$" }, angle: { type: "number", minimum: -360, maximum: 360 }, + } }, + edits: { type: "array", maxItems: 100, items: { + type: "object", required: ["id", "patch"], additionalProperties: false, + properties: { id: { type: "string", minLength: 1 }, patch: { + type: "object", additionalProperties: false, properties: { + text: { type: "string", maxLength: 8000 }, fill: { type: "string", pattern: "^#[0-9a-fA-F]{6}$" }, + fontSize: { type: "number", minimum: 4, maximum: 8192 }, fontWeight: { type: "string", enum: ["normal", "bold"] }, textAlign: { type: "string", enum: ["left", "center", "right"] }, + x: { type: "number", minimum: -8192, maximum: 8192 }, y: { type: "number", minimum: -8192, maximum: 8192 }, + width: { type: "number", minimum: 1, maximum: 8192 }, height: { type: "number", minimum: 1, maximum: 8192 }, + rotation: { type: "number", minimum: -360, maximum: 360 }, opacity: { type: "number", minimum: 0, maximum: 1 }, + }, + } }, + } }, + }, + }, + }, { name: "get_diagram", description: @@ -979,6 +1010,7 @@ const READ_ONLY_MCP_TOOLS = new Set([ "get_memo", "get_table_records", "get_diagram", + "get_poster", "list_memo_resources", "list_resources", "list_memo_revisions", diff --git a/apps/api/src/memo-list-service.ts b/apps/api/src/memo-list-service.ts index 761c2ad4..f468d36d 100644 --- a/apps/api/src/memo-list-service.ts +++ b/apps/api/src/memo-list-service.ts @@ -5,6 +5,7 @@ import { markdownToDoc, getDiagramSummary, getInfographicSummary, + getPosterSummary, getTableSummary, type MemoSummary, } from "@edgeever/shared"; @@ -73,6 +74,7 @@ export const mapMemoSummary = (row: MemoSummaryRow): MemoSummary => ({ createExcerpt(docToText(markdownToDoc(row.content_markdown ?? ""))), ...getDiagramSummary(row.content_markdown), ...getInfographicSummary(row.content_markdown), + ...getPosterSummary(row.content_markdown), ...getTableSummary(row.content_markdown), tags: parseJsonArray(row.tags_json), isPinned: Boolean(row.is_pinned), diff --git a/apps/api/src/memo-service.ts b/apps/api/src/memo-service.ts index 2eea49d5..371c362b 100644 --- a/apps/api/src/memo-service.ts +++ b/apps/api/src/memo-service.ts @@ -1,3 +1,4 @@ +import { hasPosterDocumentMarker, parsePosterDocument } from "@edgeever/shared"; import { createExcerpt, DEFAULT_MEMO_TITLE, @@ -1346,6 +1347,12 @@ export const updateMemoRecord = async ( const tags = input.tags === undefined ? parseJsonArray(current.tags_json) : normalizeTags(input.tags); const excerpt = createExcerpt(contentText); const notebookId = input.notebookId ?? current.notebook_id; + if (hasPosterDocumentMarker(current.content_markdown) && !parsePosterDocument(contentMarkdown)) { + return { error: "poster_update_required", message: "Poster source must be edited on a supported client.", status: 409 }; + } + if (hasPosterDocumentMarker(contentMarkdown) && !parsePosterDocument(contentMarkdown)) { + return { error: "invalid_poster", message: "Invalid poster source.", status: 400 }; + } const currentTable = parseTableDocument(current.content_markdown); const nextTable = parseTableDocument(contentMarkdown); if (currentTable && !nextTable) { diff --git a/apps/ios/EdgeEver/Editor/TipTapContentSource.swift b/apps/ios/EdgeEver/Editor/TipTapContentSource.swift index b3f3685c..2cc07168 100644 --- a/apps/ios/EdgeEver/Editor/TipTapContentSource.swift +++ b/apps/ios/EdgeEver/Editor/TipTapContentSource.swift @@ -32,6 +32,10 @@ enum TipTapContentSource: Sendable { let stripped = stripStructuredTableMarker(markdown) return Decision(useJSON: false, payload: stripped, fingerprint: "table:\(stripped)") } + if markdown.contains(""#, with: "", options: .regularExpression).trimmingCharacters(in: .whitespacesAndNewlines) + return Decision(useJSON: false, payload: stripped, fingerprint: "poster:\(stripped)") + } if markdown.contains("" + let decision = TipTapContentSource.resolve(mode: .viewer, documentJSON: "{}", markdown: markdown) + XCTAssertFalse(decision.useJSON) + XCTAssertTrue(decision.payload.contains("res_preview/blob")) + XCTAssertFalse(decision.payload.contains("edgeever-poster-v1")) + } + func testEditorMarkdownRemainsAuthoritativeForRichStructures() { let markdown = """ 1. first diff --git a/apps/mobile/src/lib/mobile-diagram.test.ts b/apps/mobile/src/lib/mobile-diagram.test.ts index b530f734..171be1fa 100644 --- a/apps/mobile/src/lib/mobile-diagram.test.ts +++ b/apps/mobile/src/lib/mobile-diagram.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "node:fs"; import { describe, expect, test } from "bun:test"; -import { createDefaultDiagramDocument, createDefaultTableDocument, diagramFallbackMarkdown, serializeDiagramDocument, serializeInfographicDocument, serializeTableDocument, tableFallbackMarkdown } from "@edgeever/shared"; -import { getMobileVisualDiagramKind, hasMobileInfographic, hasMobileStructuredTable, hasMobileVisualDiagram, resolveMobileMemoViewerContent } from "./mobile-diagram"; +import { createPosterDocument, serializePosterDocument, createDefaultDiagramDocument, createDefaultTableDocument, diagramFallbackMarkdown, serializeDiagramDocument, serializeInfographicDocument, serializeTableDocument, tableFallbackMarkdown } from "@edgeever/shared"; +import { hasMobilePoster, getMobileVisualDiagramKind, hasMobileInfographic, hasMobileStructuredTable, hasMobileVisualDiagram, resolveMobileMemoViewerContent } from "./mobile-diagram"; const hasMermaidCodeBlock = (doc: { content?: Array<{ type?: string; attrs?: { language?: string } }> }) => Boolean(doc.content?.some((node) => node.type === "codeBlock" && node.attrs?.language === "mermaid")); @@ -47,6 +47,15 @@ describe("mobile visual diagram viewer", () => { expect(JSON.stringify(resolveMobileMemoViewerContent(null, broken))).not.toContain("edgeever-table-v1"); }); + test("shows a poster preview and keeps editable source out of the native reader", () => { + const markdown = serializePosterDocument({ ...createPosterDocument("Poster"), previewResourceId: "res_preview" }); + expect(hasMobilePoster(markdown)).toBe(true); + const doc = resolveMobileMemoViewerContent(null, markdown); + expect(JSON.stringify(doc)).toContain("res_preview/blob"); + expect(JSON.stringify(doc)).not.toContain("edgeever-poster-v1"); + expect(hasMobilePoster("text\n")).toBe(true); + }); + test("shows infographic syntax without exposing its marker to the native viewer", () => { const markdown = serializeInfographicDocument({ schemaVersion: 1, syntax: "infographic list-row-simple-horizontal-arrow\ndata\n title Test" }); expect(hasMobileInfographic(markdown)).toBe(true); diff --git a/apps/mobile/src/lib/mobile-diagram.ts b/apps/mobile/src/lib/mobile-diagram.ts index 4bb877a4..9e0e0efd 100644 --- a/apps/mobile/src/lib/mobile-diagram.ts +++ b/apps/mobile/src/lib/mobile-diagram.ts @@ -1,6 +1,8 @@ import { hasDiagramDocumentMarker, hasInfographicDocumentMarker, + hasPosterDocumentMarker, + stripPosterDocumentMarker, hasTableDocumentMarker, markdownToDoc, parseDiagramDocument, @@ -27,11 +29,14 @@ export const hasMobileStructuredTable = (contentMarkdown: string) => export const hasMobileInfographic = (contentMarkdown: string) => hasInfographicDocumentMarker(contentMarkdown); +export const hasMobilePoster = (contentMarkdown: string) => hasPosterDocumentMarker(contentMarkdown); + /** Viewer TipTap payload for a visual-diagram envelope. Valid IR is drawn by read-only X6, so this returns an empty doc instead of a hidden Mermaid projection. Invalid envelopes keep the stripped Mermaid fence as degraded content. */ export const resolveMobileMemoViewerContent = ( contentJson: TiptapDoc | null | undefined, contentMarkdown: string, ) => { + if (hasPosterDocumentMarker(contentMarkdown)) return markdownToDoc(stripPosterDocumentMarker(contentMarkdown)); if (parseDiagramDocument(contentMarkdown)) { return { type: "doc", content: [{ type: "paragraph" }] } satisfies TiptapDoc; } diff --git a/apps/mobile/src/screens/WorkspaceMemoDetail.tsx b/apps/mobile/src/screens/WorkspaceMemoDetail.tsx index fef9c33a..8b5f25d8 100644 --- a/apps/mobile/src/screens/WorkspaceMemoDetail.tsx +++ b/apps/mobile/src/screens/WorkspaceMemoDetail.tsx @@ -21,7 +21,7 @@ import { MobileAiAssistantModal } from "../components/MobileAiAssistantModal"; import { MobileResourceActions } from "../components/MobileResourceActions"; import { SAFE_DOM_WEBVIEW_PROPS } from "../lib/mobile-dom"; import { getNextMobileNoteSearchIndex } from "../lib/mobile-note-search"; -import { hasMobileInfographic, hasMobileStructuredTable, hasMobileVisualDiagram, resolveMobileMemoViewerContent } from "../lib/mobile-diagram"; +import { hasMobilePoster, hasMobileInfographic, hasMobileStructuredTable, hasMobileVisualDiagram, resolveMobileMemoViewerContent } from "../lib/mobile-diagram"; import { safeDomCall } from "../lib/safe-dom-call"; import { getMobileImageTarget, @@ -555,7 +555,7 @@ export const MemoDetailModal = ({ () => (memo ? hasMobileStructuredTable(memo.contentMarkdown) : false), [memo] ); - const locksRichTextEdit = isVisualDiagram || isStructuredTable || Boolean(memo && hasMobileInfographic(memo.contentMarkdown)); + const locksRichTextEdit = isVisualDiagram || isStructuredTable || Boolean(memo && (hasMobileInfographic(memo.contentMarkdown) || hasMobilePoster(memo.contentMarkdown))); const visualDiagramJson = useMemo(() => { const diagram = memo ? parseDiagramDocument(memo.contentMarkdown) : null; return diagram ? JSON.stringify(diagram) : undefined; diff --git a/apps/web/package.json b/apps/web/package.json index cdb0ca01..f2afcf01 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,6 +28,7 @@ "ai": "7.0.58", "beautiful-mermaid": "^1.1.3", "docx-preview": "0.4.1", + "fabric": "7.4.0", "highlight.js": "^11.11.1", "html-to-image": "^1.11.13", "lowlight": "^3.3.0", diff --git a/apps/web/public/poster-fonts/anton.woff2 b/apps/web/public/poster-fonts/anton.woff2 new file mode 100644 index 00000000..2d79727e Binary files /dev/null and b/apps/web/public/poster-fonts/anton.woff2 differ diff --git a/apps/web/public/poster-fonts/bebas.woff2 b/apps/web/public/poster-fonts/bebas.woff2 new file mode 100644 index 00000000..ede33a9b Binary files /dev/null and b/apps/web/public/poster-fonts/bebas.woff2 differ diff --git a/apps/web/public/poster-fonts/dmserif.woff2 b/apps/web/public/poster-fonts/dmserif.woff2 new file mode 100644 index 00000000..7d6d23cb Binary files /dev/null and b/apps/web/public/poster-fonts/dmserif.woff2 differ diff --git a/apps/web/public/poster-fonts/douyin.ttf b/apps/web/public/poster-fonts/douyin.ttf new file mode 100644 index 00000000..eb8555c6 Binary files /dev/null and b/apps/web/public/poster-fonts/douyin.ttf differ diff --git a/apps/web/public/poster-fonts/glow.woff2 b/apps/web/public/poster-fonts/glow.woff2 new file mode 100644 index 00000000..5e83e289 Binary files /dev/null and b/apps/web/public/poster-fonts/glow.woff2 differ diff --git a/apps/web/public/poster-fonts/huangyou.woff2 b/apps/web/public/poster-fonts/huangyou.woff2 new file mode 100644 index 00000000..fbba0fbe Binary files /dev/null and b/apps/web/public/poster-fonts/huangyou.woff2 differ diff --git a/apps/web/public/poster-fonts/inter.woff2 b/apps/web/public/poster-fonts/inter.woff2 new file mode 100644 index 00000000..f92bdd38 Binary files /dev/null and b/apps/web/public/poster-fonts/inter.woff2 differ diff --git a/apps/web/public/poster-fonts/jetbrains.woff2 b/apps/web/public/poster-fonts/jetbrains.woff2 new file mode 100644 index 00000000..b7a7ef5d Binary files /dev/null and b/apps/web/public/poster-fonts/jetbrains.woff2 differ diff --git a/apps/web/public/poster-fonts/jiangcheng.woff2 b/apps/web/public/poster-fonts/jiangcheng.woff2 new file mode 100644 index 00000000..2ab52100 Binary files /dev/null and b/apps/web/public/poster-fonts/jiangcheng.woff2 differ diff --git a/apps/web/public/poster-fonts/kuaile.woff2 b/apps/web/public/poster-fonts/kuaile.woff2 new file mode 100644 index 00000000..5e1c65e0 Binary files /dev/null and b/apps/web/public/poster-fonts/kuaile.woff2 differ diff --git a/apps/web/public/poster-fonts/licenses/anton.txt b/apps/web/public/poster-fonts/licenses/anton.txt new file mode 100644 index 00000000..979f0b64 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/anton.txt @@ -0,0 +1,33 @@ +Anton (Anton) +Source: https://fonts.google.com/specimen/Anton +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2020 The Anton Project Authors (https://github.com/googlefonts/AntonFont.git) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/bebas.txt b/apps/web/public/poster-fonts/licenses/bebas.txt new file mode 100644 index 00000000..95b2a7e5 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/bebas.txt @@ -0,0 +1,33 @@ +Bebas Neue (Bebas Neue) +Source: https://fonts.google.com/specimen/Bebas+Neue +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2019 The Bebas Neue Project Authors (https://github.com/dharmatype/Bebas-Neue) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/dmserif.txt b/apps/web/public/poster-fonts/licenses/dmserif.txt new file mode 100644 index 00000000..896a8104 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/dmserif.txt @@ -0,0 +1,33 @@ +DM Serif Display (DM Serif Display) +Source: https://fonts.google.com/specimen/DM+Serif+Display +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2014 - 2017 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. Copyright 2019 Google LLC. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/douyin.txt b/apps/web/public/poster-fonts/licenses/douyin.txt new file mode 100644 index 00000000..dd45a686 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/douyin.txt @@ -0,0 +1,34 @@ +抖音美好体 (Douyin Sans) +Source: https://github.com/bytedance/fonts +This copy: unmodified original + +Copyright (c) , 2023 Beijing Zitiao Network Technology Co. Ltd. +with Reserved Font Names "Douyin", "抖音", "抖音美好". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/glow.txt b/apps/web/public/poster-fonts/licenses/glow.txt new file mode 100644 index 00000000..8d9113bd --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/glow.txt @@ -0,0 +1,33 @@ +未来荧黑 (Glow Sans SC Heavy) +Source: https://github.com/welai/glow-sans +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Glow Sans (c) 2021 Project Welai + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/huangyou.txt b/apps/web/public/poster-fonts/licenses/huangyou.txt new file mode 100644 index 00000000..5e138d4a --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/huangyou.txt @@ -0,0 +1,33 @@ +站酷庆科黄油体 (ZCOOL QingKe HuangYou) +Source: https://fonts.google.com/specimen/ZCOOL+QingKe+HuangYou +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2018 The ZCOOL QingKe HuangYou Project Authors (https://www.github.com/googlefonts/zcool-qingke-huangyou) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/inter.txt b/apps/web/public/poster-fonts/licenses/inter.txt new file mode 100644 index 00000000..d47c7b2a --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/inter.txt @@ -0,0 +1,33 @@ +Inter (Inter) +Source: https://fonts.google.com/specimen/Inter +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/jetbrains.txt b/apps/web/public/poster-fonts/licenses/jetbrains.txt new file mode 100644 index 00000000..d9affa6d --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/jetbrains.txt @@ -0,0 +1,33 @@ +JetBrains Mono (JetBrains Mono) +Source: https://fonts.google.com/specimen/JetBrains+Mono +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/jiangcheng.txt b/apps/web/public/poster-fonts/licenses/jiangcheng.txt new file mode 100644 index 00000000..532d05f8 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/jiangcheng.txt @@ -0,0 +1,33 @@ +江城圆体 (JiangCheng YuanTi) +Source: https://www.npmjs.com/package/@fontpkg/jiang-cheng-yuan-ti +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +JiangCheng YuanTi + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/kuaile.txt b/apps/web/public/poster-fonts/licenses/kuaile.txt new file mode 100644 index 00000000..3bb9bfc5 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/kuaile.txt @@ -0,0 +1,33 @@ +站酷快乐体 (ZCOOL KuaiLe) +Source: https://fonts.google.com/specimen/ZCOOL+KuaiLe +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2018 The ZCOOL KuaiLe Project Authors (https://github.com/googlefonts/zcool-kuaile) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/mashan.txt b/apps/web/public/poster-fonts/licenses/mashan.txt new file mode 100644 index 00000000..7853fccf --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/mashan.txt @@ -0,0 +1,33 @@ +马善政楷书 (Ma Shan Zheng) +Source: https://fonts.google.com/specimen/Ma+Shan+Zheng +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2018 The MaShanZheng Project Authors (https://github.com/googlefonts/mashanzheng) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/notosans-heavy.txt b/apps/web/public/poster-fonts/licenses/notosans-heavy.txt new file mode 100644 index 00000000..e39cb8f7 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/notosans-heavy.txt @@ -0,0 +1,33 @@ +思源黑体 Heavy (Noto Sans SC Black) +Source: https://fonts.google.com/noto/specimen/Noto+Sans+SC +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +(c) 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/notosans.txt b/apps/web/public/poster-fonts/licenses/notosans.txt new file mode 100644 index 00000000..3bf91bbb --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/notosans.txt @@ -0,0 +1,33 @@ +思源黑体 (Noto Sans SC) +Source: https://fonts.google.com/noto/specimen/Noto+Sans+SC +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +(c) 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/notoserif-heavy.txt b/apps/web/public/poster-fonts/licenses/notoserif-heavy.txt new file mode 100644 index 00000000..70bc0a39 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/notoserif-heavy.txt @@ -0,0 +1,33 @@ +思源宋体 Heavy (Noto Serif SC Black) +Source: https://fonts.google.com/noto/specimen/Noto+Serif+SC +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +(c) 2017-2024 Adobe (http://www.adobe.com/). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/notoserif.txt b/apps/web/public/poster-fonts/licenses/notoserif.txt new file mode 100644 index 00000000..921d5cc0 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/notoserif.txt @@ -0,0 +1,33 @@ +思源宋体 (Noto Serif SC) +Source: https://fonts.google.com/noto/specimen/Noto+Serif+SC +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +(c) 2017-2024 Adobe (http://www.adobe.com/). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/smiley.txt b/apps/web/public/poster-fonts/licenses/smiley.txt new file mode 100644 index 00000000..3519e256 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/smiley.txt @@ -0,0 +1,33 @@ +得意黑 (Smiley Sans) +Source: https://github.com/atelier-anchor/smiley-sans +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright © 2022–2024 atelierAnchor. All rights reserved. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/spacegrotesk.txt b/apps/web/public/poster-fonts/licenses/spacegrotesk.txt new file mode 100644 index 00000000..30821da7 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/spacegrotesk.txt @@ -0,0 +1,33 @@ +Space Grotesk (Space Grotesk) +Source: https://fonts.google.com/specimen/Space+Grotesk +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/wenkai.txt b/apps/web/public/poster-fonts/licenses/wenkai.txt new file mode 100644 index 00000000..ff332015 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/wenkai.txt @@ -0,0 +1,34 @@ +霞鹜文楷 (LXGW WenKai) +Source: https://github.com/lxgw/LxgwWenKai +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2021-2025 LXGW (https://github.com/lxgw/LxgwWenKai) +Copyright 2020 The Klee Project Authors (https://github.com/fontworks-fonts/Klee) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/licenses/zhuque.txt b/apps/web/public/poster-fonts/licenses/zhuque.txt new file mode 100644 index 00000000..7b2c0539 --- /dev/null +++ b/apps/web/public/poster-fonts/licenses/zhuque.txt @@ -0,0 +1,33 @@ +朱雀仿宋 (Zhuque Fangsong) +Source: https://github.com/TrionesType/zhuque +This copy: subset and converted to WOFF2 by Qiaomu Cover Design + +Copyright 2023 JadeFoci + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: +- 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +- 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +- 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +- 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +- 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION +This license becomes null and void if any of the above conditions are not met. +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/public/poster-fonts/mashan.woff2 b/apps/web/public/poster-fonts/mashan.woff2 new file mode 100644 index 00000000..eea17c61 Binary files /dev/null and b/apps/web/public/poster-fonts/mashan.woff2 differ diff --git a/apps/web/public/poster-fonts/notosans-heavy.woff2 b/apps/web/public/poster-fonts/notosans-heavy.woff2 new file mode 100644 index 00000000..31aba365 Binary files /dev/null and b/apps/web/public/poster-fonts/notosans-heavy.woff2 differ diff --git a/apps/web/public/poster-fonts/notosans.woff2 b/apps/web/public/poster-fonts/notosans.woff2 new file mode 100644 index 00000000..0ade561d Binary files /dev/null and b/apps/web/public/poster-fonts/notosans.woff2 differ diff --git a/apps/web/public/poster-fonts/notoserif-heavy.woff2 b/apps/web/public/poster-fonts/notoserif-heavy.woff2 new file mode 100644 index 00000000..02884bcd Binary files /dev/null and b/apps/web/public/poster-fonts/notoserif-heavy.woff2 differ diff --git a/apps/web/public/poster-fonts/notoserif.woff2 b/apps/web/public/poster-fonts/notoserif.woff2 new file mode 100644 index 00000000..71bd02db Binary files /dev/null and b/apps/web/public/poster-fonts/notoserif.woff2 differ diff --git a/apps/web/public/poster-fonts/smiley.woff2 b/apps/web/public/poster-fonts/smiley.woff2 new file mode 100644 index 00000000..536cf6f0 Binary files /dev/null and b/apps/web/public/poster-fonts/smiley.woff2 differ diff --git a/apps/web/public/poster-fonts/spacegrotesk.woff2 b/apps/web/public/poster-fonts/spacegrotesk.woff2 new file mode 100644 index 00000000..fbacab1e Binary files /dev/null and b/apps/web/public/poster-fonts/spacegrotesk.woff2 differ diff --git a/apps/web/public/poster-fonts/wenkai.woff2 b/apps/web/public/poster-fonts/wenkai.woff2 new file mode 100644 index 00000000..59231f42 Binary files /dev/null and b/apps/web/public/poster-fonts/wenkai.woff2 differ diff --git a/apps/web/public/poster-fonts/zhuque.woff2 b/apps/web/public/poster-fonts/zhuque.woff2 new file mode 100644 index 00000000..34a1e586 Binary files /dev/null and b/apps/web/public/poster-fonts/zhuque.woff2 differ diff --git a/apps/web/src/components/EditorPane.tsx b/apps/web/src/components/EditorPane.tsx index af948bfe..202bcd42 100644 --- a/apps/web/src/components/EditorPane.tsx +++ b/apps/web/src/components/EditorPane.tsx @@ -316,6 +316,7 @@ import { } from "./editor/editor-pane-helpers"; type EditorPaneProps = { + onCreatePoster?: (memo: MemoDetail, text: string) => Promise; memo: MemoDetail | null; repository: EdgeEverRepository; desktopFocusMode: boolean; @@ -416,6 +417,7 @@ const RichEditorPane = ({ onRestored, onMobileDefaultEditConsumed, onSaveAsTemplate, + onCreatePoster, searchFocusToken, replaceFocusToken, aiAssistantOpenToken, @@ -4112,6 +4114,11 @@ const RichEditorPane = ({ onSearch={() => openNoteSearch()} textNoteMenuItems={( <> + {onCreatePoster && !effectiveReadOnly && { + const selection = editor?.state.selection; + const text = selection && !selection.empty ? editor?.state.doc.textBetween(selection.from, selection.to, "\n") ?? "" : editor?.getText() ?? memo?.contentText ?? ""; + void (async () => { if (!memo) return; if (hasUnsavedChangesRef.current) await saveMutation.mutateAsync(); await onCreatePoster(memoRef.current ?? memo, text); })().catch((error) => setSaveState("error")); + }}>{t("poster.createFromNote")}} {!isMobileViewport && !useMobilePlainTextEditor && !useMarkdownSourceEditor && ( {memo.diagramPreview.labels.join(" · ")} ) : null} + ) : memo.poster ? ( +
) : memo.infographic ? (