gitlab-glfm-markdown 0.0.32 → 0.0.33

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8783e3abd91c5a60248453cd6adfd4fe025a6be5fcd4288708117cb91fe57628
4
- data.tar.gz: cb1a1880c09f4aeae9849682f5452c4aa01cf7d751ab880372b13ebd92efc8f0
3
+ metadata.gz: fb8448f904c8d824f877414066a5958e72eda7bd405af187c8093ffb88c1763c
4
+ data.tar.gz: 26244206863034e94f575db9678c4a97bae736ce8010fc49c849142d8648fdfc
5
5
  SHA512:
6
- metadata.gz: f2378222831599e70ef3e4b4357ff5b95bb088218de7a0ce7a59ba899a3056f75fa10b13b3e66473ce7e0bcd8df3d8d31dee21074cc43b1574c58a478890f3d4
7
- data.tar.gz: 3a196f9875eae6c768eb0a6d9f90ea46399c2d53aa3b0f468784e1564228828b1c48e48d5ed5630b199ba03b0713ec98c546e6267ab9760548512bdcdf8128f0
6
+ metadata.gz: bf82fe75c037f4a8e22015f4bcddb1fd45d9ebdb08640322a0770b16a1d4cedae41008c318213e2ed2292dfbf240102fcf09484f0b20abf34c48685f6cd6bbd5
7
+ data.tar.gz: 7dcee4806c5acecf184bad92b2cdfc980a114cc84ab05bb31a22db34c51b3f059cd6268fc65f13a9f73a15eec7c95c537870054d420bb9ba77751ab9eb95ff6e
data/Cargo.lock CHANGED
@@ -227,9 +227,9 @@ checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
227
227
 
228
228
  [[package]]
229
229
  name = "comrak"
230
- version = "0.39.1"
230
+ version = "0.40.0"
231
231
  source = "registry+https://github.com/rust-lang/crates.io-index"
232
- checksum = "2fefab951771fc3beeed0773ce66a4f7b706273fc6c4c95b08dd1615744abcf5"
232
+ checksum = "32c3278f396e5707769a68bc0943e9b8f84a172836b173827810918279621747"
233
233
  dependencies = [
234
234
  "caseless",
235
235
  "emojis",
@@ -320,7 +320,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
320
320
 
321
321
  [[package]]
322
322
  name = "glfm_markdown"
323
- version = "0.0.32"
323
+ version = "0.0.33"
324
324
  dependencies = [
325
325
  "clap",
326
326
  "comrak",
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Implements GLFM (as used by GitLab) using the Rust-based markdown parser [comrak](https://github.com/kivikakk/comrak)
7
7
  and providing a Ruby interface.\
8
- _Currently using `comrak 0.39.1`_.
8
+ _Currently using `comrak 0.40.0`_.
9
9
 
10
10
  This project is still in constant flux, so interfaces and functionality can change at any time.
11
11
 
@@ -32,43 +32,45 @@ GLFMMarkdown.to_html('# header', options: { sourcepos: true })
32
32
 
33
33
  ### Options
34
34
 
35
- | Option name | Description |
36
- |--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
37
- | `autolink` | Enable the `autolink` extension |
38
- | `description_lists` | Enable the `description-lists` extension |
39
- | `escape` | Escape raw HTML instead of clobbering it |
40
- | `escape_char_spans` | Wrap escaped characters in a `<span>` to allow any post-processing to recognize them |
41
- | `figure_with_caption` | Render the image as a figure element with the title as its caption |
42
- | `footnotes` | Enable the `footnotes` extension |
43
- | `full_info_string` | Enable full info strings for code blocks |
44
- | `gemojis` | Enable the `gemojis` extensions - translate gemojis into UTF-8 characters |
45
- | `gfm_quirks` | Enables GFM-style quirks in output HTML, such as not nesting <strong> tags |
46
- | `github_pre_lang` | Use GitHub-style `<pre lang>` for code blocks |
47
- | `greentext` | Enable the `greentext` extension - requires at least one space after a `>` character to generate a blockquote, and restarts blockquote nesting across unique lines of input |
48
- | `hardbreaks` | Treat newlines as hard line breaks |
49
- | `header_ids <PREFIX>` | Enable the `header-id` extension, with the given ID prefix |
50
- | `ignore_empty_links` | Ignore empty links in input |
51
- | `ignore_setext` | Ignore setext headings in input |
52
- | `math_code` | Enables `math code` extension, using math code syntax |
53
- | `math_dollars` | Enables `math dollars` extension, using math dollar syntax |
54
- | `multiline_block_quotes` | Enable the `multiline-block-quotes` extension |
55
- | `default_html` | Disables any custom HTML, and returns default HTML from `comrak` |
56
- | `placeholder_detection` | Detect placeholder variables in the format `%{placeholder}` |
57
- | `relaxed_autolinks` | Enable relaxing of autolink parsing, allowing links to be recognized when in brackets |
58
- | `relaxed_tasklist_character` | Enable relaxing which character is allowed in tasklists |
59
- | `sourcepos` | Include source mappings in HTML attributes |
60
- | `smart` | Use smart punctuation |
61
- | `spoiler` | Enable the `spoiler` extension - use double vertical bars |
62
- | `strikethrough` | Enable the `strikethrough` extension |
63
- | `superscript` | Enable the `superscript` extension |
64
- | `table` | Enable the `table` extension |
65
- | `tagfilter` | Enable the `tagfilter` extension |
66
- | `tasklist` | Enable the `tasklist` extension |
67
- | `underline` | Enables the `underline` extension - use double underscores |
68
- | `unsafe` | Allow raw HTML and dangerous URLs |
69
- | `wikilinks_title_after_pipe` | Enable the `wikilinks_title_after_pipe` extension |
70
- | `wikilinks_title_before_pipe` | Enable the `wikilinks_title_before_pipe` extension |
71
- | `debug` | Show debug information |
35
+ | Option name | Description |
36
+ |-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
37
+ | `autolink` | Enable the `autolink` extension |
38
+ | `description_lists` | Enable the `description-lists` extension |
39
+ | `escape` | Escape raw HTML instead of clobbering it |
40
+ | `escape_char_spans` | Wrap escaped characters in a `<span>` to allow any post-processing to recognize them |
41
+ | `figure_with_caption` | Render the image as a figure element with the title as its caption |
42
+ | `footnotes` | Enable the `footnotes` extension |
43
+ | `full_info_string` | Enable full info strings for code blocks |
44
+ | `gemojis` | Enable the `gemojis` extensions - translate gemojis into UTF-8 characters |
45
+ | `gfm_quirks` | Enables GFM-style quirks in output HTML, such as not nesting <strong> tags |
46
+ | `github_pre_lang` | Use GitHub-style `<pre lang>` for code blocks |
47
+ | `greentext` | Enable the `greentext` extension - requires at least one space after a `>` character to generate a blockquote, and restarts blockquote nesting across unique lines of input |
48
+ | `hardbreaks` | Treat newlines as hard line breaks |
49
+ | `header_ids <PREFIX>` | Enable the `header-id` extension, with the given ID prefix |
50
+ | `ignore_empty_links` | Ignore empty links in input |
51
+ | `ignore_setext` | Ignore setext headings in input |
52
+ | `inapplicable_tasks` | Allow inapplicable tasks items. Must also set the `relaxed_tasklist_character` option. |
53
+ | `math_code` | Enables `math code` extension, using math code syntax |
54
+ | `math_dollars` | Enables `math dollars` extension, using math dollar syntax |
55
+ | `multiline_block_quotes` | Enable the `multiline-block-quotes` extension |
56
+ | `default_html` | Disables any custom HTML, and returns default HTML from `comrak` |
57
+ | `placeholder_detection` | Detect placeholder variables in the format `%{placeholder}` |
58
+ | `relaxed_autolinks` | Enable relaxing of autolink parsing, allowing links to be recognized when in brackets |
59
+ | `relaxed_tasklist_character` | Enable relaxing which character is allowed in tasklists |
60
+ | `sourcepos` | Include source mappings in HTML attributes |
61
+ | `smart` | Use smart punctuation |
62
+ | `spoiler` | Enable the `spoiler` extension - use double vertical bars |
63
+ | `strikethrough` | Enable the `strikethrough` extension |
64
+ | `superscript` | Enable the `superscript` extension |
65
+ | `table` | Enable the `table` extension |
66
+ | `tagfilter` | Enable the `tagfilter` extension |
67
+ | `tasklist` | Enable the `tasklist` extension |
68
+ | `tasklist_classes` | Output classes on tasklist elements so that they can be styled with CSS |
69
+ | `underline` | Enables the `underline` extension - use double underscores |
70
+ | `unsafe` | Allow raw HTML and dangerous URLs |
71
+ | `wikilinks_title_after_pipe` | Enable the `wikilinks_title_after_pipe` extension |
72
+ | `wikilinks_title_before_pipe` | Enable the `wikilinks_title_before_pipe` extension |
73
+ | `debug` | Show debug information |
72
74
 
73
75
  ## Dingus / Demo
74
76
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "glfm_markdown"
3
- version = "0.0.32"
3
+ version = "0.0.33"
4
4
  edition = "2021"
5
5
  authors = ["digitalmoksha <bwalker@gitlab.com>"]
6
6
  description = "GitLab Flavored Markdown parser and formatter. 100% CommonMark-compatible. Experimental."
@@ -15,7 +15,7 @@ required-features = ["cli"]
15
15
 
16
16
  [dependencies]
17
17
  clap = { version = "=4.4.18", optional = true, features = ["derive", "string"] }
18
- comrak = { version = "0.39.1", default-features = false, features = ["shortcodes"] }
18
+ comrak = { version = "0.40.0", default-features = false, features = ["shortcodes"] }
19
19
  magnus = "0.6.2"
20
20
  rb-sys = { version = "0.9.86", default-features = false, features = ["stable-api-compiled-fallback"] }
21
21
  regex = "1.11.1"
@@ -1,5 +1,5 @@
1
1
  use comrak::html::{ChildRendering, Context};
2
- use comrak::nodes::{AstNode, NodeValue};
2
+ use comrak::nodes::{AstNode, ListType, NodeValue};
3
3
  use comrak::{create_formatter, html, parse_document, Arena, Plugins};
4
4
  use lazy_static::lazy_static;
5
5
  use regex::Regex;
@@ -45,14 +45,20 @@ pub struct RenderOptions {
45
45
  pub table: bool,
46
46
  pub tagfilter: bool,
47
47
  pub tasklist: bool,
48
+ pub tasklist_classes: bool,
48
49
  pub underline: bool,
49
50
  pub unsafe_: bool,
50
51
  pub wikilinks_title_after_pipe: bool,
51
52
  pub wikilinks_title_before_pipe: bool,
52
53
 
54
+ /// GLFM specific options
55
+
53
56
  /// Only use default comrak HTML formatting
54
57
  pub default_html: bool,
55
58
 
59
+ /// Detect inapplicable tasks (`- [~]`)
60
+ pub inapplicable_tasks: bool,
61
+
56
62
  /// Detect and mark potential placeholder variables, which
57
63
  /// have the format `%{PLACEHOLDER}`
58
64
  pub placeholder_detection: bool,
@@ -62,6 +68,7 @@ pub struct RenderOptions {
62
68
 
63
69
  pub struct RenderUserData {
64
70
  pub default_html: bool,
71
+ pub inapplicable_tasks: bool,
65
72
  pub placeholder_detection: bool,
66
73
  pub debug: bool,
67
74
  }
@@ -70,6 +77,7 @@ impl From<&RenderOptions> for RenderUserData {
70
77
  fn from(options: &RenderOptions) -> Self {
71
78
  RenderUserData {
72
79
  default_html: options.default_html,
80
+ inapplicable_tasks: options.inapplicable_tasks,
73
81
  placeholder_detection: options.placeholder_detection,
74
82
  debug: options.debug,
75
83
  }
@@ -112,6 +120,7 @@ impl From<&RenderOptions> for comrak::Options<'_> {
112
120
  comrak_options.render.ignore_empty_links = options.ignore_empty_links;
113
121
  comrak_options.render.ignore_setext = options.ignore_setext;
114
122
  comrak_options.render.sourcepos = options.sourcepos;
123
+ comrak_options.render.tasklist_classes = options.tasklist_classes;
115
124
  // comrak_options.render.syntax_highlighting = options.syntax_highlighting;
116
125
 
117
126
  comrak_options.render.unsafe_ = options.unsafe_;
@@ -162,6 +171,12 @@ create_formatter!(CustomFormatter<RenderUserData>, {
162
171
  },
163
172
  NodeValue::Image(_) => |context, node, entering| {
164
173
  return render_image(context, node, entering);
174
+ },
175
+ NodeValue::List(_) => |context, node, entering| {
176
+ return render_list(context, node, entering);
177
+ },
178
+ NodeValue::TaskItem(_) => |context, node, entering| {
179
+ return render_task_item(context, node, entering);
165
180
  }
166
181
  });
167
182
 
@@ -276,6 +291,108 @@ fn render_link<'a>(
276
291
  Ok(ChildRendering::HTML)
277
292
  }
278
293
 
294
+ // Overridden to use class `task-list` instead of `contains-task-list`
295
+ // to align with GitLab class usage
296
+ fn render_list<'a>(
297
+ context: &mut Context<RenderUserData>,
298
+ node: &'a AstNode<'a>,
299
+ entering: bool,
300
+ ) -> io::Result<ChildRendering> {
301
+ if !entering || !context.options.render.tasklist_classes {
302
+ return html::format_node_default(context, node, entering);
303
+ }
304
+
305
+ let NodeValue::List(ref nl) = node.data.borrow().value else {
306
+ panic!("Attempt to render invalid node as list")
307
+ };
308
+
309
+ context.cr()?;
310
+ match nl.list_type {
311
+ ListType::Bullet => {
312
+ context.write_all(b"<ul")?;
313
+ if nl.is_task_list {
314
+ context.write_all(b" class=\"task-list\"")?;
315
+ }
316
+ html::render_sourcepos(context, node)?;
317
+ context.write_all(b">\n")?;
318
+ }
319
+ ListType::Ordered => {
320
+ context.write_all(b"<ol")?;
321
+ if nl.is_task_list {
322
+ context.write_all(b" class=\"task-list\"")?;
323
+ }
324
+ html::render_sourcepos(context, node)?;
325
+ if nl.start == 1 {
326
+ context.write_all(b">\n")?;
327
+ } else {
328
+ writeln!(context, " start=\"{}\">", nl.start)?;
329
+ }
330
+ }
331
+ }
332
+
333
+ Ok(ChildRendering::HTML)
334
+ }
335
+
336
+ // Overridden to detect inapplicable task list items
337
+ fn render_task_item<'a>(
338
+ context: &mut Context<RenderUserData>,
339
+ node: &'a AstNode<'a>,
340
+ entering: bool,
341
+ ) -> io::Result<ChildRendering> {
342
+ if !context.user.inapplicable_tasks {
343
+ return html::format_node_default(context, node, entering);
344
+ }
345
+
346
+ let NodeValue::TaskItem(symbol) = node.data.borrow().value else {
347
+ panic!("Attempt to render invalid node as task item")
348
+ };
349
+
350
+ if symbol.is_none() || matches!(symbol, Some('x' | 'X')) {
351
+ return html::format_node_default(context, node, entering);
352
+ }
353
+
354
+ if entering {
355
+ // Handle an inapplicable task symbol.
356
+ if matches!(symbol, Some('~')) {
357
+ context.cr()?;
358
+ context.write_all(b"<li")?;
359
+ context.write_all(b" class=\"inapplicable")?;
360
+
361
+ if context.options.render.tasklist_classes {
362
+ context.write_all(b" task-list-item")?;
363
+ }
364
+ context.write_all(b"\"")?;
365
+
366
+ html::render_sourcepos(context, node)?;
367
+ context.write_all(b">")?;
368
+ context.write_all(b"<input type=\"checkbox\"")?;
369
+
370
+ if context.options.render.tasklist_classes {
371
+ context.write_all(b" class=\"task-list-item-checkbox\"")?;
372
+ }
373
+
374
+ context.write_all(b" data-inapplicable disabled=\"\"> ")?;
375
+ } else {
376
+ // Don't allow unsupported symbols to render a checkbox
377
+ context.cr()?;
378
+ context.write_all(b"<li")?;
379
+
380
+ if context.options.render.tasklist_classes {
381
+ context.write_all(b" class=\"task-list-item\"")?;
382
+ }
383
+
384
+ html::render_sourcepos(context, node)?;
385
+ context.write_all(b">")?;
386
+ context.write_all(b"[")?;
387
+ context.escape(symbol.unwrap().to_string().as_bytes())?;
388
+ context.write_all(b"] ")?;
389
+ }
390
+ } else {
391
+ context.write_all(b"</li>\n")?;
392
+ }
393
+
394
+ Ok(ChildRendering::HTML)
395
+ }
279
396
  fn render_text<'a>(
280
397
  context: &mut Context<RenderUserData>,
281
398
  node: &'a AstNode<'a>,
@@ -33,6 +33,7 @@ pub fn render_to_html_rs(text: String, options: RHash) -> String {
33
33
  header_ids: get_string_opt("header_ids", options),
34
34
  ignore_empty_links: get_bool_opt("ignore_empty_links", options),
35
35
  ignore_setext: get_bool_opt("ignore_setext", options),
36
+ inapplicable_tasks: get_bool_opt("inapplicable_tasks", options),
36
37
  math_code: get_bool_opt("math_code", options),
37
38
  math_dollars: get_bool_opt("math_dollars", options),
38
39
  multiline_block_quotes: get_bool_opt("multiline_block_quotes", options),
@@ -48,6 +49,7 @@ pub fn render_to_html_rs(text: String, options: RHash) -> String {
48
49
  table: get_bool_opt("table", options),
49
50
  tagfilter: get_bool_opt("tagfilter", options),
50
51
  tasklist: get_bool_opt("tasklist", options),
52
+ tasklist_classes: get_bool_opt("tasklist_classes", options),
51
53
  underline: get_bool_opt("underline", options),
52
54
  unsafe_: get_bool_opt("unsafe", options),
53
55
  wikilinks_title_after_pipe: get_bool_opt("wikilinks_title_after_pipe", options),
@@ -146,6 +146,10 @@ struct Args {
146
146
  #[arg(long)]
147
147
  tasklist: bool,
148
148
 
149
+ /// Output classes on tasklist elements so that they can be styled with CSS
150
+ #[arg(long)]
151
+ tasklist_clases: bool,
152
+
149
153
  /// Enables underlines using double underscores
150
154
  #[arg(long)]
151
155
  underline: bool,
@@ -166,6 +170,12 @@ struct Args {
166
170
  #[arg(long)]
167
171
  default_html: bool,
168
172
 
173
+ /// GLFM specific options
174
+
175
+ /// Detect inapplicable tasks (`- [~]`)
176
+ #[arg(long)]
177
+ inapplicable_tasks: bool,
178
+
169
179
  /// Detect and marks potential placeholder variables, which
170
180
  /// have the format `%{PLACEHOLDER}`
171
181
  #[arg(long)]
@@ -209,6 +219,7 @@ fn main() {
209
219
  header_ids: cli.header_ids,
210
220
  ignore_empty_links: cli.ignore_empty_links,
211
221
  ignore_setext: cli.ignore_setext,
222
+ inapplicable_tasks: cli.inapplicable_tasks,
212
223
  math_code: cli.math_code,
213
224
  math_dollars: cli.math_dollars,
214
225
  multiline_block_quotes: cli.multiline_block_quotes,
@@ -224,6 +235,7 @@ fn main() {
224
235
  table: cli.table,
225
236
  tagfilter: cli.tagfilter,
226
237
  tasklist: cli.tasklist,
238
+ tasklist_classes: cli.tasklist_classes,
227
239
  underline: cli.underline,
228
240
  unsafe_: cli.unsafe_,
229
241
  wikilinks_title_after_pipe: cli.wikilinks_title_after_pipe,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GLFMMarkdown
4
- VERSION = '0.0.32'
4
+ VERSION = '0.0.33'
5
5
  end
data/lib/glfm_markdown.rb CHANGED
@@ -14,6 +14,7 @@ module GLFMMarkdown
14
14
  gfm_quirks: true,
15
15
  github_pre_lang: false,
16
16
  hardbreaks: false,
17
+ inapplicable_tasks: false,
17
18
  math_code: false,
18
19
  math_dollars: false,
19
20
  multiline_block_quotes: true,
@@ -24,6 +25,7 @@ module GLFMMarkdown
24
25
  table: true,
25
26
  tagfilter: false,
26
27
  tasklist: true,
28
+ tasklist_classes: true,
27
29
  unsafe: true,
28
30
 
29
31
  debug: false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-glfm-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.32
4
+ version: 0.0.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-07-03 00:00:00.000000000 Z
11
+ date: 2025-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys