gitlab-glfm-markdown 0.0.31-aarch64-linux-gnu → 0.0.33-aarch64-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.
- checksums.yaml +4 -4
- data/Cargo.lock +178 -108
- data/README.md +40 -38
- data/ext/glfm_markdown/Cargo.lock +178 -108
- data/ext/glfm_markdown/Cargo.toml +2 -2
- data/ext/glfm_markdown/src/glfm.rs +118 -1
- data/ext/glfm_markdown/src/lib.rs +2 -0
- data/ext/glfm_markdown/src/main.rs +12 -0
- data/lib/glfm_markdown/3.1/glfm_markdown.so +0 -0
- data/lib/glfm_markdown/3.2/glfm_markdown.so +0 -0
- data/lib/glfm_markdown/3.3/glfm_markdown.so +0 -0
- data/lib/glfm_markdown/3.4/glfm_markdown.so +0 -0
- data/lib/glfm_markdown/version.rb +1 -1
- data/lib/glfm_markdown.rb +2 -0
- metadata +2 -2
@@ -1,6 +1,6 @@
|
|
1
1
|
[package]
|
2
2
|
name = "glfm_markdown"
|
3
|
-
version = "0.0.
|
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.
|
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
|
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.
|
4
|
+
version: 0.0.33
|
5
5
|
platform: aarch64-linux-gnu
|
6
6
|
authors:
|
7
7
|
- Brett Walker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rb_sys
|