@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 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 the `descriptionList` option is enabled the plugin converts specially formatted bullet lists into HTML description lists (`<dl>`).
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
- - If the Term line is not separated from the description by a blank line, then the Term line must end with two ASCII spaces (a Markdown line-break) or a backslash `\` to indicate the description follows.
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: Currently the content inside `<dd>` elements is always wrapped in `<p>` elements.
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
- // Check if markdown-it-attrs is loaded (detect once at plugin initialization)
30
- const hasAttrsPlugin = md.core.ruler.__rules__.some(rule => rule.name === 'curly_attributes')
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 original listInfos as tokens may have been removed in Phase2
60
- // (Uses markerInfo stored in tokens)
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
- processHtmlBlocks(state)
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, listInfos, opt)
89
+ generateSpans(tokens, opt)
70
90
 
71
91
  return true
72
92
  }
73
93
 
74
- md.core.ruler.before('inline', 'numbering_ul_phases', listProcessor)
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
- if (hasAttrsPlugin) {
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.2.3",
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.5.5",
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"