From 20cd63f9f9b9aca0778f1ecfa88e466163882418 Mon Sep 17 00:00:00 2001
From: govin
Date: Fri, 18 Sep 2026 19:11:05 +0800
Subject: [PATCH] frontend: print nothing under an empty paragraph
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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.
---
.../src/components/papers/PaperParagraph.vue | 21 ++++++++++---------
frontend/src/views/papers/PaperDetailView.vue | 5 +++--
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/frontend/src/components/papers/PaperParagraph.vue b/frontend/src/components/papers/PaperParagraph.vue
index 26201e2..b640fb1 100644
--- a/frontend/src/components/papers/PaperParagraph.vue
+++ b/frontend/src/components/papers/PaperParagraph.vue
@@ -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_
- (本段暂无内容)
+
@@ -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;
}
diff --git a/frontend/src/views/papers/PaperDetailView.vue b/frontend/src/views/papers/PaperDetailView.vue
index fa76a4c..ac8d8b9 100644
--- a/frontend/src/views/papers/PaperDetailView.vue
+++ b/frontend/src/views/papers/PaperDetailView.vue
@@ -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.