Skip to content

Commit 6e67be9

Browse files
Merge pull request #6 from StructuralPython/features/explicit-list-syntax
Explicit list syntax (_ul / _ol); bare lists become paragraphs
2 parents 904c26b + ee62ace commit 6e67be9

18 files changed

Lines changed: 439 additions & 149 deletions

File tree

Examples/Document Configuration/report.yml

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ _style:
99
Customizing your document configuration and styling:
1010
- >
1111
There are `three` categories of document configuration
12-
- 1: The document template
13-
2: Text styles
14-
3: Table styles
15-
12+
- _ol:
13+
- The document template
14+
- Text styles
15+
- Table styles
16+
1617
- >
1718
These three categories are set at three different levels of priority
18-
- 1: The internal defaults (lowest priority)
19-
2: Project config
20-
3: Document internal config (highest priority)
19+
- _ol:
20+
- The internal defaults (lowest priority)
21+
- Project config
22+
- Document internal config (highest priority)
2123

2224
- >
2325
Each level of priority in the configuration heirarchy effectively inherits the configuration of the level of priority above it.
@@ -27,10 +29,11 @@ Customizing your document configuration and styling:
2729
- The document template (_doc):
2830
- >
2931
The template controls settings such as
30-
- - Page size
31-
- Margins
32-
- PDF background file path
33-
- And whether or not you have a separate set of the above settings applying to the first page of your document or not.
32+
- _ul:
33+
- Page size
34+
- Margins
35+
- PDF background file path
36+
- And whether or not you have a separate set of the above settings applying to the first page of your document or not.
3437

3538
- >
3639
Currently, the document template is internally configured to only use a single content frame. This limitation would only affect you if you wanted to do something like a two-column layout (where text flows into the second column on the same page once the first one is full).
@@ -39,39 +42,36 @@ Customizing your document configuration and styling:
3942
- >
4043
With text styles, you can control the body text
4144
- Text styling attributes:
42-
- Font family
43-
- Text color
44-
- Size
45-
- Line spacing ratio
46-
- Bullet style:
47-
- Bullet color
48-
- Bullet symbol heirarchy
49-
- Bullet indentation
50-
45+
_ul:
46+
- Font family
47+
- Text color
48+
- Size
49+
- Line spacing ratio
50+
- "Bullet style:"
51+
- - Bullet color
52+
- Bullet symbol heirarchy
53+
- Bullet indentation
54+
5155
- >
5256
You can also control the text heading styles separately from the body text by adjusting their
53-
54-
- - Font family
55-
- Text color
56-
- Typographic ratio (in musical intervals, e.g. "minor second" or "major third")
57+
58+
- _ul:
59+
- Font family
60+
- Text color
61+
- Typographic ratio (in musical intervals, e.g. "minor second" or "major third")
5762
- Table styles (_tablestyle):
5863
- >
5964
You can control how your tables are displayed by modifying the table style. With the _tablestyle key, you can control
60-
- Table header
61-
- background (color)
62-
- gridlines (above, below, between)
63-
- text
64-
- font
65-
- size
66-
- color
67-
- Table rows
68-
- even (rows, background color)
69-
- odd (rows, background color)
70-
- gridlines (above, below, between)
71-
- text
72-
- font
73-
- size
74-
- color
65+
- _ul:
66+
- "Table header:"
67+
- - background (color)
68+
- gridlines (above, below, between)
69+
- "text: font, size, color"
70+
- "Table rows:"
71+
- - even (rows, background color)
72+
- odd (rows, background color)
73+
- gridlines (above, below, between)
74+
- "text: font, size, color"
7575

7676

7777

Examples/Document variables/report.yml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ Document Variables (_vars):
1515
representation is shown (i.e. the result of str(var)).
1616
1717
This document has five variables defined, a, b, c, d, e.
18-
- _spacer: 0 # The use of a "0-spacer" is a hack to prevent the paragraph above being interpreted as a bullet point.
19-
20-
- - a = {{a}}
21-
- b = {{b}}
22-
- c = {{c}}
23-
- d = {{d}}
24-
- e = {{e.key2}}
25-
- f = {{f}}
18+
- _ul:
19+
- a = {{a}}
20+
- b = {{b}}
21+
- c = {{c}}
22+
- d = {{d}}
23+
- e = {{e.key2}}
24+
- f = {{f}}
2625
- Passing Python Objects: >
2726
It is also possible to pass variable data as Python objects to blocks (see "YMPrint blocks") using the $var syntax (similar to bash).
2827

Examples/PDF Backgrounds/report.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Custom styling with PDF backgrounds:
2626
Form fields are _automatically_ populated when a document variable name exactly matches the PDF form field name.
2727
2828
If you want to avoid this behaviour:
29-
- Make sure that none of your variable names match your field names (i.e. using a special naming convention for your form field names to prevent accidental clashes)
30-
- Do not use form fields
29+
_ul:
30+
- Make sure that none of your variable names match your field names (i.e. using a special naming convention for your form field names to prevent accidental clashes)
31+
- Do not use form fields
3132
Example: The form fields below have been populated from the document vars

Examples/Simple example/report.yml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@ Report title:
1717
1818
- Standard content types:
1919
- Bullets:
20-
- Bullet 1
21-
- Bullet 2
22-
- Bullet 3
23-
- - Bullet 4
24-
- Bullet 5
25-
- Bullet 6
20+
_ul:
21+
- Bullet 1
22+
- Bullet 2
23+
- Bullet 3
24+
- - Bullet 4
25+
- Bullet 5
26+
- Bullet 6
2627
- Ordered list:
27-
1: First Item
28-
2: Second item
29-
3:
30-
12: Fourth item,
31-
6: Fifth item,
32-
10: Sixth Item
28+
_ol:
29+
- First item
30+
- Second item
31+
- - Nested first
32+
- Nested second
33+
- Nested third
3334
- Tables:
3435
- Item Number: 12.01
3536
Description: There is a problem here. This report documents it.

Examples/YMPrint blocks/report.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ Using Blocks:
1616
scale_ratio: 0.3
1717
- Admonitions:
1818
- "The following admonitions blocks are available:"
19-
-
20-
- _info
21-
- _warning
22-
- _danger
23-
- _tip
24-
- _note
19+
- _ul:
20+
- _info
21+
- _warning
22+
- _danger
23+
- _tip
24+
- _note
2525
- They are rendered below
2626

2727
_info: Here is an "info" admonition
@@ -108,10 +108,10 @@ Using Blocks:
108108
for k in [a, b, c]:
109109
acc.append(k)
110110
- "Now, the values of the variables a, b, and c can be included in the document:"
111-
-
112-
- a = {{py1.a}} (using py1.a)
113-
- b = {{py1.b}} (using py1.b)
114-
- c = {{py1.c}} (using py1.c)
111+
- _ul:
112+
- a = {{py1.a}} (using py1.a)
113+
- b = {{py1.b}} (using py1.b)
114+
- c = {{py1.c}} (using py1.c)
115115
- _code:
116116
source: |
117117
yaml_data: is being shown
@@ -132,6 +132,6 @@ Using Blocks:
132132
path: extra_vars.json
133133
namespace: extra_vars
134134
- "Here are the values of the vars contained within the 'extravars' namespace:"
135-
-
136-
- bn = {{extra_vars.bn}}
137-
- dx = {{extra_vars.dx}}
135+
- _ul:
136+
- bn = {{extra_vars.bn}}
137+
- dx = {{extra_vars.dx}}

design/explicit-list-syntax.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Design: Explicit list syntax (`_ul` / `_ol`)
2+
3+
Status: prototype
4+
Branch: `features/explicit-list-syntax` (off `main`)
5+
6+
## Problem
7+
8+
A YAML list under a heading is structurally identical whether the author means
9+
"several paragraphs" or "an unordered list". Today YMPrint guesses from the list's
10+
*contents*:
11+
12+
- a **pure** list of strings → `convert_ul` → bullets
13+
- a **mixed** list (strings + block/subsection dicts) → each string becomes a
14+
paragraph
15+
16+
So the same `heading:\n - >prose` renders as a bullet or a paragraph depending on
17+
what else is in the list. A single wrapped paragraph under a heading silently comes
18+
out as a one-item bullet list (observed under "Alignment and named styles" in the
19+
text-styles example).
20+
21+
The ambiguity is **structural** — YAML gives identical structure to both intents —
22+
so no heuristic can resolve it. One of the two meanings must be made explicit.
23+
24+
## Decision
25+
26+
Make **bullets explicit** and let a bare list mean "a sequence of content items".
27+
28+
- A YAML list is always a *sequence of blocks*: strings become paragraphs, mappings
29+
become subsections (heading + content), in order. It is never auto-bulleted.
30+
- Unordered lists are written with the **`_ul`** block; ordered lists with **`_ol`**.
31+
- The implicit detections (`check_for_nested_lists` → bullets, and the
32+
dict-with-integer-keys → numbered list) are retired from dispatch. The check
33+
functions remain (still unit-tested) but no longer drive `build_story`.
34+
35+
This yields a single rule with no guessing: *a list is content in order; bullets and
36+
numbers are named constructs.*
37+
38+
### Rejected alternative
39+
40+
Making **paragraphs** explicit (`_p`) instead would avoid breaking existing bullet
41+
lists, but it keeps the surprising default (bare list = bullets) and only adds an
42+
escape hatch beside the ambiguity rather than removing it.
43+
44+
## Syntax
45+
46+
```yaml
47+
Findings:
48+
- The inspection covered three areas. # paragraph
49+
- _ul: # unordered list
50+
- The handrail is loose on the north stair.
51+
- Two ceiling tiles are water-stained.
52+
- - a nested sub-point # nested list → sub-bullets
53+
- another sub-point
54+
- Recommended actions: # subsection heading
55+
_ol: # ordered list
56+
- Re-secure the handrail.
57+
- Replace the stained tiles.
58+
```
59+
60+
- `_ul` value is a list; nested lists produce sub-bullets (unchanged `convert_ul`).
61+
- `_ol` value is a list; numbering is automatic by position; nested lists produce
62+
nested numbering. (`convert_ol` also still accepts a mapping for back-compat.)
63+
- Both may be written as a list item (`- _ul: [...]`) or as the value of a heading
64+
key (`heading:\n _ul: [...]`). Suffixes are allowed for uniqueness in a mapping
65+
(`_ul_left`, `_ol_steps`), consistent with other block codes.
66+
67+
## Implementation
68+
69+
`_ul` / `_ol` are intercepted **directly in `build_story`**, not registered in the
70+
block registry. Two reasons:
71+
72+
1. They are structural (they change how a list is interpreted), sitting naturally
73+
beside the list-dispatch logic.
74+
2. It keeps them **forward-compatible with scoped text styles**: `build_story` is
75+
where a `current_style` parameter lives (on the `features/scoped-text-styles`
76+
branch), so intercepting here lets `_ul`/`_ol` pass the active style into
77+
`convert_ul`/`convert_ol`. Routing them through the generic block registry —
78+
whose converters do not receive the active style — would make bullets ignore the
79+
surrounding `_textstyle` scope. (On this `main`-based branch there is no
80+
`current_style` yet; the interception point is chosen so the two features compose
81+
cleanly when merged.)
82+
83+
| File | Change |
84+
| --- | --- |
85+
| `story_builder.py` | Intercept `_ul`/`_ol` (list-item and heading-value forms, with suffixes) → `convert_ul`/`convert_ol`. Replace the implicit bullet/ordered dispatch: a bare list/mapping now always recurses (strings → paragraphs, mappings → subsections). |
86+
| `content_converters.py` | `convert_ol` accepts a **list** (positional numbering; nested lists nest) as well as a mapping (back-compat). |
87+
| test data / examples | Migrate bare-list bullets and integer-keyed ordered lists to `_ul` / `_ol`. Genuine multi-paragraph lists (e.g. report 2 "third topic") are left as lists and now render as paragraphs — the intended fix. |
88+
89+
## Backward compatibility
90+
91+
This is a **breaking** content change (consistent with the pre-1.0 status and the
92+
earlier multi-page-template change): existing documents that relied on bare lists for
93+
bullets, or integer-keyed mappings for numbered lists, must adopt `_ul` / `_ol`.
94+
95+
## Open questions
96+
97+
- Should `_ol` support an explicit `start:` offset or custom markers (a/i/…)?
98+
- Should list items be allowed to contain blocks (e.g. an image inside a bullet)?
99+
- When merged with scoped text styles, thread `current_style` into the `_ul`/`_ol`
100+
interception so bullets honour the active family.

0 commit comments

Comments
 (0)