A block's body is a Markdown string, so no text export or import can round-trip
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 5/100
調査の方向性
This is a design proposal, not a task with a clear first step. The payload points to lib/syntax/inline.ml (the entity parser that drops the backslash), Type_op.md_escaped, astExportMarkdown, and the fuzz namespaces listed in the issue, which are the places to read to see the collisions. Done would mean a maintainer-agreed data model for block bodies (text runs, refs, code and math nodes) and a decision on :block/title, which needs a design discussion before any code.
索引モデルが issue の本文から書いたものです。
説明
A DB graph stores a block's whole body in :block/title as a Markdown string, and every text format Logseq moves blocks through (Copy as text and paste, the Markdown mirror and the file-graph importer, the clipboard) is Markdown read by the same parser. A block's text and the format's structure share one grammar, so text that looks like structure comes back as structure. This cannot be fixed one bug at a time.
Why it cannot be patched
- mldoc's parse is not injective.
\DeltaGandDeltaGboth parse toPlain "DeltaG"(theentityparser inlib/syntax/inline.mldrops the backslash before a word that is not an entity, and mldoc's own testinline-entity / no separatorexpects it). Once two texts parse the same, no printer can give either one back. - mldoc has no printer that inverts its parser.
Type_op.md_escapedisfailwith "not impl yet".astExportMarkdownis a lossy exporter: the text\# xparses as plain text# xand prints as# x, which parses as a heading. - The outline grammar cannot hold some block text at all. A block whose text has a line
- xshows it as a line of the block; in any outline file that line is a child block. Only an escape can tell them apart, and every escape needs every reader to agree on it.
The bugs it produces
Found by fuzzing the round-trips with no escaping added anywhere: master with the open structural PRs merged, harness on yuxi-liu-wired/logseq roundtrip-fuzz, namespaces frontend.handler.export-paste-fuzz-test, frontend.worker.markdown-mirror-import-fuzz-test, frontend.handler.copy-paste-fuzz-test, logseq.db.sqlite.export-import-fuzz-test, run with FUZZ_N=10 FUZZ_SEED=1 and FUZZ_SEED=11.
Copy as text, then paste:
| block before | block after |
|---|---|
text émoji😀 \tail. |
text émoji😀 tail. |
text >中文 \[^1] |
text 中文 [^1] |
text émoji😀 \(x\)[^1] |
text émoji😀 $x$ [1] |
empty block, tag research |
block whose text is tags:: research |
block $$ with p-choice:: sad, then block \frac{a}{b} |
one block: $$, tags:: research, p-choice:: sad, - $$, frac{a}{b}, $$ |
Markdown mirror, then the importer:
| block before | block after |
|---|---|
text DONE |
a done task, empty text |
text ## |
a heading 2 |
text [#A] **bold** tail. #[[Beta Gamma]] |
priority high, tag Beta Gamma, text **bold** tail. |
text >{{query (task TODO)}}>中文 |
a quote block (task TODO)>中文, tag Quote |
text :PROPERTIES: / :x: 1 / :END: |
property x = 1 |
text ~~s~~key:: v42 |
empty text |
text id:: 6aa|a|b| |
empty text |
text émoji😀 / - a:b '42 |
the second line becomes a child block |
The EDN export and import, which serialize data instead of printing Markdown, found no mismatches on the same seeds.
Patches withdrawn
Each of these escaped or special-cased one collision. They are closed: fixing symptoms hides the design problem, and the fuzzers kept finding new collisions after each one.
- #13721 export: keep backslash escapes
- #13743 mirror: escape text a Markdown reader takes as structure
- #13719 paste: Markdown quote lines as a quote block
- #13720 export and paste: property, status, priority, tag and collapsed lines
- #13730 export: text before an embed macro
- #13732 export: macro syntax, embeds in property values
- #13742 mirror: tags and status written next to a math fence
- #13754 paste: keep
#tagsyntax
Related symptoms already filed: #13755, logseq/db-test#1439, logseq/db-test#1440.
The fix
Store a block's body as data, not as a Markdown string: text runs, emphasis, refs and tags by id, code and math as their own nodes. Keep :block/title a plain-text name. Then exporting is a printer over that data and importing is a parser into it, and the DB's own formats round-trip by serialization, as EDN already does.
- 主要言語
- 言語のデータがありません
- スター
- 29
- フォーク
- 2
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
logseq/db-test のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
-
Page titles with `$$`, `$&`, `` $` `` or `$'` change when block refs are resolved対応中かも @RaphaelFakhri が 20 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
`#Asset` label is not displayed on asset nodes when `Hide from Node` is disabled対応中かも @tiensonqin が 23 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
似ている issue
-
[Bug]: GraphML export writes invalid XML when a value contains a control character (e.g. form feed)オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
topoteretes/cognee#6646 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
opensanctions/opensanctions#6227 ·
メンテナーはふだん 1 日以内に返信
-
ai-driven-fuzzing bug claude Minor
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
メンテナーはふだん 2 日以内に返信
-
channels:edit check:passed
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
duckduckgo/tracker-radar#409 ·