carve-lang 0.1.1 → 0.1.2
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 +138 -0
- data/README.md +8 -4
- data/ext/carve/Cargo.lock +30 -3
- data/ext/carve/Cargo.toml +3 -2
- data/ext/carve/src/lib.rs +76 -3
- data/lib/carve/version.rb +1 -1
- data/lib/carve.rb +13 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9dc82ae49fa620a500b09b60ad705caca3488b99c18ec3dda8ff22f1aabc5b55
|
|
4
|
+
data.tar.gz: 192a18307bfb8cc9bd9364a333592b92bf0cd9075f2403fa602b09307705912b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a0eb63cc0fb830f1d6a69136d7a934931069718a700aa280017313e05a704614ef805bd9a136ce17620fd88188bb39cd4e335e059ecb002683a7a7bf4a646c1c
|
|
7
|
+
data.tar.gz: 33039444b491c79db93ef2041556d4ec40533ec98ed1dec8cc154c79b4b147ffde9a8533bf8df0839ac72c74da352d5087251c1eccb5521d769d0ff3a202a035
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,144 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.2] - 2026-08-27
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- The gem is published through RubyGems trusted publishing rather than a
|
|
15
|
+
long-lived API key, and the gemspec sets `rubygems_mfa_required`, so RubyGems
|
|
16
|
+
refuses a push from an account without MFA (#81).
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- The engine moves from carve-rs `0.1.3` (`a33c42ad`), which `0.1.1` shipped, to
|
|
21
|
+
`bd19414d` - 106 commits across four pin bumps (#80, #82, #84, #87). Rendering
|
|
22
|
+
changes an existing document can see: a column's alignment defaults come from
|
|
23
|
+
the header section, an explicit alignment run is validated and inherited, and
|
|
24
|
+
a table cell's marker run must end at a space; tables gained semantic row
|
|
25
|
+
partitions and a list table can carry local headers; a braced hyphen pair is
|
|
26
|
+
an en dash, an empty brace pair is text, and the doubled run is the canonical
|
|
27
|
+
arrow; a hyphen run opening a word after whitespace is a flag, not a dash; a
|
|
28
|
+
continuation marker attaches only a flush-left block; the footnote backlink
|
|
29
|
+
has an accessible name; a caption no longer disables a diagram fence's preset;
|
|
30
|
+
the first code group is numbered like every other one; a heading at a content
|
|
31
|
+
column leaves no paragraph open, and a definition at a list item's content
|
|
32
|
+
column closes its paragraph; an all-blank raw payload stays distinct from an
|
|
33
|
+
absent one; and depth limits guard every recursive parse, render and AST-JSON
|
|
34
|
+
path. `<thead>` and `<tfoot>` also write one row per line, which changes the
|
|
35
|
+
emitted HTML without changing what it renders. The last bump adds: three blank
|
|
36
|
+
lines are a hard list boundary rather than a wide gap between two items, so a
|
|
37
|
+
document that used the run as spacing now parses as two lists; a heading id
|
|
38
|
+
can opt in to ASCII folding; a tab control renders as a button and a code
|
|
39
|
+
group takes the mode option; and a `%%` line a verbatim run has already
|
|
40
|
+
swallowed no longer produces a comment node after that run, which changes the
|
|
41
|
+
tree without changing the HTML (#84).
|
|
42
|
+
The fourth bump is 18 further commits, and over the spec corpus exactly one
|
|
43
|
+
document's HTML moves with it: a list marker at an item's content column
|
|
44
|
+
opens a sublist whether or not it is the item's first, so a marker that
|
|
45
|
+
follows a blank line and a paragraph inside an item no longer joins that
|
|
46
|
+
paragraph (markup-carve/carve-rs#1251). A further 104 documents change only
|
|
47
|
+
their reported positions, because a container's span now starts at its
|
|
48
|
+
opening markup and ends at its last placed child, and a definition list's
|
|
49
|
+
likewise (markup-carve/carve-rs#1238, markup-carve/carve-rs#1248,
|
|
50
|
+
markup-carve/carve-rs#1252). Nothing else an existing document can see
|
|
51
|
+
changes (#87).
|
|
52
|
+
- The engine then moves from `bd19414d` to `f2fbb24c` - 39 further commits
|
|
53
|
+
(#91). A container with no closer ends at its last placed child rather than
|
|
54
|
+
one codepoint past it, which is the PART 12 §4 extent defect this gem was
|
|
55
|
+
still the one implementation reporting (markup-carve/carve-rs#1308, #89); a
|
|
56
|
+
footnote continuation survives a blank run (markup-carve/carve-rs#1295); and
|
|
57
|
+
a list takes PART 9 §17 L7's consumed `loose` attribute, which loosens the
|
|
58
|
+
list instead of being emitted on it and which `Carve.parse` publishes on a
|
|
59
|
+
definition list as a `loose` field (markup-carve/carve-rs#1304). Seven corpus
|
|
60
|
+
documents move with the bump and all seven are documents the corpus gained,
|
|
61
|
+
so nothing that already rendered correctly changed.
|
|
62
|
+
- The embedded engine moves to carve-rs `42a952cb`. An indented lone image now
|
|
63
|
+
parses as a paragraph holding an inline image rather than a block image
|
|
64
|
+
(markup-carve/carve#1660, markup-carve/carve-rs#1347). AST only - the
|
|
65
|
+
rendered HTML is unchanged on every corpus document (#93).
|
|
66
|
+
- The embedded engine moves from `42a952cb` to `468e71af` - 70 further commits
|
|
67
|
+
across three pin bumps (#96, #97, #98), and each of the three changes what an
|
|
68
|
+
existing document renders as. The first two settle one rule between them: a
|
|
69
|
+
list item's content column is measured from the bare marker, so neither the
|
|
70
|
+
task checkbox nor a marker-attached attribute block widens it
|
|
71
|
+
(markup-carve/carve-rs#1364, markup-carve/carve-rs#1374,
|
|
72
|
+
markup-carve/carve-rs#1379). `-{#k} [x] a` has content column 2, so a `# h`
|
|
73
|
+
written under it at column 2 opens a heading inside the item where the wider
|
|
74
|
+
column made it lazy paragraph text. Also in those two: a lone image at an
|
|
75
|
+
item's content column keeps the item's looseness, restoring the `<p>` wrapper
|
|
76
|
+
the item used to drop (markup-carve/carve-rs#1359); the ANSI quote bar
|
|
77
|
+
reports containment, so a quoted heading, code block, table, thematic break
|
|
78
|
+
and lone image keep the bar and a quoted list's bar sits outside its marker
|
|
79
|
+
(markup-carve/carve-rs#1363); and on the import side an imported heading
|
|
80
|
+
records its id, an imported task item comes back a task item, an input's type
|
|
81
|
+
matches the checkbox keyword case-insensitively, an HTML comment imports as a
|
|
82
|
+
Carve comment, and an imported code block no longer gains a trailing blank
|
|
83
|
+
line on every pass (markup-carve/carve-rs#1361, markup-carve/carve-rs#1366,
|
|
84
|
+
markup-carve/carve-rs#1378, markup-carve/carve-rs#1386,
|
|
85
|
+
markup-carve/carve-rs#1384).
|
|
86
|
+
The third bump is 44 commits on its own, and rendered HTML moves on 50 corpus
|
|
87
|
+
documents with it. Measured against the corpus's own expected output at the
|
|
88
|
+
spec the new pin pins, the old pin differed on all 50 and the new pin on
|
|
89
|
+
none, so those 50 were being rendered wrongly and this is a correctness fix
|
|
90
|
+
rather than a preference. What an author notices is that a recognized block
|
|
91
|
+
opener written past a container's content column now opens that block inside
|
|
92
|
+
the container instead of folding into text: an indented `> q` under a list
|
|
93
|
+
item wrote `<p>> q</p>` and now writes a block quote, an indented `# h`
|
|
94
|
+
wrote `<p># h</p>` and now writes a heading, an indented code fence folded
|
|
95
|
+
into inline code inside a paragraph and now writes a `<pre>` block, and a
|
|
96
|
+
tab-indented `> quote` wrote text on the item's own line and now writes a
|
|
97
|
+
block quote; where a blank line preceded the block, the item is no longer
|
|
98
|
+
reported loose either. The same authored base applies inside a footnote body
|
|
99
|
+
and a definition description, so a table or a link reference definition
|
|
100
|
+
written past the body's column registers there (markup-carve/carve-rs#1387,
|
|
101
|
+
markup-carve/carve-rs#1420, markup-carve/carve-rs#1422,
|
|
102
|
+
markup-carve/carve-rs#1425, markup-carve/carve-rs#1431,
|
|
103
|
+
markup-carve/carve-rs#1432, markup-carve/carve-rs#1433, measured over the
|
|
104
|
+
corpus that markup-carve/carve-rs#1417 pins). Four further changes an
|
|
105
|
+
existing document can see ride along: an explicit id or class may begin with
|
|
106
|
+
an ASCII digit, so `::: 123` opens a div with that class instead of staying a
|
|
107
|
+
paragraph (markup-carve/carve-rs#1393); `::: >` spells a block quote with no
|
|
108
|
+
marker column, and its closing fence takes a caption
|
|
109
|
+
(markup-carve/carve-rs#1399, markup-carve/carve-rs#1411); reference and
|
|
110
|
+
footnote labels differing only in ASCII whitespace resolve to one definition
|
|
111
|
+
(markup-carve/carve-rs#1397); and `{align=left|right|center}` on an element
|
|
112
|
+
whose `align` means text alignment renders a CSS declaration rather than the
|
|
113
|
+
deprecated presentational attribute (markup-carve/carve-rs#1412).
|
|
114
|
+
`Carve.to_carve` also writes one space after a definition separator
|
|
115
|
+
(markup-carve/carve-rs#1426) (#98).
|
|
116
|
+
- The final release pin moves from `0c54d2ea` to the released carve-rs 0.1.4
|
|
117
|
+
(`2e9c43f2`). This closes every declared spec-drift window: link and
|
|
118
|
+
abbreviation definitions below a definition body's column follow the same
|
|
119
|
+
folding rule, a comment in a footnote body leaves no blank line behind, the
|
|
120
|
+
continuation marker's column gate reaches every container, an empty
|
|
121
|
+
description body writes the `{empty}` sentinel, citation items are typed and
|
|
122
|
+
positioned, and paragraph block-image promotion is published on the AST.
|
|
123
|
+
- The stale pin is what made this gem the only implementation failing PART 12
|
|
124
|
+
conformance in markup-carve/carve#1451 - a binding has no vote of its own, and
|
|
125
|
+
this one was voting with an engine 28 commits behind (#82). It recurred within
|
|
126
|
+
two days, on three documents and a pin one day old, because nothing in this
|
|
127
|
+
repository compares the tree this gem produces against the engine's own (#84).
|
|
128
|
+
It recurred again the next day, on one document, with that comparison still
|
|
129
|
+
unmerged (#86) and the pin 18 commits behind (#87). It recurred twice more
|
|
130
|
+
inside this window: at 39 commits behind, still carrying the PART 12 §4
|
|
131
|
+
extent defect (#89, #91), and again on a ruling only the tree can see,
|
|
132
|
+
which a byte-for-byte HTML comparison cannot detect (#93).
|
|
133
|
+
|
|
134
|
+
### Added
|
|
135
|
+
|
|
136
|
+
- `Carve.from_html(source, mode: :safe)` and `Carve.from_markdown(source)`
|
|
137
|
+
import an existing document into canonical Carve (#92). Both return the
|
|
138
|
+
shared migration shape `{value:, report:}`: `value` is the Carve source, and
|
|
139
|
+
`report` carries `diagnostics`, each with `code`, `message`, `severity` and,
|
|
140
|
+
where the engine placed one, `path`. `from_html` takes `:safe`, `:semantic`
|
|
141
|
+
or `:roundtrip` and reports back the `mode` and `adapter` it ran with; any
|
|
142
|
+
other mode raises `ArgumentError`. `from_markdown` reports
|
|
143
|
+
`source_format: "markdown"` and diagnoses nothing.
|
|
144
|
+
- `Carve.to_markdown`, `to_plain_text`, `to_ansi` and `to_carve`, so every core
|
|
145
|
+
render target the embedded engine already understood is reachable from Ruby
|
|
146
|
+
(#88). `Carve.to_html` and the AST entry points are unchanged.
|
|
147
|
+
|
|
10
148
|
## [0.1.1] - 2026-08-18
|
|
11
149
|
|
|
12
150
|
Everything below is the delta from `v0.1.0`, which is the only version a
|
data/README.md
CHANGED
|
@@ -37,6 +37,14 @@ time via `rb_sys`.
|
|
|
37
37
|
require "carve"
|
|
38
38
|
|
|
39
39
|
Carve.to_html("# Hello *world*")
|
|
40
|
+
|
|
41
|
+
# Every core engine target is available from the binding.
|
|
42
|
+
Carve.to_markdown(source)
|
|
43
|
+
Carve.to_plain_text(source)
|
|
44
|
+
Carve.to_ansi(source)
|
|
45
|
+
Carve.to_carve(source)
|
|
46
|
+
Carve.from_html('<p>Hello <strong>world</strong></p>')
|
|
47
|
+
Carve.from_markdown('*em* and **strong**')
|
|
40
48
|
# => "<section id=\"Hello-world\">\n <h1>Hello <strong>world</strong></h1>\n</section>"
|
|
41
49
|
|
|
42
50
|
# Carve syntax note: *...* is STRONG (bold), /.../ is EMPHASIS (italic).
|
|
@@ -320,7 +328,3 @@ that has fallen behind fails a build. Locally:
|
|
|
320
328
|
```sh
|
|
321
329
|
CARVE_SPEC_CORPUS=/path/to/carve/tests/corpus bundle exec rake test
|
|
322
330
|
```
|
|
323
|
-
|
|
324
|
-
## License
|
|
325
|
-
|
|
326
|
-
MIT, markup-carve.
|
data/ext/carve/Cargo.lock
CHANGED
|
@@ -37,21 +37,23 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|
|
37
37
|
|
|
38
38
|
[[package]]
|
|
39
39
|
name = "carve-lang"
|
|
40
|
-
version = "0.1.
|
|
41
|
-
source = "git+https://github.com/markup-carve/carve-rs?rev=
|
|
40
|
+
version = "0.1.4"
|
|
41
|
+
source = "git+https://github.com/markup-carve/carve-rs?rev=2e9c43f22c5ed05dbd93323ae6b9c94bb867b285#2e9c43f22c5ed05dbd93323ae6b9c94bb867b285"
|
|
42
42
|
dependencies = [
|
|
43
43
|
"html5ever",
|
|
44
44
|
"markup5ever_rcdom",
|
|
45
45
|
"pulldown-cmark",
|
|
46
|
+
"regex",
|
|
46
47
|
]
|
|
47
48
|
|
|
48
49
|
[[package]]
|
|
49
50
|
name = "carve-rb"
|
|
50
|
-
version = "0.1.
|
|
51
|
+
version = "0.1.2"
|
|
51
52
|
dependencies = [
|
|
52
53
|
"carve-lang",
|
|
53
54
|
"magnus",
|
|
54
55
|
"rb-sys",
|
|
56
|
+
"serde_json",
|
|
55
57
|
]
|
|
56
58
|
|
|
57
59
|
[[package]]
|
|
@@ -125,6 +127,12 @@ dependencies = [
|
|
|
125
127
|
"either",
|
|
126
128
|
]
|
|
127
129
|
|
|
130
|
+
[[package]]
|
|
131
|
+
name = "itoa"
|
|
132
|
+
version = "1.0.18"
|
|
133
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
134
|
+
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
135
|
+
|
|
128
136
|
[[package]]
|
|
129
137
|
name = "lazy_static"
|
|
130
138
|
version = "1.5.0"
|
|
@@ -471,6 +479,19 @@ dependencies = [
|
|
|
471
479
|
"syn 3.0.3",
|
|
472
480
|
]
|
|
473
481
|
|
|
482
|
+
[[package]]
|
|
483
|
+
name = "serde_json"
|
|
484
|
+
version = "1.0.151"
|
|
485
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
486
|
+
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
|
487
|
+
dependencies = [
|
|
488
|
+
"itoa",
|
|
489
|
+
"memchr",
|
|
490
|
+
"serde",
|
|
491
|
+
"serde_core",
|
|
492
|
+
"zmij",
|
|
493
|
+
]
|
|
494
|
+
|
|
474
495
|
[[package]]
|
|
475
496
|
name = "shell-words"
|
|
476
497
|
version = "1.1.1"
|
|
@@ -587,3 +608,9 @@ dependencies = [
|
|
|
587
608
|
"mac",
|
|
588
609
|
"markup5ever",
|
|
589
610
|
]
|
|
611
|
+
|
|
612
|
+
[[package]]
|
|
613
|
+
name = "zmij"
|
|
614
|
+
version = "1.0.23"
|
|
615
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
616
|
+
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
data/ext/carve/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "carve-rb"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
rust-version = "1.75"
|
|
6
6
|
publish = false
|
|
@@ -17,8 +17,9 @@ crate-type = ["cdylib"]
|
|
|
17
17
|
# interop handles so this builds cleanly under rb_sys/mkmf for Ruby 3.2.
|
|
18
18
|
magnus = { version = "0.8", features = ["rb-sys"] }
|
|
19
19
|
rb-sys = "0.9"
|
|
20
|
+
serde_json = "1"
|
|
20
21
|
|
|
21
22
|
# The Carve engine. Imported under the Rust crate alias `carve_rs` so the
|
|
22
23
|
# binding's own crate name (`carve-rb`) does not collide with the engine's
|
|
23
24
|
# package name (`carve`) in the Cargo lockfile.
|
|
24
|
-
carve_rs = { package = "carve-lang", git = "https://github.com/markup-carve/carve-rs", rev = "
|
|
25
|
+
carve_rs = { package = "carve-lang", git = "https://github.com/markup-carve/carve-rs", rev = "2e9c43f22c5ed05dbd93323ae6b9c94bb867b285" }
|
data/ext/carve/src/lib.rs
CHANGED
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
//! symbols: {...}, safe: ..., profile: ..., sections: ...)` on top of these
|
|
25
25
|
//! primitives.
|
|
26
26
|
|
|
27
|
-
|
|
28
27
|
use carve_rs::extensions::registry;
|
|
29
28
|
use carve_rs::{CarveExtension, Mode, Options, Profile, StaticRenderers};
|
|
30
29
|
use magnus::value::{InnerValue, Opaque};
|
|
@@ -200,6 +199,73 @@ fn to_html(source: String) -> String {
|
|
|
200
199
|
carve_rs::to_html(&source)
|
|
201
200
|
}
|
|
202
201
|
|
|
202
|
+
fn to_markdown(source: String) -> String {
|
|
203
|
+
carve_rs::to_markdown(&source)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
fn to_plain_text(source: String) -> String {
|
|
207
|
+
carve_rs::to_plain_text(&source)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
fn to_ansi(source: String) -> String {
|
|
211
|
+
carve_rs::to_ansi(&source)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
fn to_carve(source: String) -> String {
|
|
215
|
+
carve_rs::to_carve(&source)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fn from_html_json(ruby: &Ruby, source: String, mode: String) -> Result<String, Error> {
|
|
219
|
+
let mode = carve_rs::HtmlImportMode::from_name(&mode).ok_or_else(|| {
|
|
220
|
+
Error::new(
|
|
221
|
+
ruby.exception_arg_error(),
|
|
222
|
+
"mode must be safe, semantic, or roundtrip".to_string(),
|
|
223
|
+
)
|
|
224
|
+
})?;
|
|
225
|
+
let result = carve_rs::html_to_carve(
|
|
226
|
+
&source,
|
|
227
|
+
&carve_rs::HtmlImportOptions {
|
|
228
|
+
mode,
|
|
229
|
+
..Default::default()
|
|
230
|
+
},
|
|
231
|
+
)
|
|
232
|
+
.map_err(|error| {
|
|
233
|
+
Error::new(
|
|
234
|
+
ruby.exception_runtime_error(),
|
|
235
|
+
format!("HTML import failed: {error:?}"),
|
|
236
|
+
)
|
|
237
|
+
})?;
|
|
238
|
+
let diagnostics = result
|
|
239
|
+
.report
|
|
240
|
+
.diagnostics
|
|
241
|
+
.iter()
|
|
242
|
+
.map(|diagnostic| {
|
|
243
|
+
let mut value = serde_json::json!({
|
|
244
|
+
"code": diagnostic.code.as_str(),
|
|
245
|
+
"message": diagnostic.message,
|
|
246
|
+
"severity": diagnostic.severity.as_str(),
|
|
247
|
+
});
|
|
248
|
+
if let Some(path) = &diagnostic.path {
|
|
249
|
+
value["path"] = serde_json::json!(path);
|
|
250
|
+
}
|
|
251
|
+
value
|
|
252
|
+
})
|
|
253
|
+
.collect::<Vec<_>>();
|
|
254
|
+
Ok(serde_json::json!({
|
|
255
|
+
"value": result.value,
|
|
256
|
+
"report": {
|
|
257
|
+
"mode": result.report.mode.as_str(),
|
|
258
|
+
"adapter": result.report.adapter.as_str(),
|
|
259
|
+
"diagnostics": diagnostics,
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
.to_string())
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
fn from_markdown(source: String) -> String {
|
|
266
|
+
carve_rs::markdown_to_carve(&source)
|
|
267
|
+
}
|
|
268
|
+
|
|
203
269
|
/// Parse Carve source and return its AST as a JSON string.
|
|
204
270
|
///
|
|
205
271
|
/// The pure-Ruby wrapper (`Carve.parse`) turns this into a tree of Ruby
|
|
@@ -319,7 +385,9 @@ fn to_html_full_with_symbols(
|
|
|
319
385
|
// The safe-render arguments default off and section wrapping stays on, so
|
|
320
386
|
// this signature stays as published; `to_html_safe` is the one that takes
|
|
321
387
|
// them.
|
|
322
|
-
to_html_safe(
|
|
388
|
+
to_html_safe(
|
|
389
|
+
ruby, source, names, mode, renderers, symbols, false, None, true,
|
|
390
|
+
)
|
|
323
391
|
}
|
|
324
392
|
|
|
325
393
|
/// Map a profile name to a [`Profile`], or raise Ruby ArgumentError.
|
|
@@ -407,7 +475,6 @@ fn to_html_safe(
|
|
|
407
475
|
.map_err(|e| Error::new(ruby.exception_arg_error(), e.to_string()))
|
|
408
476
|
}
|
|
409
477
|
|
|
410
|
-
|
|
411
478
|
/// Read a document's provenance marker.
|
|
412
479
|
///
|
|
413
480
|
/// Returns a Hash `{version:, generated_by:}` or nil when the document carries
|
|
@@ -452,6 +519,12 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
452
519
|
// these. `_to_html` is the no-extension fast path; the wrapper owns the
|
|
453
520
|
// bare `to_html` name.
|
|
454
521
|
module.define_singleton_method("_to_html", function!(to_html, 1))?;
|
|
522
|
+
module.define_singleton_method("to_markdown", function!(to_markdown, 1))?;
|
|
523
|
+
module.define_singleton_method("to_plain_text", function!(to_plain_text, 1))?;
|
|
524
|
+
module.define_singleton_method("to_ansi", function!(to_ansi, 1))?;
|
|
525
|
+
module.define_singleton_method("to_carve", function!(to_carve, 1))?;
|
|
526
|
+
module.define_singleton_method("_from_html_json", function!(from_html_json, 2))?;
|
|
527
|
+
module.define_singleton_method("_from_markdown", function!(from_markdown, 1))?;
|
|
455
528
|
module.define_singleton_method("_to_ast_json", function!(to_ast_json, 1))?;
|
|
456
529
|
module.define_singleton_method(
|
|
457
530
|
"to_html_with_extensions",
|
data/lib/carve/version.rb
CHANGED
|
@@ -8,5 +8,5 @@ module Carve
|
|
|
8
8
|
# compares it against ext/carve/Cargo.toml and against the newest cut
|
|
9
9
|
# CHANGELOG section on every run, and .github/workflows/release.yml refuses to
|
|
10
10
|
# publish a gem whose version is not the tag being released.
|
|
11
|
-
VERSION = "0.1.
|
|
11
|
+
VERSION = "0.1.2"
|
|
12
12
|
end
|
data/lib/carve.rb
CHANGED
|
@@ -42,6 +42,19 @@ module Carve
|
|
|
42
42
|
RENDERER_KEYS = %i[mermaid chart graphviz math].freeze
|
|
43
43
|
|
|
44
44
|
class << self
|
|
45
|
+
# Import HTML or Markdown into canonical Carve. Both methods return the
|
|
46
|
+
# shared migration shape `{ value:, report: }`.
|
|
47
|
+
def from_html(source, mode: :safe)
|
|
48
|
+
JSON.parse(_from_html_json(source, mode.to_s), symbolize_names: true)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def from_markdown(source)
|
|
52
|
+
{
|
|
53
|
+
value: _from_markdown(source),
|
|
54
|
+
report: { source_format: "markdown", diagnostics: [] }
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
45
58
|
# Render Carve +source+ to an HTML string.
|
|
46
59
|
#
|
|
47
60
|
# With no extensions:
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: carve-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- markup-carve
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rb_sys
|
|
@@ -88,7 +88,8 @@ files:
|
|
|
88
88
|
homepage: https://github.com/markup-carve/carve-rb
|
|
89
89
|
licenses:
|
|
90
90
|
- MIT
|
|
91
|
-
metadata:
|
|
91
|
+
metadata:
|
|
92
|
+
rubygems_mfa_required: 'true'
|
|
92
93
|
post_install_message:
|
|
93
94
|
rdoc_options: []
|
|
94
95
|
require_paths:
|