98 lines
16 KiB
Markdown
98 lines
16 KiB
Markdown
# Text blocks and container layout
|
||
|
||
Apply C16–C23 and C27 in [production rules](production-rules.md) to page authoring, reconstruction, reusable components and collaboration. These are required constraints. A page-library example is a design reference, not an exemption from current rules. Keep fonts, colors and fixed UI tied to the selected external template; approved-mockup content sizes, geometry and spacing may use declared shared project adjustments under C27.
|
||
|
||
## One paragraph, one logical text block
|
||
|
||
Prefer one native text frame for each paragraph, including a continuous multi-line heading or label. Use wrapping, internal line breaks and styled runs inside that frame. Separate subheadings, separate list items, table cells, axis labels and independently meaningful node labels may be separate objects; a visual line break does not create a new semantic item. Do not split a paragraph across independent boxes to fit a container or imitate a mockup.
|
||
|
||
If the selected route has a concrete technical reason to fragment the text, preserve all of these properties:
|
||
|
||
- One stable logical block ID and one complete text/runs source. Store line breaks as part of that source or compute them from it, never as independent authored line strings.
|
||
- One overall frame, text-role contract, alignment, line spacing and reading order. A shared layout implementation derives fragment positions and wrapping from the whole block; the page author cannot override individual fragment coordinates or styles.
|
||
- One update operation: changing text, width or typography regenerates the whole block. Preserve the logical ID and fragment mapping in project inputs; group exported fragments as one movable unit where the route supports it.
|
||
- Record the reason for fragmentation and actual object behavior. Source-level unified editing does not prove PowerPoint-native text flow; if edits in PowerPoint cannot reflow across fragments, disclose that limit. Grouping existing independently authored lines alone does not create a logical text block.
|
||
|
||
The project content model may represent this as `{id, content, runs?, bounds, text_role, layout_rule}`. This is an authoring pattern, not new compiler metadata or an automatically interpreted schema. The shared renderer consumes the block. Fragments, if necessary, are derived output and are never independently maintained content.
|
||
|
||
### SVG and the bundled native route
|
||
|
||
Use a single SVG `text` for the paragraph. For authored visual rows, use direct-child `tspan` elements: repeat the parent's `x`, start at `dy="0"`, then use the same positive line step. Inline styling may use nested spans without baseline jumps. Take all coordinates and text styles from the selected layout/renderer, not hand-measured mockup offsets.
|
||
|
||
The bundled compiler's default `preserve` text flow retains eligible stacked rows as one native frame, with internal breaks. Arbitrary per-line `y`, unequal `x`, nested baseline jumps or prior line-flattening may produce separate frames. Do not assume that one SVG `text` guarantees one PPTX frame. Inspect the actual native object structure. Do not select split text flow for ordinary paragraph authoring.
|
||
|
||
For an object check, find the text-bearing `p:sp` objects and their `p:txBody` in the current slide XML. A normal paragraph should occupy one text-bearing shape; multiple `a:r` runs, `a:br` breaks or `a:p` elements inside the same `p:txBody` are internal text structure. Distinct semantic labels remain independent. If the fallback is used, check the whole-block source and fragment mapping as well as native counts. Group/native XML checks do not establish actual application editing or appearance.
|
||
|
||
## Paragraph line-breaking rules
|
||
|
||
Apply punctuation prohibitions at **every line start and end**. Closing punctuation, such as Chinese commas/full stops, closing brackets and closing quotation marks, stays with preceding text; opening brackets and opening quotation marks stay with following text. Do not split paired ellipses (`……`), paired dashes (`——`) or an unbreakable Western word/number merely to fill a line. Use the appropriate punctuation convention for the language and the selected template.
|
||
|
||
No paragraph line may consist of only one substantive character after ignoring surrounding punctuation and whitespace. Examples of prohibited lines include `果`, `果。`, `(果)` and `“果”。`. Adding more punctuation or spaces does not make a singleton acceptable. Check **all lines, including the final line**, rather than checking only the paragraph's tail. Punctuation-only lines are also invalid.
|
||
|
||
Independent short labels, standalone table values and separate mathematical symbols are not automatically paragraphs. Determine their actual function; do not relabel a sentence fragment as a label to evade this rule.
|
||
|
||
Recompute the complete paragraph's break positions. Prefer intact phrases/clauses where they fit; move enough content between neighboring lines to satisfy both punctuation and singleton rules. If the existing bounds cannot support compliant lines, use the template's normal rewrite/layout/capacity policy or C27's declared shared typography/geometry adjustment for an approved mockup, then check actual container/page overflow. Preserve the complete content and logical text block. Do not delete punctuation, silently add words, compress glyphs, invent an undeclared smaller font size or independently position the last line.
|
||
|
||
For supported plain horizontal text, `scripts/paragraph_layout.py` provides `wrap_paragraph(text, max_width, measure, *, max_lines=None)` and `validate_lines(lines)`. The caller supplies a width-measurement function using the actual selected font and size. The wrapper returns derived rows whose concatenation preserves the input; render them as internal lines of one text frame. Unsupported or impossible input raises an error instead of returning a known-invalid layout. Keep the helper with the shared renderer in the portable project's inputs.
|
||
|
||
This helper is not a complete Unicode line-breaking or typesetting engine, and does not automatically run on arbitrary SVG, rich-text runs or PowerPoint objects. Mixed run sizes need measurements for those actual runs; application reflow must be checked in the current render even when the source rows passed validation. The punctuation/widow descriptions in the [W3C Chinese Layout Requirements working draft](https://www.w3.org/TR/clreq/#prohibition_rules_for_line_start_end) and [orphan discussion](https://www.w3.org/TR/clreq/#handling_of_widows_and_orphans) inform the implementation; the user's requirement here explicitly covers every line.
|
||
|
||
## Spacing and paragraph separation
|
||
|
||
Check more than overlap. Text must not crowd a border, a preceding explanation, a following module or a connector. Check heading/body spacing, four-sided container padding, column/group gaps, and the clearance around separators and formulas. Judge actual glyphs and visible edges at normal viewing scale; a text frame's nominal box may contain extra space or fail to describe its ink.
|
||
|
||
Spacing is **fixed per relationship by the active shared recipe**, using template values by default or declared project-owned content-area adjustments for an approved mockup under C27. Content callers cannot supply numeric gaps, minima, arbitrary padding or alternate spacing variants. The recipe applies the chosen values consistently; callers do not decide how wide a particular instance should look. See the [fixed spacing contract](spacing.md). Resolve crowding by reflow, an authorized content/layout change or a controlled shared typography/spacing adjustment, followed by [container/page overflow review](visual-design.md#controlled-adjustments-for-approved-mockups). Preserve substantive content and readable hierarchy. Intentionally cropped watermarks, attached arrows and other decorative/semantic contacts retain their own fixed rules.
|
||
|
||
Preserve separate paragraphs as separate complete strings or explicit paragraph nodes. Use the fixed positive paragraph gap beyond the normal line-height slots, consistently within the same text role/variant. A line wrap inside one paragraph is not a new paragraph. Prefer native paragraph before/after spacing when multiple paragraphs share a frame; one native frame per paragraph is also supported, with the shared layout deriving all positions. Avoid empty paragraphs, repeated hard breaks and blank text boxes used only as spacers.
|
||
|
||
`scripts/text_block.py` provides `render_text_block(data, style, theme, bounds, component_id, measure)`. Data carries `schema_version: 1`, `paragraphs: [complete string, ...]` and optional declared `text_role`/`palette_index`. The renderer reads `components.text_group.padding_px` and `paragraph_gap_px`, resolves the role's line height and uses the measured paragraph helper. It emits one SVG text per paragraph with derived internal rows, rejects height overflow, and retains the full content and layout records in metadata. Paragraph bounds describe line-height slots, not exact font ink. Supply actual-font width measurements; check native frame counts and actual rendered spacing separately.
|
||
|
||
`scripts/layout_spacing.py` provides `resolve_spacing(style, role)` and `check_spacing(boxes, checks, *, style)`. Boxes map stable IDs to `[x,y,width,height]`; shared recipes declare directional gaps or padding using template role names. Numeric `minimum`/`expected`/override fields are rejected. Checks compare the exact fixed value, reporting `too_narrow`, `too_wide`, `overlap` or `outside`. Padding compares the outer frame with its complete usable inner area; actual text need not fill that area. Only declared meaningful relationships are checked. Floating-point tolerance is not layout allowance. This geometric check supplements actual visual review.
|
||
|
||
## Keep substantive explanations visible
|
||
|
||
Determine importance before assigning `caption`, `detail` or muted styles. Small muted text can carry background, data sources, data ranges, measurement definitions and citation details. A condition that directly changes the core conclusion or required action belongs with the related main information. Keep substantive chart explanations, key process conditions/timing, dependencies and conclusions readable as body, node text or a substantive callout heading.
|
||
|
||
Fix ambiguous or overstrong body text directly, supplement the evidence or integrate the necessary condition. Remove disclaimers that only anticipate hypothetical objections and add no useful understanding, judgment or action. A small note or warning box does not justify keeping an unnecessary statement. Retain concrete useful warnings with emphasis suited to their role; ordinary source and range notes do not need to become warnings.
|
||
|
||
| Statement | Treatment |
|
||
|---|---|
|
||
| Data source, collection date, citation locator or supplementary range/measurement definition | Small supplementary text is allowed; retain source metadata too |
|
||
| “Only proceed after approval”, “retry after timeout” | Main process/node text; the viewer needs it to follow the process |
|
||
| “Method B is faster” | Main comparison/conclusion hierarchy |
|
||
| The measured dataset defines the scope of the core performance claim | State that scope in the claim or its related main information; detailed dataset provenance may remain small |
|
||
| A unit/definition that changes what a chart means | Keep it visibly associated with the chart at a suitable readable level |
|
||
|
||
Read the page without the small muted notes. Its workflow, conclusion and necessary scope must remain understandable and accurate. Then check the notes for useful supporting detail rather than repeated disclaimers. This check also applies to any field named `source`: the field name cannot make a substantive claim into provenance.
|
||
|
||
## Different roles inside a container
|
||
|
||
Assign named roles before rendering: for example `card_heading`, `card_body`, `value`, `unit` and `source_note`, mapped to the external template's declared typography and palette, with any C27 content-size adjustment declared in the shared project style/recipe. If subheading and body have different functions, distinguish them perceptibly with size, weight and/or color. Using serif for one and sans serif for the other at otherwise identical styling is insufficient. Do not introduce undeclared instance sizes or literal colors to create the difference.
|
||
|
||
The required distinction is between functions, not every string. Peers with the same function share a role. Verify the distinction in the actual theme and normal viewing scale; two almost identical colors are not a useful hierarchy. A substantive statement remains a body/callout role even when the component offers a small `detail` field.
|
||
|
||
## A shared layout implementation for each container type
|
||
|
||
Reuse a template/component renderer when it fits. For a new container, define one shared recipe/function and a content interface before placing its instances. The same type/variant must use the same padding, slot order, text roles, wrapping/height policy, icon size/alignment and spacing rules across pages and authors.
|
||
|
||
The caller may pass semantic content, an icon asset/role, a declared variant and the whole container's bounds/placement. Internal `title_x`, `body_y`, `icon_offset`, per-line coordinates and similar instance-level overrides are prohibited. The renderer may compute geometry from bounds, content and common style; deterministic calculation is how the rule is implemented. A shared content-driven height/wrapping policy can produce different heights for different text lengths.
|
||
|
||
If content does not fit, use the recipe's supported wrapping/height rules, rewrite, enlarge the whole slot or change the page/layout. Add a named shared variant only for a meaningful repeated need; do not disguise each instance's manual offsets as its own variant. Do not stretch generated text or icons with a group transform to make them fit. Regenerate from new bounds.
|
||
|
||
Diagram nodes may be arranged to express the actual topology. Each repeated node's internal label/icon layout still comes from the shared node recipe. Custom diagrams do not justify hand-positioning the contents of every repeated card or node.
|
||
|
||
Keep the recipe, parameters, content and assets in the portable project's declared inputs. For multiple authors, the coordinator freezes the shared implementation/style/variant set; page workers only instantiate it. Shared changes return to the coordinator and trigger checks on affected pages.
|
||
|
||
## Review before delivery
|
||
|
||
1. Compare the complete paragraph source with native text frames. Confirm one frame, or the justified whole-block fallback with derived fragments; inspect actual breaks, reading order and edit behavior at the requested evidence level.
|
||
2. Review every small muted note for meaning. Move essential statements into the main hierarchy and verify no qualification disappeared in the move.
|
||
3. Compare subheading/body and other distinct roles within each container at normal viewing scale. Font family alone cannot pass.
|
||
4. Compare all instances of each type/variant and inspect their creation calls/source. Confirm one shared implementation, no child-coordinate overrides and no post-generation nudges. Equal-looking screenshots alone cannot prove this.
|
||
5. Read the actual line starts, line ends and last line of each paragraph. Reject forbidden punctuation positions, split unbreakable marks/words, punctuation-only rows and every singleton row, including a character surrounded by punctuation. Reflow and regenerate the whole logical paragraph when changing content, width or typography.
|
||
6. Check the active shared style/recipe's exact fixed values for text padding, heading/body, adjacent-group and formula/connector spacing, including any declared C27 project adjustment. Verify no numeric spacing overrides or instance variants entered the caller input. Check actual glyph/edge clearance separately; non-overlap alone is insufficient.
|
||
7. Locate semantic paragraph boundaries in the content source and render. Confirm visible extra separation between paragraphs while maintaining normal line spacing within each paragraph; no dummy empty paragraphs or manually positioned spacer objects.
|
||
8. For mathematics, inspect [font and equation structure](mathematics.md), then the actual render. Confirm scripts/fractions/limits have not become ordinary unformatted text or a picture.
|
||
|
||
The compiler cannot reliably infer these semantic properties from arbitrary SVG. Combine source review, native object checks and current rendered-page review; mark unavailable application checks explicitly.
|