rouge-carve 0.1.4 → 0.1.5
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/CHANGELOG.md +9 -0
- data/README.md +13 -71
- data/lib/rouge/demos/carve +4 -4
- data/lib/rouge/lexers/carve.rb +78 -73
- data/lib/rouge-carve/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 56fbae7b1785bf82049bdeb87ee240391843fd025ae86d383ad7b48b3b3e9562
|
|
4
|
+
data.tar.gz: bc9a2e6b121c743dec62e18c059105fd2b3959a0d4fc09684849475c071a7e76
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be5892326629840d6697bb02c14875b1b075b5220d393e88fd5f85af894af8ada36911dd81c90eb3bb8b4d2cb2c7bc182731704a18c6c2d0ef7f4ef459e360a5
|
|
7
|
+
data.tar.gz: c14089a1b08264317473a18c84fdad82a946499096f5ef0143952b073a74a4d37da745a53d469a635bae2a752c15a94076c16a2abb4429f85c15504581cce2f5
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.5] - 2026-11-12
|
|
6
|
+
|
|
7
|
+
- Braced cell alignment (`|={>} Price |`, `|={<^ .x} Name |`, `|{~} 1 |`) lexes as an attribute with its alignment run as an operator, like the deprecated `|=>` prefix; cell pipes and escaped pipes stay outside it (#37).
|
|
8
|
+
- `->`, `<-`, `<->` and `=>` are text, and `-->` and `<--` need their exact hyphen run (#38).
|
|
9
|
+
- A mention or tag name needs an ASCII letter (#38).
|
|
10
|
+
- A first-line `---` opens frontmatter through the end of the document when no closer follows; a mid-document `---` never does (#38).
|
|
11
|
+
- A letter or roman marker with a dot needs two spaces, and a definition term is one line (#38).
|
|
12
|
+
- A code fence opener and a `%%%` comment span open without a closer lookahead, and a multiline attribute block continues only on lines indented past its `{` (#38).
|
|
13
|
+
|
|
5
14
|
## [0.1.4] - 2026-10-23
|
|
6
15
|
|
|
7
16
|
- `csv` and `tsv` fence bodies are highlighted: every field has its own token type and the separator is an operator, colored apart from the fields in the default styles (#25, #26, #27, #28).
|
data/README.md
CHANGED
|
@@ -1,84 +1,26 @@
|
|
|
1
1
|
# rouge-carve
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[Carve](https://markup-carve.github.io/carve/) markup language.
|
|
3
|
+
Rouge lexer for Carve 0.1 syntax. It registers `.crv`, `.carve`, and Carve fenced code for Rouge 3.30 or later. Read the [Carve documentation](https://markup-carve.github.io/carve/) for the language syntax.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
7
8
|
gem install rouge-carve
|
|
8
9
|
```
|
|
9
10
|
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
10
13
|
```ruby
|
|
11
14
|
require 'rouge-carve'
|
|
12
|
-
|
|
13
|
-
Rouge::Lexer.find('carve') # => Rouge::Lexers::Carve
|
|
14
|
-
Rouge::Lexer.guess(filename: 'notes.crv') # => Rouge::Lexers::Carve
|
|
15
|
+
Rouge::Lexer.find('carve')
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Requiring the gem registers the lexer. Anything that already highlights with
|
|
20
|
-
Rouge - GitLab, Jekyll, Redcarpet, most Ruby static site generators - then
|
|
21
|
-
handles `.crv` and `.carve` files, and ` ```carve ` fenced blocks, without
|
|
22
|
-
further configuration.
|
|
23
|
-
|
|
24
|
-
## Why not just use the Markdown lexer
|
|
25
|
-
|
|
26
|
-
Because it is not close enough to be wrong quietly. Carve deliberately changed
|
|
27
|
-
the delimiters Markdown got backwards, and three of them **invert**:
|
|
28
|
-
|
|
29
|
-
| Carve | means | Markdown reads it as |
|
|
30
|
-
| --- | --- | --- |
|
|
31
|
-
| `*bold*` | strong | emphasis |
|
|
32
|
-
| `/italic/` | emphasis | literal slashes |
|
|
33
|
-
| `_under_` | underline | emphasis |
|
|
34
|
-
| `~strike~` | strikethrough | subscript, or literal |
|
|
35
|
-
| `{=mark=}` | highlight | literal braces |
|
|
36
|
-
| `{^sup^}` | superscript | literal braces |
|
|
37
|
-
|
|
38
|
-
Highlighting a Carve document as Markdown does not degrade to plain text. It
|
|
39
|
-
shows bold where the author wrote emphasis.
|
|
40
|
-
|
|
41
|
-
## What it covers
|
|
42
|
-
|
|
43
|
-
Every construct in the language: headings, containers (`::: note`), fenced and
|
|
44
|
-
raw blocks, tables with alignment and per-row attributes, definition lists,
|
|
45
|
-
footnotes, citations, cross-references, attribute blocks, task items, critic
|
|
46
|
-
markup, symbol shortcodes, mentions, tags and the typographic runs.
|
|
47
|
-
|
|
48
|
-
**Fenced code is delegated.** A ` ```ruby ` block inside a `.crv` file is lexed
|
|
49
|
-
as Ruby, because that is what a reader expects. A ` ```=html ` raw block is not:
|
|
50
|
-
its info string names an output format, not a language, so the payload stays
|
|
51
|
-
opaque.
|
|
52
|
-
CSV and TSV fences highlight separators, quoted fields, escaped quotes, and unquoted fields (the header record apart from the data rows).
|
|
53
|
-
|
|
54
|
-
**Fence widths are respected.** A three-backtick line inside a four-backtick
|
|
55
|
-
fence is content, not a closer. The width is closed over per block rather than
|
|
56
|
-
approximated, which the sibling grammars in other ecosystems cannot do.
|
|
57
|
-
|
|
58
|
-
## What it cannot say
|
|
59
|
-
|
|
60
|
-
Rouge has no underline token - the vocabulary stops at `Generic::Emph`,
|
|
61
|
-
`Generic::Strong` and `Generic::EmphStrong`. Carve's `_x_` is underline, so its
|
|
62
|
-
content shares `Generic::Emph` with italic. The delimiters stay `Punctuation`,
|
|
63
|
-
so a consumer can still tell the two apart by the delimiter each carries.
|
|
64
|
-
|
|
65
|
-
Block openers are matched at any indent. Carve opens a block at column 0 or at
|
|
66
|
-
an enclosing container's content column and nowhere in between, which needs a
|
|
67
|
-
container model this lexer does not carry. The trade-off is deliberate and
|
|
68
|
-
shared with the Prism, highlight.js and Pygments grammars, so the four agree:
|
|
69
|
-
it over-colours an indented-at-document-level opener rather than
|
|
70
|
-
under-colouring the far more common indented construct inside a list item.
|
|
71
|
-
|
|
72
|
-
## Related
|
|
18
|
+
## Documentation
|
|
73
19
|
|
|
74
|
-
- [
|
|
75
|
-
- [
|
|
76
|
-
|
|
77
|
-
- [carve-grammars](https://github.com/markup-carve/carve-grammars) - TextMate,
|
|
78
|
-
Prism and highlight.js
|
|
79
|
-
- [carve-css](https://github.com/markup-carve/carve-css) - styles for the HTML
|
|
80
|
-
Carve renders
|
|
20
|
+
- [Carve documentation](https://markup-carve.github.io/carve/)
|
|
21
|
+
- [Documentation index](docs/README.md)
|
|
22
|
+
- [Development](docs/development.md)
|
|
81
23
|
|
|
82
|
-
##
|
|
24
|
+
## License
|
|
83
25
|
|
|
84
|
-
|
|
26
|
+
[MIT](LICENSE)
|
data/lib/rouge/demos/carve
CHANGED
|
@@ -21,13 +21,13 @@ A word with no registered handler renders as a generic div, which is what
|
|
|
21
21
|
makes a whole family of constructs possible without touching the parser.
|
|
22
22
|
:::
|
|
23
23
|
|
|
24
|
-
```
|
|
24
|
+
```ruby "example.rb"
|
|
25
25
|
def greet(name) = "Hello, #{name}!"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|= Engine |= Status |
|
|
29
|
-
| carve-js | shipped
|
|
30
|
-
| carve-rs | shipped
|
|
28
|
+
|= Engine |={~} Status |
|
|
29
|
+
| carve-js | shipped |
|
|
30
|
+
| carve-rs | shipped |
|
|
31
31
|
|
|
32
32
|
^ Table 1: the reference implementations.
|
|
33
33
|
|
data/lib/rouge/lexers/carve.rb
CHANGED
|
@@ -158,6 +158,10 @@ module Rouge
|
|
|
158
158
|
|#{LINE_BREAK}
|
|
159
159
|
)*\}
|
|
160
160
|
/x.freeze
|
|
161
|
+
# The same block as an interrupting line, whose continuations must be
|
|
162
|
+
# indented (carve#5080). Exact at column 0; an indented block is checked
|
|
163
|
+
# against its own `{` column in the :block rule.
|
|
164
|
+
ATTRS_INTERRUPT = Regexp.new(ATTRS_LINE.source.gsub(LINE_BREAK, '\n(?=[ \t]+[^ \t\n])'), Regexp::EXTENDED)
|
|
161
165
|
|
|
162
166
|
# The prefix of a line inside a blockquote, nested markers included.
|
|
163
167
|
# Each `>` needs a space or the line end after it: `>foo` and `>> x`
|
|
@@ -177,8 +181,9 @@ module Rouge
|
|
|
177
181
|
end
|
|
178
182
|
|
|
179
183
|
# An ordered marker: a number, one letter, or a roman numeral. `Body.`
|
|
180
|
-
# is a word, not a marker
|
|
181
|
-
|
|
184
|
+
# is a word, not a marker, and a letter with `.` needs two spaces, so
|
|
185
|
+
# `J. R. R. Tolkien` is prose (carve#4811).
|
|
186
|
+
ORDERED = "(?:\\d+[.)]|(?:[A-Za-z]|[ivxlcdm]+|[IVXLCDM]+)(?:\\)|\\.(?=(?:#{ATTRS})? )))"
|
|
182
187
|
|
|
183
188
|
# The states read a column-0 `+` with a flush-left block below as an
|
|
184
189
|
# attachment. Whether a `+` is the marker is settled by CarveContinuation.
|
|
@@ -188,34 +193,38 @@ module Rouge
|
|
|
188
193
|
LIST_MARKER = "(?:[-*]|#{ORDERED}|\\.)(?:#{ATTRS})?(?:[ \\t]|$)"
|
|
189
194
|
OPENER_RUN = "(?:(?:[-*]|#{ORDERED}|\\.)(?:#{ATTRS})? +[ \\t]*|> )+"
|
|
190
195
|
|
|
196
|
+
# A cell's alignment symbols: horizontal, then an optional vertical one.
|
|
197
|
+
CELL_ALIGN = '(?:[<>~][\\^~v]?|\\?[\\^~v])'
|
|
198
|
+
# A cell's attribute block when it opens with alignment (carve#5091 D3),
|
|
199
|
+
# glued to its `|` or `|=` and followed by the cell's space.
|
|
200
|
+
CELL_BRACE = %(({)(#{CELL_ALIGN})((?:[ ]+(?:"(?:[^"\\\\\n]|\\\\.)*"|'(?:[^'\\\\\n]|\\\\.)*'|[^{}"'|\n])*)?)(})(?= ))
|
|
201
|
+
|
|
191
202
|
# A table row needs its closing pipe: `| not a table` is a paragraph.
|
|
192
203
|
ROW_END = /(?=(?:\\.|[^\\\n])*\|[ \t]*(?:#{ATTRS})?[ \t]*$)/.freeze
|
|
193
204
|
|
|
194
205
|
# The block openers that interrupt a paragraph. A list marker and a
|
|
195
|
-
# caption do not
|
|
196
|
-
#
|
|
206
|
+
# caption do not. A fence opener does without looking for its closer
|
|
207
|
+
# (carve#4018); a backtick in a backtick info string makes it a code span.
|
|
197
208
|
INTERRUPT = %r/
|
|
198
209
|
\#{1,6}[ \t] | >(?:[ \t]|$) | ::: | ::[ \t] | %%
|
|
210
|
+
| `{3,}[^`\n]*$ | ~{3,}
|
|
199
211
|
| (?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$
|
|
200
212
|
| \|=?[<>^v~]*#{ROW_END}
|
|
201
213
|
| (?:\[\^|\*\[|\[)[^\]\n]+\]:[ ]
|
|
202
|
-
| #{
|
|
214
|
+
| #{ATTRS_INTERRUPT}[ \t]*$
|
|
203
215
|
/x.freeze
|
|
204
216
|
|
|
205
217
|
# Where a bracketed inline body must close, by the block it sits in: a
|
|
206
218
|
# paragraph ends at a blank line or an interrupting block, a list item
|
|
207
219
|
# also at the next marker, and a heading or table row at its line end.
|
|
208
|
-
# A fence ends either only when it is closed, which is checked in code.
|
|
209
220
|
BODY_ENDS = {
|
|
210
221
|
para: /\n(?=[ \t]*(?:\n|\z)|#{MARGIN}(?:#{INTERRUPT}))/,
|
|
211
222
|
item: /\n(?=[ \t]*(?:\n|\z)|#{MARGIN}(?:#{INTERRUPT}|#{LIST_MARKER}|:[ \t]))/,
|
|
212
223
|
line: /\n/
|
|
213
224
|
}.freeze
|
|
214
|
-
FENCE_NEXT = /\n(?=#{MARGIN}(`{3,}|~{3,}))/.freeze
|
|
215
|
-
|
|
216
225
|
# The block states that decide which of those ends applies.
|
|
217
226
|
BODY_SCOPE = {
|
|
218
|
-
paragraph: :para, listitem: :item, dlterm: :
|
|
227
|
+
paragraph: :para, listitem: :item, dlterm: :line, heading: :line,
|
|
219
228
|
caption: :line, quoteline: :line, tablerow: :line, defline: :line
|
|
220
229
|
}.freeze
|
|
221
230
|
|
|
@@ -259,8 +268,15 @@ module Rouge
|
|
|
259
268
|
PLAIN_NO_PIPE = plain_run('|').freeze
|
|
260
269
|
PLAIN_NO_BRACKET = plain_run('\\]').freeze
|
|
261
270
|
|
|
271
|
+
# The document start. Front matter opens only here: Rouge 3 and 4 scan
|
|
272
|
+
# without a fixed anchor, so \A alone would also match mid-document.
|
|
262
273
|
state :root do
|
|
263
|
-
|
|
274
|
+
rule %r/\A(?)(---)(?:( ?)([A-Za-z0-9]+))?([ \t]*(?:\n|\z))/ do
|
|
275
|
+
groups Text, Punctuation, Text, Keyword::Type, Text
|
|
276
|
+
goto :block
|
|
277
|
+
push :frontmatter
|
|
278
|
+
end
|
|
279
|
+
rule(//) { goto :block }
|
|
264
280
|
end
|
|
265
281
|
|
|
266
282
|
# ------------------------------------------------------------------
|
|
@@ -472,6 +488,11 @@ module Rouge
|
|
|
472
488
|
# Tables. The header marker, the alignment run and the separator row
|
|
473
489
|
# are their own tokens; cell content is lexed inline. A row needs its
|
|
474
490
|
# closing pipe.
|
|
491
|
+
rule %r/#{bol}(#{MARGIN})(\|=?)#{CELL_BRACE}#{ROW_END}/ do |m|
|
|
492
|
+
token Text, m[1]
|
|
493
|
+
braced_cell(m)
|
|
494
|
+
open_block :tablerow
|
|
495
|
+
end
|
|
475
496
|
rule %r/#{bol}(#{MARGIN})(\|=[<>^v~]*)#{ROW_END}/ do
|
|
476
497
|
groups Text, Operator
|
|
477
498
|
open_block :tablerow
|
|
@@ -487,32 +508,19 @@ module Rouge
|
|
|
487
508
|
state(:quoteopeners, &block_openers(''))
|
|
488
509
|
|
|
489
510
|
state :block do
|
|
490
|
-
# Front matter, only at the very start of the document. \A is what
|
|
491
|
-
# keeps a `---yaml` line mid-document from opening one.
|
|
492
|
-
rule %r/\A(?)(---)([a-zA-Z][\w-]*)?([ \t]*\n)(?=[\s\S]*?^---[ \t]*$)/ do
|
|
493
|
-
groups Text, Punctuation, Keyword::Type, Text
|
|
494
|
-
push :frontmatter
|
|
495
|
-
end
|
|
496
|
-
|
|
497
511
|
# A comment fence (%%% or longer) versus a one-line comment. The fence
|
|
498
512
|
# has to be tried first: %%% also matches the one-line form. Only a
|
|
499
513
|
# run of the SAME length closes it, so the width is closed over the
|
|
500
|
-
# way #push_fence does it
|
|
501
|
-
#
|
|
514
|
+
# way #push_fence does it. No closer is looked for: an unclosed span
|
|
515
|
+
# ends at a line left of its opener, which misses the opener's owner,
|
|
516
|
+
# or at the end of the document. Text after either run is comment.
|
|
502
517
|
rule %r/^(#{MARGIN})(%%%+)([^\n]*)(\n)/ do |m|
|
|
503
518
|
closer = %r/^([ \t]*)(%{#{m[2].length}})(?!%)([^\n]*)$/
|
|
504
|
-
|
|
505
|
-
# The tokens of the one-line rule below. Rouge 3 has no
|
|
506
|
-
# fallthrough! to hand the line on to it.
|
|
507
|
-
token Text, m[1]
|
|
508
|
-
token Comment::Preproc, '%%'
|
|
509
|
-
token Comment, m[2][2..] + m[3]
|
|
510
|
-
token Text, m[4]
|
|
511
|
-
next
|
|
512
|
-
end
|
|
519
|
+
outside = m[1].empty? ? nil : %r/^(?=[ \t]{0,#{m[1].length - 1}}[^ \t\n])/
|
|
513
520
|
|
|
514
521
|
groups Text, Comment::Preproc, Comment, Text
|
|
515
522
|
push do
|
|
523
|
+
rule(outside) { pop! } if outside
|
|
516
524
|
rule closer do
|
|
517
525
|
groups Text, Comment::Preproc, Comment
|
|
518
526
|
pop!
|
|
@@ -536,17 +544,20 @@ module Rouge
|
|
|
536
544
|
|
|
537
545
|
mixin :blockopeners
|
|
538
546
|
|
|
539
|
-
# A standalone attribute block, which may span lines
|
|
540
|
-
|
|
541
|
-
|
|
547
|
+
# A standalone attribute block, which may span lines indented past its
|
|
548
|
+
# `{` (carve#5080). One that does not is a paragraph.
|
|
549
|
+
rule %r/^(#{MARGIN})(#{ATTRS_LINE})/ do |m|
|
|
550
|
+
width = m[1].length
|
|
551
|
+
if m[2].split("\n").drop(1).all? { |line| line[/\A[ \t]*/].length > width }
|
|
552
|
+
groups Text, Name::Attribute
|
|
553
|
+
else
|
|
554
|
+
@current_stream.unscan
|
|
555
|
+
start_paragraph
|
|
556
|
+
end
|
|
542
557
|
end
|
|
543
558
|
|
|
544
559
|
# Any other line with content starts a paragraph.
|
|
545
|
-
rule
|
|
546
|
-
@lone_image = !@current_stream.check(IMAGE_LINE).nil?
|
|
547
|
-
@indented = @current_stream.check(/[ \t]/) ? true : false
|
|
548
|
-
push :paragraph
|
|
549
|
-
end
|
|
560
|
+
rule(%r/^(?=#{MARGIN}\S)/) { start_paragraph }
|
|
550
561
|
|
|
551
562
|
mixin :inline
|
|
552
563
|
end
|
|
@@ -567,7 +578,6 @@ module Rouge
|
|
|
567
578
|
continuation_host_before? ? pop! : continue_paragraph(:paragraph)
|
|
568
579
|
end
|
|
569
580
|
rule(%r/^(?=#{MARGIN}(?:#{INTERRUPT}))/) { pop! }
|
|
570
|
-
rule(%r/^(?=#{MARGIN}(`{3,}|~{3,}))/) { |m| fence_closed_below?(m[1]) ? pop! : continue_paragraph(:paragraph) }
|
|
571
581
|
rule(%r/^(?=#{MARGIN}\^[ \t])/) { @lone_image ? pop! : continue_paragraph(:paragraph) }
|
|
572
582
|
# An indented paragraph sits in a container, so a list marker below it
|
|
573
583
|
# opens a sublist or the next item rather than continuing it.
|
|
@@ -580,11 +590,16 @@ module Rouge
|
|
|
580
590
|
{ listitem: Text, dlterm: Generic::Heading }.each do |name, tok|
|
|
581
591
|
line = :"#{name}line"
|
|
582
592
|
state name do
|
|
583
|
-
|
|
593
|
+
if name == :dlterm
|
|
594
|
+
rule(/\n/) { token Text; pop! }
|
|
595
|
+
else
|
|
596
|
+
rule(/\n/) { token Text; goto line }
|
|
597
|
+
end
|
|
584
598
|
mixin :inlinecontent
|
|
585
599
|
rule PLAIN, tok
|
|
586
600
|
rule(/./) { token plain_token }
|
|
587
601
|
end
|
|
602
|
+
next if name == :dlterm
|
|
588
603
|
|
|
589
604
|
state line do
|
|
590
605
|
rule(%r/^(?=[ \t]*(?:\n|\z))/) { pop! }
|
|
@@ -595,7 +610,6 @@ module Rouge
|
|
|
595
610
|
end
|
|
596
611
|
end
|
|
597
612
|
rule(%r/^(?=#{MARGIN}(?:#{INTERRUPT}|#{LIST_MARKER}|:[ \t]))/) { pop! }
|
|
598
|
-
rule(%r/^(?=#{MARGIN}(`{3,}|~{3,}))/) { |m| fence_closed_below?(m[1]) ? pop! : goto(name) }
|
|
599
613
|
rule(//) { goto name }
|
|
600
614
|
end
|
|
601
615
|
end
|
|
@@ -650,6 +664,9 @@ module Rouge
|
|
|
650
664
|
rule %r/$/, Text, :pop!
|
|
651
665
|
# A header cell marker, optionally carrying an alignment run. The pipe
|
|
652
666
|
# is part of it, so `|=` reads as one construct.
|
|
667
|
+
# An escaped pipe is consumed by the escape rule first, so a `|` here
|
|
668
|
+
# always ends a cell.
|
|
669
|
+
rule(%r/(\|=?)#{CELL_BRACE}/) { |m| braced_cell(m) }
|
|
653
670
|
rule %r/\|=[<>^v~]*/, Operator
|
|
654
671
|
# A separator row cell, in the native and the GFM spelling.
|
|
655
672
|
rule %r/(?<=\|)[ \t]*:?-{2,}:?[ \t]*(?=\|)/, Punctuation
|
|
@@ -877,12 +894,12 @@ module Rouge
|
|
|
877
894
|
|
|
878
895
|
# A mention and a tag, each one token: the sigil is part of the name
|
|
879
896
|
# rather than punctuation beside it.
|
|
880
|
-
rule %r/(?<![\w\/])@[\w][\w.-]*/, Name::Variable::Magic
|
|
881
|
-
rule %r/(?<![\w&])\#[\w][\w-]*/, Name::Variable::Instance
|
|
897
|
+
rule %r/(?<![\w\/])@(?=[\w.-]*?[A-Za-z])[\w][\w.-]*/, Name::Variable::Magic
|
|
898
|
+
rule %r/(?<![\w&])\#(?=[\w-]*?[A-Za-z])[\w][\w-]*/, Name::Variable::Instance
|
|
882
899
|
|
|
883
900
|
# Typographic runs, longest first: an arrow is not an en dash plus a
|
|
884
901
|
# stray angle bracket, and `---` is not `--` plus `-`.
|
|
885
|
-
rule %r
|
|
902
|
+
rule %r/<-->|<--(?!-)|(?<!-)-->|<=>|==>|<==/, Operator
|
|
886
903
|
rule %r/(?<!-)---(?!-)|(?<!-)--(?!-)/, Punctuation
|
|
887
904
|
rule %r/\.\.\./, Punctuation
|
|
888
905
|
end
|
|
@@ -1004,15 +1021,6 @@ module Rouge
|
|
|
1004
1021
|
state :"#{body}_#{scope}" do
|
|
1005
1022
|
rule %r/\]/, Punctuation, :pop!
|
|
1006
1023
|
rule(%r/(?=#{ends.source}|\n?\z)/) { pop! }
|
|
1007
|
-
# The newline is handed back so the block reads the fence line.
|
|
1008
|
-
rule(FENCE_NEXT) do |m|
|
|
1009
|
-
if fence_closed_below?(m[1])
|
|
1010
|
-
m.pos -= 1
|
|
1011
|
-
pop!
|
|
1012
|
-
else
|
|
1013
|
-
token Text
|
|
1014
|
-
end
|
|
1015
|
-
end
|
|
1016
1024
|
mixin :inlinecontent
|
|
1017
1025
|
rule PLAIN_NO_BRACKET, tok
|
|
1018
1026
|
rule %r/[^\]\n]/, tok
|
|
@@ -1247,20 +1255,10 @@ module Rouge
|
|
|
1247
1255
|
entry[1].bsearch { |at| at >= pos } ? scope : nil
|
|
1248
1256
|
end
|
|
1249
1257
|
|
|
1250
|
-
# Where a body opened at +pos+ must end: the first block end
|
|
1251
|
-
# first closed fence, after it.
|
|
1258
|
+
# Where a body opened at +pos+ must end: the first block end after it.
|
|
1252
1259
|
def body_end(text, pos, scope)
|
|
1253
1260
|
ends = BODY_ENDS[scope]
|
|
1254
|
-
|
|
1255
|
-
return last if scope == :line
|
|
1256
|
-
|
|
1257
|
-
at = pos
|
|
1258
|
-
while (fence = text.index(FENCE_NEXT, at)) && fence < last
|
|
1259
|
-
return fence if fence_closed_below?($~[1], fence + 1)
|
|
1260
|
-
|
|
1261
|
-
at = fence + 1
|
|
1262
|
-
end
|
|
1263
|
-
last
|
|
1261
|
+
text.index(ends, pos) || text.length
|
|
1264
1262
|
end
|
|
1265
1263
|
|
|
1266
1264
|
BRACKET_SCAN = /\\.|(?<!`)(`+)(?!`).*?(?<!`)\1(?!`)|\]/.freeze
|
|
@@ -1407,9 +1405,9 @@ module Rouge
|
|
|
1407
1405
|
|
|
1408
1406
|
lines.map! { |line| line.empty? ? line : line[prefix.length..] }
|
|
1409
1407
|
end
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
lines.
|
|
1408
|
+
# A term is one line (carve#4894): only a blank may stand between it
|
|
1409
|
+
# and its `: ` line.
|
|
1410
|
+
lines.size <= 1 && lines.all? { |line| line.match?(/\A[ \t]*\z/) }
|
|
1413
1411
|
end
|
|
1414
1412
|
|
|
1415
1413
|
# A `:` left of the `::` column of every open term above it ends the
|
|
@@ -1499,13 +1497,20 @@ module Rouge
|
|
|
1499
1497
|
goto name
|
|
1500
1498
|
end
|
|
1501
1499
|
|
|
1502
|
-
#
|
|
1503
|
-
#
|
|
1504
|
-
def
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1500
|
+
# The tokens of a cell marker and its braced alignment block, from a
|
|
1501
|
+
# match whose last five groups are the marker and CELL_BRACE.
|
|
1502
|
+
def braced_cell(m)
|
|
1503
|
+
pipe, open, align, rest, close = m.captures.last(5)
|
|
1504
|
+
token pipe == '|' ? Punctuation : Operator, pipe
|
|
1505
|
+
token Name::Attribute, open
|
|
1506
|
+
token Operator, align
|
|
1507
|
+
token Name::Attribute, rest + close
|
|
1508
|
+
end
|
|
1509
|
+
|
|
1510
|
+
def start_paragraph
|
|
1511
|
+
@lone_image = !@current_stream.check(IMAGE_LINE).nil?
|
|
1512
|
+
@indented = @current_stream.check(/[ \t]/) ? true : false
|
|
1513
|
+
push :paragraph
|
|
1509
1514
|
end
|
|
1510
1515
|
|
|
1511
1516
|
# Lex the tail of a fence or container opener line without leaving the
|
data/lib/rouge-carve/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rouge-carve
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mark Scherer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rouge
|