frontend: print nothing under an empty paragraph

An empty paragraph printed 「(本段暂无内容)」 under its heading. A paragraph
with no sentences is not an error to report: it is a position in an outline, and
some of those are meant to be empty — a separator, a position the template
reserves, a section the writer has not reached yet. The words also go with the
paper on export, which is worse: a placeholder is the tool talking, inside the
document.

The structure stays exactly as it was (the heading, the count, the edit button);
only the annotation is gone. Measured on a paper with 19 empty paragraphs: no
placeholder element anywhere, the text absent from the page, and each empty
paragraph renders as its heading alone at 56px.
This commit is contained in:
2026-09-18 19:11:05 +08:00
parent e582198cc8
commit 20cd63f9f9
2 changed files with 14 additions and 12 deletions
@@ -5,8 +5,10 @@
* Three things about this component carry the feature's contracts:
*
* 1. **The structure is never skipped.** A paragraph with no sentences still
* renders its heading and a quiet placeholder, because the paper's shape
* comes from its template and an unwritten paragraph is still a paragraph.
* renders its heading, because the paper's shape comes from its template and
* an unwritten paragraph is still a paragraph — and then prints nothing
* under it. A blank paragraph is blank: some positions in an outline are
* meant to stay empty, and placeholder text would end up in the paper.
* 2. **A paragraph is reassembled from its sentences.** They are printed in
* `sort` order, and the only thing between them is the server's
* `separator_before` — a space for English, nothing for Chinese. This
@@ -117,7 +119,13 @@ const anchor = computed(() => `paragraph-${props.paragraph.paper_template_filed_
</template>
</p>
<p v-else class="paragraph-empty">本段暂无内容</p>
<!-- Nothing below the heading when there is nothing to print. An empty
paragraph is a position in an outline, and in an academic paper some
of those are meant to be empty a separator, a placeholder the
template reserves, a section the writer has not reached yet. Printing
本段暂无内容 into a paper puts words there that the paper did
not ask for, and on export they would go with it. The blank body is
the honest rendering of a blank paragraph. -->
</section>
</template>
@@ -213,13 +221,6 @@ const anchor = computed(() => `paragraph-${props.paragraph.paper_template_filed_
line-height: 0;
}
.paragraph-empty {
margin: 8px 0 0;
font-size: 13px;
color: var(--el-text-color-placeholder);
font-style: italic;
}
.cite-tip {
max-width: 320px;
}
@@ -11,8 +11,9 @@
* Three states are visible and none of them is an error:
*
* * a **written paragraph** — heading, prose, numbered citation markers;
* * an **empty paragraph** — heading and a placeholder, because the structure
* is there before the words are;
* * an **empty paragraph** — its heading and nothing else. Some positions in an
* outline are meant to stay empty, so a blank paragraph is printed blank
* rather than annotated;
* * an **unmatched paragraph** (未设定) — content whose position the current
* template does not define, kept in order rather than hidden, and recoverable
* by editing the paragraph or switching back.