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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 300be9217acf879b361b092d5bd9f814858ba169272f98f730cdbfa86a2e75bf
4
- data.tar.gz: 1b4e02989bd311b9d0423e1021250d5ddac1982420c15016d80600ddb82386b0
3
+ metadata.gz: 56fbae7b1785bf82049bdeb87ee240391843fd025ae86d383ad7b48b3b3e9562
4
+ data.tar.gz: bc9a2e6b121c743dec62e18c059105fd2b3959a0d4fc09684849475c071a7e76
5
5
  SHA512:
6
- metadata.gz: 63d049afb99f11ac50d7b64a2829c8fec7bc220b1501b621cbbe2e6a87160e75cc326bc94f3724f3280650e12e9be2ce0a00bb160f1c9012e717fc2d538916b9
7
- data.tar.gz: d3dce00b0304ec63f85dc9e258f78e7c516d7a9048e1ac9e76e8745140c2931a8ee3e0de70abc7a7a804203b511707d901f7ecd44c152ad08bdaeaa3e22dd35d
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
- A [Rouge](https://github.com/rouge-ruby/rouge) lexer for the
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
- ```bash
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
- It needs Rouge 3.30 or later and is tested against Rouge 3, 4 and 5.
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
- - [carve](https://github.com/markup-carve/carve) - the language and its spec
75
- - [pygments-carve](https://github.com/markup-carve/pygments-carve) - the same
76
- grammar for Pygments, which this was ported from
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
- ## Development
24
+ ## License
83
25
 
84
- Contributor setup, testing, and maintenance notes are in the [development guide](docs/development.md).
26
+ [MIT](LICENSE)
@@ -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
- ``` ruby "example.rb"
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
 
@@ -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
- ORDERED = '(?:\\d+|[A-Za-z]|[ivxlcdm]+|[IVXLCDM]+)[.)]'
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, and a fence does only when it is closed - that one is
196
- # checked in code, see the :paraline state.
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
- | #{ATTRS_LINE}[ \t]*$
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: :item, heading: :line,
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
- mixin :block
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, and an opener with no such closer below it
501
- # is the one-line form. Text after either run is part of the comment.
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
- unless closer_below?(closer, m[2].length)
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
- rule %r/^(#{MARGIN})(#{ATTRS_LINE})/ do
541
- groups Text, Name::Attribute
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 %r/^(?=#{MARGIN}\S)/ do
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
- rule(/\n/) { token Text; goto line }
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/<-->|<==>|<=>|-->|<--|==>|<==|->|<-/, Operator
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, or the
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
- last = text.index(ends, pos) || text.length
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
- return false if lines.count { |line| line.match?(/\A[ \t]*\z/) } > 1
1411
-
1412
- lines.none? { |line| line.match?(/\A(?:\#{1,6} +|:{3,}|[-*] +|> |\||`{3,}|~{3,}|(?:[-*_][ \t]*){3,}\z)/) }
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
- # Whether a fence opened by +run+ on the current line is closed further
1503
- # down. Only a closed fence interrupts a paragraph.
1504
- def fence_closed_below?(run, line_start = @current_stream.charpos)
1505
- text = @current_stream.string
1506
- line_end = text.index("\n", line_start) || text.length
1507
- closer = %r/^[ \t]*#{Regexp.escape(run[0])}{#{run.length},}[ \t]*$/
1508
- closer_below?(closer, run, line_end)
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
@@ -3,5 +3,5 @@
3
3
  # Kept apart from the entry file so the gemspec can read it without loading
4
4
  # Rouge, which is not installed yet when Bundler evaluates the gemspec.
5
5
  module RougeCarve
6
- VERSION = '0.1.4'
6
+ VERSION = '0.1.5'
7
7
  end
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
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-10-23 00:00:00.000000000 Z
11
+ date: 2026-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rouge