motion-markdown-it 0.4.0.3.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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +243 -0
  3. data/lib/motion-markdown-it.rb +71 -0
  4. data/lib/motion-markdown-it/common/entities.rb +1084 -0
  5. data/lib/motion-markdown-it/common/html_blocks.rb +60 -0
  6. data/lib/motion-markdown-it/common/html_re.rb +28 -0
  7. data/lib/motion-markdown-it/common/string.rb +14 -0
  8. data/lib/motion-markdown-it/common/url_schemas.rb +173 -0
  9. data/lib/motion-markdown-it/common/utils.rb +216 -0
  10. data/lib/motion-markdown-it/helpers/parse_link_destination.rb +75 -0
  11. data/lib/motion-markdown-it/helpers/parse_link_label.rb +51 -0
  12. data/lib/motion-markdown-it/helpers/parse_link_title.rb +48 -0
  13. data/lib/motion-markdown-it/index.rb +507 -0
  14. data/lib/motion-markdown-it/parser_block.rb +113 -0
  15. data/lib/motion-markdown-it/parser_core.rb +46 -0
  16. data/lib/motion-markdown-it/parser_inline.rb +121 -0
  17. data/lib/motion-markdown-it/presets/commonmark.rb +76 -0
  18. data/lib/motion-markdown-it/presets/default.rb +42 -0
  19. data/lib/motion-markdown-it/presets/zero.rb +59 -0
  20. data/lib/motion-markdown-it/renderer.rb +286 -0
  21. data/lib/motion-markdown-it/ruler.rb +327 -0
  22. data/lib/motion-markdown-it/rules_block/blockquote.rb +138 -0
  23. data/lib/motion-markdown-it/rules_block/code.rb +35 -0
  24. data/lib/motion-markdown-it/rules_block/fence.rb +94 -0
  25. data/lib/motion-markdown-it/rules_block/heading.rb +56 -0
  26. data/lib/motion-markdown-it/rules_block/hr.rb +45 -0
  27. data/lib/motion-markdown-it/rules_block/html_block.rb +73 -0
  28. data/lib/motion-markdown-it/rules_block/lheading.rb +54 -0
  29. data/lib/motion-markdown-it/rules_block/list.rb +242 -0
  30. data/lib/motion-markdown-it/rules_block/paragraph.rb +51 -0
  31. data/lib/motion-markdown-it/rules_block/reference.rb +161 -0
  32. data/lib/motion-markdown-it/rules_block/state_block.rb +184 -0
  33. data/lib/motion-markdown-it/rules_block/table.rb +161 -0
  34. data/lib/motion-markdown-it/rules_core/block.rb +20 -0
  35. data/lib/motion-markdown-it/rules_core/inline.rb +20 -0
  36. data/lib/motion-markdown-it/rules_core/linkify.rb +138 -0
  37. data/lib/motion-markdown-it/rules_core/normalize.rb +44 -0
  38. data/lib/motion-markdown-it/rules_core/replacements.rb +90 -0
  39. data/lib/motion-markdown-it/rules_core/smartquotes.rb +158 -0
  40. data/lib/motion-markdown-it/rules_core/state_core.rb +20 -0
  41. data/lib/motion-markdown-it/rules_inline/autolink.rb +74 -0
  42. data/lib/motion-markdown-it/rules_inline/backticks.rb +51 -0
  43. data/lib/motion-markdown-it/rules_inline/emphasis.rb +172 -0
  44. data/lib/motion-markdown-it/rules_inline/entity.rb +51 -0
  45. data/lib/motion-markdown-it/rules_inline/escape.rb +55 -0
  46. data/lib/motion-markdown-it/rules_inline/html_inline.rb +49 -0
  47. data/lib/motion-markdown-it/rules_inline/image.rb +158 -0
  48. data/lib/motion-markdown-it/rules_inline/link.rb +153 -0
  49. data/lib/motion-markdown-it/rules_inline/newline.rb +47 -0
  50. data/lib/motion-markdown-it/rules_inline/state_inline.rb +57 -0
  51. data/lib/motion-markdown-it/rules_inline/strikethrough.rb +130 -0
  52. data/lib/motion-markdown-it/rules_inline/text.rb +94 -0
  53. data/lib/motion-markdown-it/token.rb +134 -0
  54. data/lib/motion-markdown-it/version.rb +5 -0
  55. data/spec/motion-markdown-it/bench_mark_spec.rb +44 -0
  56. data/spec/motion-markdown-it/commonmark_spec.rb +16 -0
  57. data/spec/motion-markdown-it/markdown_it_spec.rb +18 -0
  58. data/spec/motion-markdown-it/misc_spec.rb +277 -0
  59. data/spec/motion-markdown-it/ruler_spec.rb +153 -0
  60. data/spec/motion-markdown-it/testgen_helper.rb +68 -0
  61. data/spec/motion-markdown-it/token_spec.rb +17 -0
  62. data/spec/motion-markdown-it/utils_spec.rb +82 -0
  63. data/spec/spec_helper.rb +6 -0
  64. metadata +158 -0
@@ -0,0 +1,113 @@
1
+ # internal
2
+ # class ParserBlock
3
+ #
4
+ # Block-level tokenizer.
5
+ #------------------------------------------------------------------------------
6
+ module MarkdownIt
7
+ class ParserBlock
8
+
9
+ attr_accessor :ruler
10
+
11
+ RULES = [
12
+ # First 2 params - rule name & source. Secondary array - list of rules,
13
+ # which can be terminated by this one.
14
+ [ 'code', lambda { |state, startLine, endLine, silent| RulesBlock::Code.code(state, startLine, endLine, silent) } ],
15
+ [ 'fence', lambda { |state, startLine, endLine, silent| RulesBlock::Fence.fence(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
16
+ [ 'blockquote', lambda { |state, startLine, endLine, silent| RulesBlock::Blockquote.blockquote(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'list' ] ],
17
+ [ 'hr', lambda { |state, startLine, endLine, silent| RulesBlock::Hr.hr(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
18
+ [ 'list', lambda { |state, startLine, endLine, silent| RulesBlock::List.list(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
19
+ [ 'reference', lambda { |state, startLine, endLine, silent| RulesBlock::Reference.reference(state, startLine, endLine, silent) } ],
20
+ [ 'heading', lambda { |state, startLine, endLine, silent| RulesBlock::Heading.heading(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
21
+ [ 'lheading', lambda { |state, startLine, endLine, silent| RulesBlock::Lheading.lheading(state, startLine, endLine, silent) } ],
22
+ [ 'html_block', lambda { |state, startLine, endLine, silent| RulesBlock::HtmlBlock.html_block(state, startLine, endLine, silent) }, [ 'paragraph', 'reference', 'blockquote' ] ],
23
+ [ 'table', lambda { |state, startLine, endLine, silent| RulesBlock::Table.table(state, startLine, endLine, silent) }, [ 'paragraph', 'reference' ] ],
24
+ [ 'paragraph', lambda { |state, startLine, endLine, silent| RulesBlock::Paragraph.paragraph(state, startLine) } ]
25
+ ]
26
+
27
+
28
+ # new ParserBlock()
29
+ #------------------------------------------------------------------------------
30
+ def initialize
31
+ # ParserBlock#ruler -> Ruler
32
+ #
33
+ # [[Ruler]] instance. Keep configuration of block rules.
34
+ @ruler = Ruler.new
35
+
36
+ RULES.each do |rule|
37
+ @ruler.push(rule[0], rule[1], {alt: (rule[2] || []) })
38
+ end
39
+ end
40
+
41
+
42
+ # Generate tokens for input range
43
+ #------------------------------------------------------------------------------
44
+ def tokenize(state, startLine, endLine, ignored = false)
45
+ rules = @ruler.getRules('')
46
+ len = rules.length
47
+ line = startLine
48
+ hasEmptyLines = false
49
+ maxNesting = state.md.options[:maxNesting]
50
+
51
+ while line < endLine
52
+ state.line = line = state.skipEmptyLines(line)
53
+ break if line >= endLine
54
+
55
+ # Termination condition for nested calls.
56
+ # Nested calls currently used for blockquotes & lists
57
+ break if state.tShift[line] < state.blkIndent
58
+
59
+ # If nesting level exceeded - skip tail to the end. That's not ordinary
60
+ # situation and we should not care about content.
61
+ if state.level >= maxNesting
62
+ state.line = endLine
63
+ break
64
+ end
65
+
66
+ # Try all possible rules.
67
+ # On success, rule should:
68
+ #
69
+ # - update `state.line`
70
+ # - update `state.tokens`
71
+ # - return true
72
+ 0.upto(len - 1) do |i|
73
+ ok = rules[i].call(state, line, endLine, false)
74
+ break if ok
75
+ end
76
+
77
+ # set state.tight iff we had an empty line before current tag
78
+ # i.e. latest empty line should not count
79
+ state.tight = !hasEmptyLines
80
+
81
+ # paragraph might "eat" one newline after it in nested lists
82
+ if state.isEmpty(state.line - 1)
83
+ hasEmptyLines = true
84
+ end
85
+
86
+ line = state.line
87
+
88
+ if line < endLine && state.isEmpty(line)
89
+ hasEmptyLines = true
90
+ line += 1
91
+
92
+ # two empty lines should stop the parser in list mode
93
+ break if line < endLine && state.parentType == 'list' && state.isEmpty(line)
94
+ state.line = line
95
+ end
96
+ end
97
+ end
98
+
99
+ # ParserBlock.parse(src, md, env, outTokens)
100
+ #
101
+ # Process input string and push block tokens into `outTokens`
102
+ #------------------------------------------------------------------------------
103
+ def parse(src, md, env, outTokens)
104
+
105
+ reutrn [] if !src
106
+
107
+ state = RulesBlock::StateBlock.new(src, md, env, outTokens)
108
+
109
+ tokenize(state, state.line, state.lineMax)
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,46 @@
1
+ # internal
2
+ # class Core
3
+ #
4
+ # Top-level rules executor. Glues block/inline parsers and does intermediate
5
+ # transformations.
6
+ #------------------------------------------------------------------------------
7
+ module MarkdownIt
8
+ class ParserCore
9
+
10
+ attr_accessor :ruler
11
+
12
+ RULES = [
13
+ [ 'normalize', lambda { |state| RulesCore::Normalize.inline(state) } ],
14
+ [ 'block', lambda { |state| RulesCore::Block.block(state) } ],
15
+ [ 'inline', lambda { |state| RulesCore::Inline.inline(state) } ],
16
+ [ 'linkify', lambda { |state| RulesCore::Linkify.linkify(state) } ],
17
+ [ 'replacements', lambda { |state| RulesCore::Replacements.replace(state) } ],
18
+ [ 'smartquotes', lambda { |state| RulesCore::Smartquotes.smartquotes(state) } ],
19
+ ]
20
+
21
+
22
+ # new Core()
23
+ #------------------------------------------------------------------------------
24
+ def initialize
25
+ # Core#ruler -> Ruler
26
+ #
27
+ # [[Ruler]] instance. Keep configuration of core rules.
28
+ @ruler = Ruler.new
29
+
30
+ RULES.each do |rule|
31
+ @ruler.push(rule[0], rule[1])
32
+ end
33
+ end
34
+
35
+ # Core.process(state)
36
+ #
37
+ # Executes core chain rules.
38
+ #------------------------------------------------------------------------------
39
+ def process(state)
40
+ rules = @ruler.getRules('')
41
+ rules.each do |rule|
42
+ rule.call(state)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,121 @@
1
+ # internal
2
+ # class ParserInline
3
+ #
4
+ # Tokenizes paragraph content.
5
+ #------------------------------------------------------------------------------
6
+ module MarkdownIt
7
+ class ParserInline
8
+
9
+ attr_accessor :ruler
10
+
11
+ #------------------------------------------------------------------------------
12
+ # Parser rules
13
+
14
+ RULES = [
15
+ [ 'text', lambda { |state, startLine| RulesInline::Text.text(state, startLine) } ],
16
+ [ 'newline', lambda { |state, startLine| RulesInline::Newline.newline(state, startLine) } ],
17
+ [ 'escape', lambda { |state, startLine| RulesInline::Escape.escape(state, startLine) } ],
18
+ [ 'backticks', lambda { |state, startLine| RulesInline::Backticks.backtick(state, startLine) } ],
19
+ [ 'strikethrough', lambda { |state, startLine| RulesInline::Strikethrough.strikethrough(state, startLine) } ],
20
+ [ 'emphasis', lambda { |state, startLine| RulesInline::Emphasis.emphasis(state, startLine) } ],
21
+ [ 'link', lambda { |state, startLine| RulesInline::Link.link(state, startLine) } ],
22
+ [ 'image', lambda { |state, startLine| RulesInline::Image.image(state, startLine) } ],
23
+ [ 'autolink', lambda { |state, startLine| RulesInline::Autolink.autolink(state, startLine) } ],
24
+ [ 'html_inline', lambda { |state, startLine| RulesInline::HtmlInline.html_inline(state, startLine) } ],
25
+ [ 'entity', lambda { |state, startLine| RulesInline::Entity.entity(state, startLine) } ],
26
+ ]
27
+
28
+
29
+ #------------------------------------------------------------------------------
30
+ def initialize
31
+ # ParserInline#ruler -> Ruler
32
+ #
33
+ # [[Ruler]] instance. Keep configuration of inline rules.
34
+ @ruler = Ruler.new
35
+
36
+ RULES.each do |rule|
37
+ @ruler.push(rule[0], rule[1])
38
+ end
39
+ end
40
+
41
+ # Skip single token by running all rules in validation mode;
42
+ # returns `true` if any rule reported success
43
+ #------------------------------------------------------------------------------
44
+ def skipToken(state)
45
+ pos = state.pos
46
+ rules = @ruler.getRules('')
47
+ len = rules.length
48
+ maxNesting = state.md.options[:maxNesting]
49
+ cache = state.cache
50
+
51
+
52
+ if cache[pos] != nil
53
+ state.pos = cache[pos]
54
+ return
55
+ end
56
+
57
+ # istanbul ignore else
58
+ if state.level < maxNesting
59
+ 0.upto(len -1) do |i|
60
+ if rules[i].call(state, true)
61
+ cache[pos] = state.pos
62
+ return
63
+ end
64
+ end
65
+ end
66
+
67
+ state.pos += 1
68
+ cache[pos] = state.pos
69
+ end
70
+
71
+
72
+ # Generate tokens for input range
73
+ #------------------------------------------------------------------------------
74
+ def tokenize(state)
75
+ rules = @ruler.getRules('')
76
+ len = rules.length
77
+ end_pos = state.posMax
78
+ maxNesting = state.md.options[:maxNesting]
79
+
80
+ while state.pos < end_pos
81
+ # Try all possible rules.
82
+ # On success, rule should:
83
+ #
84
+ # - update `state.pos`
85
+ # - update `state.tokens`
86
+ # - return true
87
+
88
+ ok = false
89
+ if state.level < maxNesting
90
+ 0.upto(len - 1) do |i|
91
+ ok = rules[i].call(state, false)
92
+ break if ok
93
+ end
94
+ end
95
+
96
+ if ok
97
+ break if state.pos >= end_pos
98
+ next
99
+ end
100
+
101
+ state.pending += state.src[state.pos]
102
+ state.pos += 1
103
+ end
104
+
105
+ unless state.pending.empty?
106
+ state.pushPending
107
+ end
108
+ end
109
+
110
+ # ParserInline.parse(str, md, env, outTokens)
111
+ #
112
+ # Process input string and push inline tokens into `outTokens`
113
+ #------------------------------------------------------------------------------
114
+ def parse(str, md, env, outTokens)
115
+ state = RulesInline::StateInline.new(str, md, env, outTokens)
116
+
117
+ tokenize(state)
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,76 @@
1
+ # Commonmark default options
2
+
3
+ module MarkdownIt
4
+ module Presets
5
+ class Commonmark
6
+ def self.options
7
+ {
8
+ options: {
9
+ html: true, # Enable HTML tags in source
10
+ xhtmlOut: true, # Use '/' to close single tags (<br />)
11
+ breaks: false, # Convert '\n' in paragraphs into <br>
12
+ langPrefix: 'language-', # CSS language prefix for fenced blocks
13
+ linkify: false, # autoconvert URL-like texts to links
14
+
15
+ # Enable some language-neutral replacements + quotes beautification
16
+ typographer: false,
17
+
18
+ # Double + single quotes replacement pairs, when typographer enabled,
19
+ # and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
20
+ quotes: "\u201c\u201d\u2018\u2019", # “”‘’
21
+
22
+ # Highlighter function. Should return escaped HTML,
23
+ # or '' if input not changed
24
+ #
25
+ # function (/*str, lang*/) { return ''; }
26
+ #
27
+ highlight: nil,
28
+
29
+ maxNesting: 20 # Internal protection, recursion limit
30
+ },
31
+
32
+ components: {
33
+
34
+ core: {
35
+ rules: [
36
+ 'normalize',
37
+ 'block',
38
+ 'inline'
39
+ ]
40
+ },
41
+
42
+ block: {
43
+ rules: [
44
+ 'blockquote',
45
+ 'code',
46
+ 'fence',
47
+ 'heading',
48
+ 'hr',
49
+ 'html_block',
50
+ 'lheading',
51
+ 'list',
52
+ 'reference',
53
+ 'paragraph'
54
+ ]
55
+ },
56
+
57
+ inline: {
58
+ rules: [
59
+ 'autolink',
60
+ 'backticks',
61
+ 'emphasis',
62
+ 'entity',
63
+ 'escape',
64
+ 'html_inline',
65
+ 'image',
66
+ 'link',
67
+ 'newline',
68
+ 'text'
69
+ ]
70
+ }
71
+ }
72
+ }
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,42 @@
1
+ # markdown-it default options
2
+
3
+ module MarkdownIt
4
+ module Presets
5
+ class Default
6
+ def self.options
7
+ {
8
+ options: {
9
+ html: false, # Enable HTML tags in source
10
+ xhtmlOut: false, # Use '/' to close single tags (<br />)
11
+ breaks: false, # Convert '\n' in paragraphs into <br>
12
+ langPrefix: 'language-', # CSS language prefix for fenced blocks
13
+ linkify: false, # autoconvert URL-like texts to links
14
+
15
+ # Enable some language-neutral replacements + quotes beautification
16
+ typographer: false,
17
+
18
+ # Double + single quotes replacement pairs, when typographer enabled,
19
+ # and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
20
+ quotes: "\u201c\u201d\u2018\u2019", # “”‘’
21
+
22
+ # Highlighter function. Should return escaped HTML,
23
+ # or '' if input not changed
24
+ #
25
+ # function (/*str, lang*/) { return ''; }
26
+ #
27
+ highlight: nil,
28
+
29
+ maxNesting: 20 # Internal protection, recursion limit
30
+ },
31
+
32
+ components: {
33
+
34
+ core: {},
35
+ block: {},
36
+ inline: {}
37
+ }
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,59 @@
1
+ # "Zero" preset, with nothing enabled. Useful for manual configuring of simple
2
+ # modes. For example, to parse bold/italic only.
3
+
4
+ module MarkdownIt
5
+ module Presets
6
+ class Zero
7
+ def self.options
8
+ {
9
+ options: {
10
+ html: false, # Enable HTML tags in source
11
+ xhtmlOut: false, # Use '/' to close single tags (<br />)
12
+ breaks: false, # Convert '\n' in paragraphs into <br>
13
+ langPrefix: 'language-', # CSS language prefix for fenced blocks
14
+ linkify: false, # autoconvert URL-like texts to links
15
+
16
+ # Enable some language-neutral replacements + quotes beautification
17
+ typographer: false,
18
+
19
+ # Double + single quotes replacement pairs, when typographer enabled,
20
+ # and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
21
+ quotes: "\u201c\u201d\u2018\u2019", # “”‘’
22
+
23
+ # Highlighter function. Should return escaped HTML,
24
+ # or '' if input not changed
25
+ #
26
+ # function (/*str, lang*/) { return ''; }
27
+ #
28
+ highlight: nil,
29
+
30
+ maxNesting: 20 # Internal protection, recursion limit
31
+ },
32
+
33
+ components: {
34
+
35
+ core: {
36
+ rules: [
37
+ 'normalize',
38
+ 'block',
39
+ 'inline'
40
+ ]
41
+ },
42
+
43
+ block: {
44
+ rules: [
45
+ 'paragraph'
46
+ ]
47
+ },
48
+
49
+ inline: {
50
+ rules: [
51
+ 'text'
52
+ ]
53
+ }
54
+ }
55
+ }
56
+ end
57
+ end
58
+ end
59
+ end