gitlab-glfm-markdown 0.0.31-x86_64-linux-gnu → 0.0.33-x86_64-linux-gnu

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.
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "glfm_markdown"
3
- version = "0.0.31"
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.0", 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,
Binary file
Binary file
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GLFMMarkdown
4
- VERSION = '0.0.31'
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.31
4
+ version: 0.0.33
5
5
  platform: x86_64-linux-gnu
6
6
  authors:
7
7
  - Brett Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-14 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