@peaceroad/markdown-it-numbering-ul-regarded-as-ol 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/index.js +38 -54
- package/package.json +2 -2
- package/src/phase0-description-list.js +232 -113
- package/src/phase1-analyze.js +39 -8
- package/src/phase2-convert.js +177 -193
- package/src/phase3-attributes.js +24 -47
- package/src/phase5-spans.js +73 -54
- package/src/preprocess-literal-lists.js +295 -362
- package/src/types-utility.js +0 -15
- package/src/phase6-attrs-migration.js +0 -184
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Markdown's default ordered list markers are limited. This plugin extends Markdown's unordered lists so they can use many kinds of ordered markers.
|
|
4
4
|
|
|
5
|
-
Also, this plugin option provides a description-list conversion. Unordered list items whose first line is wrapped in `**` and followed by two spaces are converted into `<dl>` elements.
|
|
5
|
+
Also, this plugin option provides a description-list conversion. Unordered list items whose first line is wrapped in `**` and followed by a description separator (two spaces, `\\`, or a blank line) are converted into `<dl>` elements.
|
|
6
6
|
|
|
7
7
|
## Ordered lists conversion behavior
|
|
8
8
|
|
|
@@ -71,6 +71,11 @@ After the marker separator, an ASCII space is normally expected. For `fullwidth`
|
|
|
71
71
|
|
|
72
72
|
- Marker type detection is deterministic: gather all markers at a nesting level, match them against the canonical definitions, keep the type that explains the most items while preserving numeric continuity, and use the order in `listTypes.json` only as a final tiebreaker.
|
|
73
73
|
- Flattening: A pattern like `- 1.` is represented by the default `ul > li > ol` nesting structure in markdown-it, but this plugin simplifies it to a single `ol` by default to match the representation of other markers.
|
|
74
|
+
- With `markdown-it-attrs`, attr blocks follow that plugin's nearest-block behavior. This plugin does not reassign list attrs after flattening.
|
|
75
|
+
|
|
76
|
+
### Source map behavior
|
|
77
|
+
|
|
78
|
+
The flattener uses `token.map` (markdown-it source line numbers) to preserve loose list output for `- 1.` style lists. markdown-it normally assigns `map` to block tokens, but it can be missing if tokens are constructed manually, cloned without `map`, or stripped by upstream plugins to save memory. In that case, the plugin falls back to markdown-it's `paragraph.hidden` flags and `- 1.` lists with blank lines may render as tight lists (no `<p>` wrappers). Avoid stripping `map` data or set `unremoveUlNest: true` if exact loose rendering is required.
|
|
74
79
|
|
|
75
80
|
Note: For custom marker lists (those rendered with `role="list"`) the plugin assumes you will hide the native marker via CSS (for example `ol[role="list"] { list-style: none; }`). The `hasListStyleNone` option can be enabled to add `style="list-style: none;"` directly to generated `<ol>` elements.
|
|
76
81
|
|
|
@@ -85,22 +90,32 @@ You can customize the conversion using options.
|
|
|
85
90
|
- `hasListStyleNone` (boolean) — When the plugin emits `role="list"`, also add `style="list-style: none;"` to the `<ol>`.
|
|
86
91
|
- `omitMarkerMetadata` (boolean) — If `true`, omit the `data-marker-prefix` / `data-marker-suffix` attributes.
|
|
87
92
|
- `addMarkerStyleToClass` (boolean) — When `true`, append suffix-style information to the generated class name (e.g. `ol-decimal-with-round-round`). When `false` (default) the class stays as `ol-decimal`.
|
|
93
|
+
- `enableLiteralNumberingFix` (boolean) — Enable literal nested list recovery (for example, nested lists starting with 2 or greater). This is opt-in; it only applies inside list items, evaluates indentation relative to the parent list marker (marker width + 0–3 spaces), and does not convert code blocks (indent >= marker width + 4).
|
|
94
|
+
- Compatibility note: switching the default from `false` to `true` changes rendered HTML by design. On the current test corpus (`394` markdown cases), `18` cases change.
|
|
95
|
+
- Changed files in that comparison: `examples-default-14-repeated-numbers.txt` (`7`), `examples-option-literal-numbering-attrs.txt` (`1`), `examples-option-literal-numbering-fix-disabled.txt` (`2`), `examples-option-literal-numbering-fix.txt` (`3`), `examples-option-literal-numbering-indent.txt` (`4`).
|
|
96
|
+
- Recommendation: keep the default as `false` for patch/minor releases; if changing the default to `true`, treat it as a breaking change and release a major version.
|
|
88
97
|
|
|
89
98
|
## Description lists conversion behavior
|
|
90
99
|
|
|
91
|
-
When
|
|
100
|
+
When `descriptionList` or `descriptionListWithDiv` is enabled, the plugin converts specially formatted bullet lists into HTML description lists (`<dl>`).
|
|
92
101
|
|
|
93
102
|
- Each list item must start with a `**Term**` line.
|
|
94
|
-
-
|
|
103
|
+
- The `**Term**` line must be the first direct block inside that list item (term-like text inside nested sub-lists does not trigger conversion).
|
|
104
|
+
- If the description continues on the next line without a blank line, the Term line must end with two ASCII spaces (a Markdown line-break) or a backslash `\`. Inline `{.attrs}` immediately after the term are allowed.
|
|
105
|
+
- If the Term line is followed by a blank line, the description can start in the next paragraph or list (line-break control characters are optional).
|
|
106
|
+
- Same-line descriptions such as `- **Term** Description` are not converted.
|
|
107
|
+
- Same-line backslash forms such as `- **Term**\ Description` are also not converted (the hard break marker must be followed by an actual newline).
|
|
108
|
+
- Term-line attrs can be written in multiple adjacent blocks (`**Term** {.a} {#id} {data-x=1}`) and are merged onto `<dt>`.
|
|
109
|
+
- Attr-like braces are kept as description text only when your plugin chain does not parse them as attributes. With `markdown-it-attrs`, forms like `{foo}` may be treated as boolean attributes.
|
|
95
110
|
|
|
96
111
|
In the conversion the `**Term**` line becomes a `<dt>` and the subsequent lines become the corresponding `<dd>`.
|
|
97
112
|
|
|
98
|
-
Note:
|
|
113
|
+
Note: Text descriptions are wrapped in `<p>` elements; additional paragraphs and lists keep markdown-it's block structure.
|
|
99
114
|
|
|
100
115
|
### Description list options
|
|
101
116
|
|
|
102
117
|
- `descriptionList` (boolean) — Enable conversion of `**Term**` list patterns into `<dl>` description lists.
|
|
103
|
-
- `descriptionListWithDiv` (boolean) — Wrap `<dt>/<dd>` pairs in a `<div>` when enabled.
|
|
118
|
+
- `descriptionListWithDiv` (boolean) — Wrap `<dt>/<dd>` pairs in a `<div>` when enabled. This option also enables description-list conversion even when `descriptionList` is `false`.
|
|
104
119
|
- `descriptionListDivClass` (string) — Class applied to the wrapper `<div>` when `descriptionListWithDiv` is enabled (empty string disables the class).
|
|
105
120
|
|
|
106
121
|
## Examples: Ordered Lists
|
package/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { convertLists } from './src/phase2-convert.js'
|
|
|
5
5
|
import { addAttributes } from './src/phase3-attributes.js'
|
|
6
6
|
import { processHtmlBlocks } from './src/phase4-html-blocks.js'
|
|
7
7
|
import { generateSpans } from './src/phase5-spans.js'
|
|
8
|
-
import { moveNestedListAttributes } from './src/phase6-attrs-migration.js'
|
|
9
8
|
import { normalizeLiteralOrderedLists } from './src/preprocess-literal-lists.js'
|
|
10
9
|
|
|
11
10
|
const mditNumberingUl = (md, option) => {
|
|
@@ -21,13 +20,30 @@ const mditNumberingUl = (md, option) => {
|
|
|
21
20
|
omitMarkerMetadata: false, // true=omit data-marker-prefix/suffix attributes
|
|
22
21
|
useCounterStyle: false, // true=users will use @counter-style; suppress marker spans and role attr
|
|
23
22
|
addMarkerStyleToClass: false, // true=append -with-* marker style suffix to class names
|
|
23
|
+
enableLiteralNumberingFix: false, // true=normalize nested lists that don't start at 1 (opt-in)
|
|
24
24
|
|
|
25
25
|
// Override with user options
|
|
26
26
|
...option
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
|
|
29
|
+
const addRuleAfter = (ruler, afterName, ruleName, fn) => {
|
|
30
|
+
try {
|
|
31
|
+
ruler.after(afterName, ruleName, fn)
|
|
32
|
+
} catch {
|
|
33
|
+
ruler.push(ruleName, fn)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const dlProcessor = (state) => {
|
|
38
|
+
if (!state.env) {
|
|
39
|
+
state.env = {}
|
|
40
|
+
}
|
|
41
|
+
if (!opt.descriptionList && !opt.descriptionListWithDiv) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
processDescriptionList(state.tokens, opt)
|
|
45
|
+
return true
|
|
46
|
+
}
|
|
31
47
|
|
|
32
48
|
const listProcessor = (state) => {
|
|
33
49
|
// Initialize state.env
|
|
@@ -36,14 +52,9 @@ const mditNumberingUl = (md, option) => {
|
|
|
36
52
|
}
|
|
37
53
|
|
|
38
54
|
const tokens = state.tokens
|
|
39
|
-
|
|
40
|
-
// ===== PHASE 0: Description List =====
|
|
41
|
-
// Convert **Term**: pattern from paragraph to bullet_list, then to dl/dt/dd
|
|
42
|
-
// Must run before Phase 1 (parsed as bullet_list)
|
|
43
|
-
processDescriptionList(tokens, opt)
|
|
44
55
|
|
|
45
56
|
// Normalize literal nested ordered lists (markdown-it only creates nested lists when they start at 1)
|
|
46
|
-
normalizeLiteralOrderedLists(tokens)
|
|
57
|
+
normalizeLiteralOrderedLists(tokens, opt)
|
|
47
58
|
|
|
48
59
|
// ===== PHASE 1: List Structure Analysis =====
|
|
49
60
|
// Analyze marker detection and structure without token conversion
|
|
@@ -56,36 +67,32 @@ const mditNumberingUl = (md, option) => {
|
|
|
56
67
|
|
|
57
68
|
// ===== PHASE 3: Add Attributes =====
|
|
58
69
|
// Add type, class, data-* attributes to converted lists
|
|
59
|
-
// Use
|
|
60
|
-
|
|
61
|
-
addAttributes(tokens, listInfos, opt)
|
|
70
|
+
// Use markerInfo stored on list tokens (safe after Phase2 mutations)
|
|
71
|
+
addAttributes(tokens, opt)
|
|
62
72
|
|
|
63
73
|
// ===== PHASE 4: HTML Block Processing =====
|
|
64
74
|
// Remove indents from HTML blocks in lists and normalize line breaks
|
|
65
|
-
|
|
75
|
+
let hasNestedHtmlBlock = false
|
|
76
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
77
|
+
const token = tokens[i]
|
|
78
|
+
if (token.type === 'html_block' && token.level > 0) {
|
|
79
|
+
hasNestedHtmlBlock = true
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (hasNestedHtmlBlock) {
|
|
84
|
+
processHtmlBlocks(state)
|
|
85
|
+
}
|
|
66
86
|
|
|
67
87
|
// ===== PHASE 5: Span Generation =====
|
|
68
88
|
// Generate marker spans in alwaysMarkerSpan mode
|
|
69
|
-
generateSpans(tokens,
|
|
89
|
+
generateSpans(tokens, opt)
|
|
70
90
|
|
|
71
91
|
return true
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
md.core.ruler.before('inline', '
|
|
75
|
-
|
|
76
|
-
if (!opt.unremoveUlNest) {
|
|
77
|
-
// Move nested list attributes only when flattening is enabled
|
|
78
|
-
const nestedListAttrProcessor = (state) => {
|
|
79
|
-
moveNestedListAttributes(state.tokens)
|
|
80
|
-
return true
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (hasAttrsPlugin) {
|
|
84
|
-
md.core.ruler.after('curly_attributes', 'numbering_ul_nested_attrs', nestedListAttrProcessor)
|
|
85
|
-
} else {
|
|
86
|
-
md.core.ruler.push('numbering_ul_nested_attrs', nestedListAttrProcessor)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
94
|
+
md.core.ruler.before('inline', 'numbering_dl_parser', dlProcessor)
|
|
95
|
+
md.core.ruler.after('numbering_dl_parser', 'numbering_ul_phases', listProcessor)
|
|
89
96
|
|
|
90
97
|
// Description list: Move paragraph attributes to dl and add custom renderers
|
|
91
98
|
if (opt.descriptionList || opt.descriptionListWithDiv) {
|
|
@@ -95,30 +102,7 @@ const mditNumberingUl = (md, option) => {
|
|
|
95
102
|
return true
|
|
96
103
|
}
|
|
97
104
|
|
|
98
|
-
|
|
99
|
-
md.core.ruler.after('curly_attributes', 'numbering_dl_attrs', dlAttrProcessor)
|
|
100
|
-
} else {
|
|
101
|
-
md.core.ruler.push('numbering_dl_attrs', dlAttrProcessor)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Add custom renderers for description list tokens
|
|
105
|
-
// Helper function to render attributes
|
|
106
|
-
const renderAttrs = (token) => {
|
|
107
|
-
if (!token.attrs || token.attrs.length === 0) return ''
|
|
108
|
-
return ' ' + token.attrs.map(([key, value]) => `${key}="${value}"`).join(' ')
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
md.renderer.rules.dl_open = (tokens, idx) => `<dl${renderAttrs(tokens[idx])}>\n`
|
|
112
|
-
md.renderer.rules.dl_close = () => '</dl>\n'
|
|
113
|
-
md.renderer.rules.dt_open = (tokens, idx) => `<dt${renderAttrs(tokens[idx])}>`
|
|
114
|
-
md.renderer.rules.dt_close = () => '</dt>\n'
|
|
115
|
-
md.renderer.rules.dd_open = (tokens, idx) => `<dd${renderAttrs(tokens[idx])}>\n`
|
|
116
|
-
md.renderer.rules.dd_close = () => '</dd>\n'
|
|
117
|
-
|
|
118
|
-
if (opt.descriptionListWithDiv) {
|
|
119
|
-
md.renderer.rules.div_open = (tokens, idx) => `<div${renderAttrs(tokens[idx])}>\n`
|
|
120
|
-
md.renderer.rules.div_close = () => '</div>\n'
|
|
121
|
-
}
|
|
105
|
+
addRuleAfter(md.core.ruler, 'curly_attributes', 'numbering_dl_attrs', dlAttrProcessor)
|
|
122
106
|
}
|
|
123
107
|
}
|
|
124
108
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaceroad/markdown-it-numbering-ul-regarded-as-ol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "This markdown-it plugin regard ul element with numbering lists as ol element.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/peaceroad/p7d-markdown-it-numbering-ul-regarded-as-ol#readme",
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@peaceroad/markdown-it-strong-ja": "^0.
|
|
30
|
+
"@peaceroad/markdown-it-strong-ja": "^0.7.2",
|
|
31
31
|
"markdown-it": "^14.1.0",
|
|
32
32
|
"markdown-it-attrs": "^4.3.1",
|
|
33
33
|
"markdown-it-deflist": "^3.0.0"
|