kramdown-respec 0.0.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.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +600 -0
- data/bin/kramdown-respec +16 -0
- data/kramdown-respec.gemspec +15 -0
- data/lib/kramdown-respec.rb +362 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2ba63912c12fd783b548da579f41ccff5eaab6f46ad1e5c0fcde594d15eb2cbe
|
4
|
+
data.tar.gz: c796124e266be7c4353394daf20f49dd6563de213088654af8f9dd9ed0aa723d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 349070d5fb6f509747ba3e1cdf29b6bfb854de03608a1df388ab9897a3a335f29ee65deec5c6061516c01cf596f3961cbff555d7797be92a57aeb5e5e46a41f8
|
7
|
+
data.tar.gz: cdb905cdb4d0af314e0e28ee36dc736c18e8c6a896691d464e74953d4183195928cfe53710ce7b59e79a453edbe7d5ce31556fdc270f4e70730b68af0b4d4ff4
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2020 CoSMo Software <ludovic.roux@cosmosoftware.io>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,600 @@
|
|
1
|
+
# kramdown-respec
|
2
|
+
|
3
|
+
[kramdown][] is a [markdown][] parser by Thomas Leitner, which has a
|
4
|
+
number of backends for generating HTML, LaTeX, and markdown again.
|
5
|
+
|
6
|
+
**kramdown-respec** is an additional backend to that: It allows the
|
7
|
+
generation of W3C/ReSpec markup ([https://respec.org/docs/][]).
|
8
|
+
|
9
|
+
Who would care? Anybody who is writing Internet-Drafts and RFCs in
|
10
|
+
the [IETF][] and prefers (or has co-authors who prefer) to do part of
|
11
|
+
their work in markdown.
|
12
|
+
|
13
|
+
# Usage
|
14
|
+
|
15
|
+
Start by installing the kramdown-rfc2629 gem (this automatically
|
16
|
+
installs appropriate versions of referenced gems such as kramdown as
|
17
|
+
well):
|
18
|
+
|
19
|
+
gem install kramdown-rfc2629
|
20
|
+
|
21
|
+
(Add a `sudo` and a space in front of that command if you don't have
|
22
|
+
all the permissions needed.)
|
23
|
+
|
24
|
+
The guts of kramdown-rfc2629 are in one Ruby file,
|
25
|
+
`lib/kramdown-rfc2629.rb` --- this melds nicely into the extension
|
26
|
+
structure provided by kramdown. `bin/kramdown-rfc2629` started out as
|
27
|
+
a simple command-line program showing how to use this, but can now do
|
28
|
+
much more (see below).
|
29
|
+
|
30
|
+
To use kramdown-rfc2629, you'll need a Ruby 2.x, and maybe
|
31
|
+
[XML2RFC][] if you want to see the fruits of your work.
|
32
|
+
|
33
|
+
kramdown-rfc2629 mydraft.mkd >mydraft.xml
|
34
|
+
xml2rfc mydraft.xml
|
35
|
+
|
36
|
+
(The most popular file name extension that IETF people have for
|
37
|
+
markdown is .md -- for those who tend to think about GNU machine
|
38
|
+
descriptions here, any extension such as .mkd will do, too.)
|
39
|
+
|
40
|
+
A more brief interface for both calling kramdown-rfc2629 and XML2RFC
|
41
|
+
is provided by `kdrfc`:
|
42
|
+
|
43
|
+
kdrfc mydraft.mkd
|
44
|
+
|
45
|
+
`kdrfc` can also use a remote installation of XML2RFC if needed:
|
46
|
+
|
47
|
+
kdrfc -r mydraft.mkd
|
48
|
+
|
49
|
+
# Examples
|
50
|
+
|
51
|
+
For historical interest
|
52
|
+
`stupid.mkd` was an early markdown version of an actual Internet-Draft
|
53
|
+
(for a protocol called [STuPiD][] \[sic!]). This demonstrated some,
|
54
|
+
but not all features of kramdown-rfc2629. Since markdown/kramdown
|
55
|
+
does not cater for all the structure of an RFC 7749 style document,
|
56
|
+
some of the markup is in XML, and the example switches between XML and
|
57
|
+
markdown using kramdown's `{::nomarkdown}` and `{:/nomarkdown}` (this
|
58
|
+
is ugly, but works well enough). `stupid.xml` and `stupid.txt` show
|
59
|
+
what kramdown-rfc2629 and xml2rfc make out of this.
|
60
|
+
|
61
|
+
`stupid-s.mkd` is the same document in the new sectionized format
|
62
|
+
supported by kramdown-rfc2629. The document metadata are in a short
|
63
|
+
piece of YAML at the start, and from there, `abstract`, `middle`,
|
64
|
+
references (`normative` and `informative`) and `back` are sections
|
65
|
+
delimited in the markdown file. See the example for how this works.
|
66
|
+
The sections `normative` and `informative` can be populated right from
|
67
|
+
the metadata, so there is never a need to write XML any more.
|
68
|
+
Much less scary, and no `{:/nomarkdown}` etc. is needed any more.
|
69
|
+
Similarly, `stupid-s.xml` and `stupid-s.txt` show what
|
70
|
+
kramdown-rfc2629 and xml2rfc make out of this.
|
71
|
+
|
72
|
+
`draft-ietf-core-block-xx.mkd` is a real-world example of a current
|
73
|
+
Internet-Draft done this way. For RFC and Internet-Draft references,
|
74
|
+
it uses document prolog entities instead of caching the references in
|
75
|
+
the XML (i.e., not standalone mode, this is easier to handle when
|
76
|
+
collaborating with XML-only co-authors). See the `bibxml` metadata.
|
77
|
+
|
78
|
+
# The YAML header
|
79
|
+
|
80
|
+
Please consult the examples for the structure of the YAML header, this should be mostly
|
81
|
+
obvious. The `stand_alone` attribute controls whether the RFC/I-D
|
82
|
+
references are inserted into the document (yes) or entity-referenced
|
83
|
+
(no), the latter leads to increased build time, but may be more
|
84
|
+
palatable for a final XML conversion.
|
85
|
+
The author entry can be a single hash or a list, as in:
|
86
|
+
|
87
|
+
author:
|
88
|
+
ins: C. Bormann
|
89
|
+
name: Carsten Bormann
|
90
|
+
org: Universität Bremen TZI
|
91
|
+
abbrev: TZI
|
92
|
+
street: Bibliothekstr. 1
|
93
|
+
city: Bremen
|
94
|
+
code: D-28359
|
95
|
+
country: Germany
|
96
|
+
phone: +49-421-218-63921
|
97
|
+
email: cabo@tzi.org
|
98
|
+
|
99
|
+
or
|
100
|
+
|
101
|
+
author:
|
102
|
+
-
|
103
|
+
ins: C. Bormann
|
104
|
+
name: Carsten Bormann
|
105
|
+
org: Universität Bremen TZI
|
106
|
+
email: cabo@tzi.org
|
107
|
+
-
|
108
|
+
ins: Z. Shelby
|
109
|
+
name: Zach Shelby
|
110
|
+
org: Sensinode
|
111
|
+
role: editor
|
112
|
+
street: Kidekuja 2
|
113
|
+
city: Vuokatti
|
114
|
+
code: 88600
|
115
|
+
country: Finland
|
116
|
+
phone: "+358407796297"
|
117
|
+
email: zach@sensinode.com
|
118
|
+
-
|
119
|
+
role: editor
|
120
|
+
ins: P. Thubert
|
121
|
+
name: Pascal Thubert
|
122
|
+
org: Cisco Systems
|
123
|
+
abbrev: Cisco
|
124
|
+
street:
|
125
|
+
- Village d'Entreprises Green Side
|
126
|
+
- 400, Avenue de Roumanille
|
127
|
+
- Batiment T3
|
128
|
+
city: Biot - Sophia Antipolis
|
129
|
+
code: '06410'
|
130
|
+
country: FRANCE
|
131
|
+
phone: "+33 4 97 23 26 34"
|
132
|
+
email: pthubert@cisco.com
|
133
|
+
|
134
|
+
(the hash keys are the XML GIs from RFC 7749, with a flattened
|
135
|
+
structure. As RFC 7749 requires giving both the full name and
|
136
|
+
surname/initials, we use `ins` as an abbreviation for
|
137
|
+
"initials/surname". Yes, the toolchain is Unicode-capable, even if
|
138
|
+
the final RFC output is still in ASCII.)
|
139
|
+
|
140
|
+
Note that the YAML header needs to be syntactically valid YAML.
|
141
|
+
Where there is a potential for triggering some further YAML feature, a
|
142
|
+
string should be put in quotes (like the "+358407796297" above, which
|
143
|
+
might otherwise be interpreted as a number, losing the + sign).
|
144
|
+
|
145
|
+
## References
|
146
|
+
|
147
|
+
The references section is built from the references listed in the YAML
|
148
|
+
header and from references made inline to RFCs and I-Ds in the
|
149
|
+
markdown text. Since kramdown-rfc2629 cannot know whether a reference
|
150
|
+
is normative or informative, no entry is generated by default in the
|
151
|
+
references section. By indicating a normative reference as in
|
152
|
+
`{{!RFC2119}}` or an informative one as in `{{?RFC1925}}`, you can
|
153
|
+
completely automate the referencing, without the need to write
|
154
|
+
anything in the header. Alternatively, you can write something like:
|
155
|
+
|
156
|
+
informative:
|
157
|
+
RFC1925:
|
158
|
+
normative:
|
159
|
+
RFC2119:
|
160
|
+
|
161
|
+
and then just write `{{RFC2119}}` or `{{RFC1925}}`. (Yes, there is a
|
162
|
+
colon in the YAML, because this is a hash that could provide other
|
163
|
+
information.)
|
164
|
+
|
165
|
+
Since version 1.1, references imported from the [XML2RFC][] databases
|
166
|
+
can be supplied with a replacement label (anchor name). E.g., RFC 793
|
167
|
+
could be referenced as `{{!TCP=RFC0793}}`, further references then just
|
168
|
+
can say `{{TCP}}`; both will get `[TCP]` as the label. In the
|
169
|
+
YAML, the same replacement can be expressed as in the first example:
|
170
|
+
|
171
|
+
normative:
|
172
|
+
TCP: RFC0793
|
173
|
+
informative:
|
174
|
+
SST: DOI.10.1145/1282427.1282421
|
175
|
+
|
176
|
+
Notes about this feature:
|
177
|
+
|
178
|
+
* Thank you, Martin Thomson, for supplying an implementation and
|
179
|
+
insisting this be done.
|
180
|
+
* While this feature is now available, you are not forced to use it
|
181
|
+
for everything: readers of documents often benefit from not having
|
182
|
+
to look up references, so continuing to use the draft names and RFC
|
183
|
+
numbers as labels may be the preferable style in many cases.
|
184
|
+
* As a final caveat, renaming anchors does not work in the
|
185
|
+
`stand_alone: no` mode (except for IANA and DOI), as there is no
|
186
|
+
such mechanism in XML entity referencing; exporting to XML while
|
187
|
+
maintaining live references then may require some manual editing to
|
188
|
+
get rid of the custom anchors.
|
189
|
+
|
190
|
+
If your references are not in the [XML2RFC][] databases and do not
|
191
|
+
have a DOI (that also happens to have correct data) either, you need
|
192
|
+
to spell it out like in the examples below:
|
193
|
+
|
194
|
+
informative:
|
195
|
+
RFC1925:
|
196
|
+
WEI:
|
197
|
+
title: "6LoWPAN: the Wireless Embedded Internet"
|
198
|
+
# see the quotes above? Needed because of the embedded colon.
|
199
|
+
author:
|
200
|
+
-
|
201
|
+
ins: Z. Shelby
|
202
|
+
name: Zach Shelby
|
203
|
+
-
|
204
|
+
ins: C. Bormann
|
205
|
+
name: Carsten Bormann
|
206
|
+
date: 2009
|
207
|
+
seriesinfo:
|
208
|
+
ISBN: 9780470747995
|
209
|
+
ann: This is a really good reference on 6LoWPAN.
|
210
|
+
ASN.1:
|
211
|
+
title: >
|
212
|
+
Information Technology — ASN.1 encoding rules:
|
213
|
+
Specification of Basic Encoding Rules (BER), Canonical Encoding
|
214
|
+
Rules (CER) and Distinguished Encoding Rules (DER)
|
215
|
+
# YAML's ">" syntax used above is a good way to write longer titles
|
216
|
+
author:
|
217
|
+
org: International Telecommunications Union
|
218
|
+
date: 1994
|
219
|
+
seriesinfo:
|
220
|
+
ITU-T: Recommendation X.690
|
221
|
+
REST:
|
222
|
+
target: http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf
|
223
|
+
title: Architectural Styles and the Design of Network-based Software Architectures
|
224
|
+
author:
|
225
|
+
ins: R. Fielding
|
226
|
+
name: Roy Thomas Fielding
|
227
|
+
org: University of California, Irvine
|
228
|
+
date: 2000
|
229
|
+
seriesinfo:
|
230
|
+
"Ph.D.": "Dissertation, University of California, Irvine"
|
231
|
+
format:
|
232
|
+
PDF: http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf
|
233
|
+
COAP:
|
234
|
+
title: "CoAP: An Application Protocol for Billions of Tiny Internet Nodes"
|
235
|
+
seriesinfo:
|
236
|
+
DOI: 10.1109/MIC.2012.29
|
237
|
+
date: 2012
|
238
|
+
author:
|
239
|
+
-
|
240
|
+
ins: C. Bormann
|
241
|
+
name: Carsten Bormann
|
242
|
+
-
|
243
|
+
ins: A. P. Castellani
|
244
|
+
name: Angelo P. Castellani
|
245
|
+
-
|
246
|
+
ins: Z. Shelby
|
247
|
+
name: Zach Shelby
|
248
|
+
IPSO:
|
249
|
+
title: IP for Smart Objects (IPSO)
|
250
|
+
author:
|
251
|
+
- org:
|
252
|
+
date: false
|
253
|
+
seriesinfo:
|
254
|
+
Web: http://ipso-alliance.github.io/pub/
|
255
|
+
normative:
|
256
|
+
ECMA262:
|
257
|
+
author:
|
258
|
+
org: European Computer Manufacturers Association
|
259
|
+
title: ECMAScript Language Specification 5.1 Edition
|
260
|
+
date: 2011-06
|
261
|
+
target: http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf
|
262
|
+
seriesinfo:
|
263
|
+
ECMA: Standard ECMA-262
|
264
|
+
RFC2119:
|
265
|
+
RFC6690:
|
266
|
+
|
267
|
+
(as in the author list, `ins` is an abbreviation for
|
268
|
+
"initials/surname"; note that the first title had to be put in double
|
269
|
+
quotes as it contains a colon which is special syntax in YAML.)
|
270
|
+
Then you can simply reference `{{ASN.1}}` and
|
271
|
+
`{{ECMA262}}` in the text. (Make sure the reference keys are valid XML
|
272
|
+
names, though.)
|
273
|
+
|
274
|
+
# Experimental features
|
275
|
+
|
276
|
+
Most of the [kramdown syntax][kdsyntax] is supported and does
|
277
|
+
something useful; with the exception of the math syntax (math has no
|
278
|
+
special support in XML2RFC), and HTML syntax of course.
|
279
|
+
|
280
|
+
A number of more esoteric features have recently been added.
|
281
|
+
(The minimum required version for each full feature is indicated.)
|
282
|
+
|
283
|
+
(1.2.9:)
|
284
|
+
The YAML header now allows specifying [kramdown_options][].
|
285
|
+
|
286
|
+
[kramdown_options]: https://kramdown.gettalong.org/options.html
|
287
|
+
|
288
|
+
This was added specifically to provide easier access to the kramdown
|
289
|
+
`auto_id_prefix` feature, which prefixes by some distinguishing string
|
290
|
+
the anchors that are auto-generated for sections, avoiding conflicts:
|
291
|
+
|
292
|
+
```yaml
|
293
|
+
kramdown_options:
|
294
|
+
auto_id_prefix: sec-
|
295
|
+
```
|
296
|
+
|
297
|
+
(1.2.8:)
|
298
|
+
An experimental feature was added to include [BCP 14] boilerplate:
|
299
|
+
|
300
|
+
```markdown
|
301
|
+
{::boilerplate bcp14}
|
302
|
+
```
|
303
|
+
|
304
|
+
which saves some typing. Saying "bcp14+" instead of "bcp14" adds some
|
305
|
+
random clarifications at the end of the [standard boilerplate text][] that
|
306
|
+
you may or may not want to have. (Do we need other boilerplate items
|
307
|
+
beyond BCP14?)
|
308
|
+
|
309
|
+
[BCP 14]: https://www.rfc-editor.org/info/bcp14
|
310
|
+
|
311
|
+
[standard boilerplate text]: https://tools.ietf.org/html/rfc8174#page-3
|
312
|
+
|
313
|
+
(1.0.35:)
|
314
|
+
An experimental command `doilit` has been added. It can be used to
|
315
|
+
convert DOIs given on the command line into references entries for
|
316
|
+
kramdown-rfc YAML, saving a lot of typing. Note that the DOI database
|
317
|
+
is not of very consistent quality, so you likely have to hand-edit the
|
318
|
+
result before including it into the document (use `-v` to see raw JSON
|
319
|
+
data from the DOI database, made somewhat readable by converting it
|
320
|
+
into YAML). Use `-c` to enable caching (requires `open-uri-cached`
|
321
|
+
gem). Use `-h=handle` in front of a DOI to set a handle different
|
322
|
+
from the default `a`, `b`, etc. Similarly, use `-x=handle` to
|
323
|
+
generate XML2RFCv2 XML instead of kramdown-rfc YAML.
|
324
|
+
|
325
|
+
(1.0.31:)
|
326
|
+
The kramdown `smart_quotes` feature can be controlled better.
|
327
|
+
By default, it is on (with default kramdown settings), unless `coding:
|
328
|
+
us-ascii` is in effect, when it is off by default.
|
329
|
+
It also can be explicitly set on (`true`) or off (`false`) in the YAML
|
330
|
+
header, or to a specific value (an array of four kramdown entity names
|
331
|
+
or character numbers). E.g., for a German text (that is not intended
|
332
|
+
to become an Internet-Draft), one might write:
|
333
|
+
|
334
|
+
```yaml
|
335
|
+
smart_quotes: [sbquo, lsquo, bdquo, ldquo]
|
336
|
+
pi:
|
337
|
+
topblock: no
|
338
|
+
private: yes
|
339
|
+
```
|
340
|
+
|
341
|
+
(1.0.30:)
|
342
|
+
kramdown-rfc now uses kramdown 1.10, which leads to two notable updates:
|
343
|
+
|
344
|
+
* Support for empty link texts in the standard markdown
|
345
|
+
reference syntax, as in `[](#RFC7744)`.
|
346
|
+
* Language names in fenced code blocks now support all characters
|
347
|
+
except whitespace, so you can go wild with `asn.1` and `C#`.
|
348
|
+
|
349
|
+
A heuristic generates missing initials/surname from the `name` entry
|
350
|
+
in author information. This should save a lot of redundant typing.
|
351
|
+
You'll need to continue using the `ins` entry as well if that
|
352
|
+
heuristic fails (e.g., for Spanish names).
|
353
|
+
|
354
|
+
Also, there is some rather experimental support for markdown display
|
355
|
+
math (blocks between `$$` pairs) if the `tex2mail` tool is available.
|
356
|
+
|
357
|
+
(1.0.23:)
|
358
|
+
Move up to kramdown 1.6.0. This inherits a number of fixes and one
|
359
|
+
nice feature:
|
360
|
+
Markdown footnote definitions that turn into `cref`s can have their
|
361
|
+
attributes in the footnote definition:
|
362
|
+
|
363
|
+
```markdown
|
364
|
+
{:cabo: source="cabo"}
|
365
|
+
|
366
|
+
(This section to be removed by the RFC editor.)[^1]
|
367
|
+
|
368
|
+
[^1]: here is my editorial comment: warble warble.
|
369
|
+
{:cabo}
|
370
|
+
|
371
|
+
Another questionable paragraph.[^2]
|
372
|
+
|
373
|
+
[^2]: so why not delete it?
|
374
|
+
{: source="observer"}
|
375
|
+
```
|
376
|
+
|
377
|
+
(1.0.23:)
|
378
|
+
As before, IAL attributes on a codeblock go to the figure element.
|
379
|
+
Language attributes on the code block now become the artwork type, and any
|
380
|
+
attribute with a name that starts "artwork-" is moved over to the artwork.
|
381
|
+
So this snippet now does the obvious things:
|
382
|
+
|
383
|
+
```markdown
|
384
|
+
~~~ abnf
|
385
|
+
a = b / %s"foo" / %x0D.0A
|
386
|
+
~~~
|
387
|
+
{: artwork-align="center" artwork-name="syntax"}
|
388
|
+
```
|
389
|
+
|
390
|
+
(1.0.22:)
|
391
|
+
Index entries can be created with `(((item)))` or
|
392
|
+
`(((item, subitem)))`; use quotes for weird entries: `(((",", comma)))`.
|
393
|
+
If the index entry is to be marked "primary", prefix an (unquoted) `!`
|
394
|
+
as in `(((!item)))`.
|
395
|
+
|
396
|
+
In addition, auto-indexing is supported by hijacking the kramdown
|
397
|
+
"abbrev" syntax:
|
398
|
+
|
399
|
+
*[IANA]:
|
400
|
+
*[MUST]: BCP14
|
401
|
+
*[CBOR]: (((Object Representation, Concise Binary))) (((CBOR)))
|
402
|
+
|
403
|
+
The word in square brackets (which must match exactly,
|
404
|
+
case-sensitively) is entered into the index automatically for each
|
405
|
+
place where it occurs. If no title is given, just the word is entered
|
406
|
+
(first example). If one is given, that becomes the main item (the
|
407
|
+
auto-indexed word becomes the subitem, second example). If full
|
408
|
+
control is desired (e.g., for multiple entries per occurrence), just
|
409
|
+
write down the full index entries instead (third example).
|
410
|
+
|
411
|
+
(1.0.20:)
|
412
|
+
As an alternative referencing syntax for references with text,
|
413
|
+
`{{ref}}` can be expressed as `[text](#ref)`. As a special case, a
|
414
|
+
simple `[ref]` is interpreted as `[](#ref)` (except that the latter
|
415
|
+
syntax is not actually allowed by kramdown). This syntax does not
|
416
|
+
allow for automatic entry of items as normative/informative.
|
417
|
+
|
418
|
+
(1.0.16:) Markdown footnotes are converted into `cref`s (XML2RFC formal
|
419
|
+
comments; note that these are only visible if the pi "comments" is set to yes).
|
420
|
+
The anchor is taken from the markdown footnote name. The source, if
|
421
|
+
needed, can be supplied by an IAD, as in (first example with
|
422
|
+
ALD):
|
423
|
+
|
424
|
+
```markdown
|
425
|
+
{:cabo: source="cabo"}
|
426
|
+
|
427
|
+
(This section to be removed by the RFC editor.)[^1]{:cabo}
|
428
|
+
|
429
|
+
[^1]: here is my editorial comment
|
430
|
+
|
431
|
+
Another questionable paragraph.[^2]{: source="observer"}
|
432
|
+
|
433
|
+
[^2]: so why not delete it
|
434
|
+
```
|
435
|
+
|
436
|
+
Note that XML2RFC v2 doesn't allow structure in crefs. If you put any,
|
437
|
+
you get the escaped verbatim XML...
|
438
|
+
|
439
|
+
(1.0.11:) Allow overriding "style" attribute (via IAL =
|
440
|
+
[inline attribute list][kdsyntax-ial]) in lists and spans
|
441
|
+
as in:
|
442
|
+
|
443
|
+
```markdown
|
444
|
+
{:req: counter="bar" style="format R(%d)"}
|
445
|
+
|
446
|
+
{: req}
|
447
|
+
* Foo
|
448
|
+
* Bar
|
449
|
+
* Bax
|
450
|
+
|
451
|
+
Text outside the list, so a new IAL is needed.
|
452
|
+
|
453
|
+
* Foof
|
454
|
+
* Barf
|
455
|
+
* Barx
|
456
|
+
{: req}
|
457
|
+
```
|
458
|
+
|
459
|
+
(1.0.5:) An IAL attribute "cols" can be added to tables to override
|
460
|
+
the column layout. For example, `cols="* 20 30c r"` sets the width attributes to
|
461
|
+
20 and 30 for the middle columns and sets the right two columns to
|
462
|
+
center and right alignment, respectively. The alignment from `cols`
|
463
|
+
overrides that from the kramdown table, if present.
|
464
|
+
|
465
|
+
(1.0.2:) An IAL attribute "vspace" can be added to a definition list
|
466
|
+
to break after the definition term:
|
467
|
+
|
468
|
+
```markdown
|
469
|
+
{: vspace="0"}
|
470
|
+
word:
|
471
|
+
: definition
|
472
|
+
|
473
|
+
anotherword:
|
474
|
+
: another definition
|
475
|
+
```
|
476
|
+
|
477
|
+
(0.x:) Files can be included with the syntax `{::include fn}` (needs
|
478
|
+
to be in column 1 since 1.0.22; can be suppressed for use in servers
|
479
|
+
by setting environment variable KRAMDOWN_SAFE since 1.0.22). A
|
480
|
+
typical example from a recent RFC, where the contents of a figure was
|
481
|
+
machine-generated:
|
482
|
+
|
483
|
+
```markdown
|
484
|
+
~~~~~~~~~~
|
485
|
+
{::include ../ghc/packets-new/p4.out}
|
486
|
+
~~~~~~~~~~
|
487
|
+
{: #example2 title="A longer RPL example"}
|
488
|
+
```
|
489
|
+
|
490
|
+
(0.x:) A page break can be forced by adding a horizontal rule (`----`,
|
491
|
+
note that this creates ugly blank space in some HTML converters).
|
492
|
+
|
493
|
+
# Risks and Side-Effects
|
494
|
+
|
495
|
+
The code is not very polished, but now quite stable; it has been successfully used for a
|
496
|
+
number of non-trivial Internet-Drafts and RFCs. You probably still need to
|
497
|
+
skim [RFC 7749][] if you want to write an Internet-Draft, but you
|
498
|
+
don't really need to understand XML very much. Knowing the basics of
|
499
|
+
YAML helps with the metadata (but you'll understand it from the
|
500
|
+
examples).
|
501
|
+
|
502
|
+
Occasionally, you do need to reach through to the XML arcana, e.g. by
|
503
|
+
setting attribute values using kramdown's ["IAL" syntax][IAL].
|
504
|
+
This can for instance be used to obtain unnumbered appendices:
|
505
|
+
|
506
|
+
```markdown
|
507
|
+
Acknowledgements
|
508
|
+
================
|
509
|
+
{: numbered="no"}
|
510
|
+
|
511
|
+
John Mattsson was nice enough to point out the need for this being documented.
|
512
|
+
```
|
513
|
+
|
514
|
+
[IAL]: https://kramdown.gettalong.org/syntax.html#inline-attribute-lists
|
515
|
+
|
516
|
+
# Upconversion
|
517
|
+
|
518
|
+
If you have an old RFC and want to convert it to markdown, try just
|
519
|
+
using that RFC, it is 80 % there. It may be possible to automate the
|
520
|
+
remaining 20 % some more, but that hasn't been done.
|
521
|
+
|
522
|
+
If you have XML, there is an experimental upconverter that does 99 %
|
523
|
+
of the work. Please [contact the
|
524
|
+
author](mailto:cabo@tzi.org?subject=Markdown for RFCXML) if you want
|
525
|
+
to try it.
|
526
|
+
|
527
|
+
Actually, if the XML was generated by kramdown-rfc2629, you can simply
|
528
|
+
extract the input markdown from that XML file (but will of course lose
|
529
|
+
any edits that have been made to the XML file after generation):
|
530
|
+
|
531
|
+
kramdown-rfc-extract-markdown myfile.xml >myfile.md
|
532
|
+
|
533
|
+
|
534
|
+
# Tools
|
535
|
+
|
536
|
+
Joe Hildebrand has a
|
537
|
+
[grunt][] plugin for kramdown-rfc2629 at:
|
538
|
+
https://github.com/hildjj/grunt-kramdown-rfc2629
|
539
|
+
.
|
540
|
+
Get started with it at:
|
541
|
+
https://github.com/hildjj/grunt-init-rfc
|
542
|
+
.
|
543
|
+
This provides a self-refreshing web page with the
|
544
|
+
kramdown-rfc2629/xml2rfc rendition of the draft you are editing.
|
545
|
+
|
546
|
+
[grunt]: http://gruntjs.com
|
547
|
+
|
548
|
+
Martin Thomson has an [I-D Template][] for github repositories that enable
|
549
|
+
collaboration on draft development.
|
550
|
+
This supports kramdown-rfc2629 out of the
|
551
|
+
box. Just name your draft like `draft-ietf-unicorn-protocol-latest.md` and
|
552
|
+
follow the installation instructions.
|
553
|
+
|
554
|
+
[I-D Template]: https://github.com/martinthomson/i-d-template
|
555
|
+
|
556
|
+
# Related Work
|
557
|
+
|
558
|
+
Moving from XML to Markdown for RFC writing apparently is a
|
559
|
+
no-brainer, so I'm not the only one who has written code for this.
|
560
|
+
|
561
|
+
[Miek Gieben][] has done a [similar thing][pandoc2rfc] employing
|
562
|
+
pandoc, now documented in [RFC 7328][]. He uses multiple input files instead of
|
563
|
+
kramdown-rfc2629's sectionized input format. He keeps the metadata in
|
564
|
+
a separate XML file, similar to the way the previous version of
|
565
|
+
kramdown-rfc2629 stored (and still can store) the metadata in XML in
|
566
|
+
the markdown document. He also uses a slightly different referencing
|
567
|
+
syntax, which is closer to what markdown does elsewhere but more
|
568
|
+
verbose (this syntax is now also supported in kramdown-rfc2629).
|
569
|
+
(Miek now also has a new thing going on with mostly different syntax,
|
570
|
+
see [mmark][] and its [github repository][mmark-git].)
|
571
|
+
|
572
|
+
Other human-oriented markup input languages that are being used for authoring RFCXML include:
|
573
|
+
|
574
|
+
* [asciidoc][], with the [asciidoctor-rfc][] tool, as documented in [draft-ribose-asciirfc][].
|
575
|
+
* [orgmode][] (please help supply a more specific link here).
|
576
|
+
|
577
|
+
# License
|
578
|
+
|
579
|
+
Since kramdown version 1.0, kramdown itself is MIT licensed, which
|
580
|
+
made it possible to license kramdown-rfc2629 under the same license.
|
581
|
+
|
582
|
+
[kramdown]: http://kramdown.rubyforge.org/
|
583
|
+
[kdsyntax]: http://kramdown.gettalong.org/syntax.html
|
584
|
+
[kdsyntax-ial]: http://kramdown.gettalong.org/syntax.html#inline-attribute-lists
|
585
|
+
[stupid]: http://tools.ietf.org/id/draft-hartke-xmpp-stupid-00
|
586
|
+
[RFC 2629]: http://xml.resource.org/public/rfc/html/rfc2629.html
|
587
|
+
[RFC 7749]: http://tools.ietf.org/html/rfc7749
|
588
|
+
[markdown]: http://en.wikipedia.org/wiki/Markdown
|
589
|
+
[IETF]: http://www.ietf.org
|
590
|
+
[Miek Gieben]: http://www.miek.nl/
|
591
|
+
[pandoc2rfc]: https://github.com/miekg/pandoc2rfc/
|
592
|
+
[XML2RFC]: http://xml.resource.org
|
593
|
+
[RFC 7328]: http://tools.ietf.org/html/rfc7328
|
594
|
+
[mmark-git]: https://github.com/miekg/mmark
|
595
|
+
[mmark]: https://mmark.nl
|
596
|
+
[YAML]: http://www.yaml.org/spec/1.2/spec.html
|
597
|
+
[draft-ribose-asciirfc]: https://tools.ietf.org/html/draft-ribose-asciirfc
|
598
|
+
[asciidoctor-rfc]: https://github.com/metanorma/asciidoctor-rfc
|
599
|
+
[asciidoc]: http://www.methods.co.nz/asciidoc/
|
600
|
+
[orgmode]: http://orgmode.org
|
data/bin/kramdown-respec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require 'kramdown-respec'
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
$options = OpenStruct.new
|
9
|
+
op = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: kramdown-respec [options] file.md > file.html"
|
11
|
+
end
|
12
|
+
op.parse!
|
13
|
+
|
14
|
+
doc = Kramdown::Document.new(input, options)
|
15
|
+
$stderr.puts doc.warnings.to_yaml unless doc.warnings.empty?
|
16
|
+
puts doc.to_htmlRESPEC
|
@@ -0,0 +1,15 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'kramdown-respec'
|
3
|
+
s.version = '0.0.0'
|
4
|
+
s.summary = "Kramdown extension for generating respec HTML."
|
5
|
+
s.description = %{A respec HTML generating backend for Thomas Leitner's "kramdown" markdown parser. Mostly useful for RFC writers.}
|
6
|
+
s.add_dependency('kramdown', '~> 1.14')
|
7
|
+
s.files = Dir['lib/*.rb'] + %w(README.md LICENSE kramdown-respec.gemspec)
|
8
|
+
s.require_path = 'lib'
|
9
|
+
s.executables = ['kramdown-respec']
|
10
|
+
s.required_ruby_version = '>= 2.3.0'
|
11
|
+
s.authors = ['Ludovic Roux']
|
12
|
+
s.email = "ludovic.roux@cosmosoftware.io"
|
13
|
+
s.homepage = "http://github.com/ludocosmo/kramdown-respec"
|
14
|
+
s.license = 'MIT'
|
15
|
+
end
|
@@ -0,0 +1,362 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009-2010 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
# Copyright (C) 2020 CoSMo Software, Ludovic Roux <ludovic.roux@cosmosoftware.io>
|
6
|
+
#
|
7
|
+
# This file was derived from a part of the kramdown gem which is licensed under the MIT license.
|
8
|
+
# This derived work is also licensed under the MIT license, see LICENSE.
|
9
|
+
#++
|
10
|
+
#
|
11
|
+
|
12
|
+
raise "sorry, 1.8 was last decade" unless RUBY_VERSION >= '1.9'
|
13
|
+
|
14
|
+
gem 'kramdown', '~> 1.14'
|
15
|
+
require 'kramdown'
|
16
|
+
require 'kramdown/parser'
|
17
|
+
require 'kramdown/converter'
|
18
|
+
require 'kramdown/utils'
|
19
|
+
|
20
|
+
module Kramdown
|
21
|
+
|
22
|
+
# Re-open class Document
|
23
|
+
#
|
24
|
+
# The main interface to kramdown-respec.
|
25
|
+
#
|
26
|
+
# This class provides a one-stop-shop for using kramdown-respec to convert text into various output
|
27
|
+
# formats. Use it like this:
|
28
|
+
#
|
29
|
+
# require 'kramdown-respec'
|
30
|
+
# doc = KramdownRespec::Document.new('This *is* some kramdown-respec text')
|
31
|
+
# puts doc.to_html
|
32
|
+
#
|
33
|
+
# The #to_html method is a shortcut for using the Converter::Html class. See #method_missing for
|
34
|
+
# more information.
|
35
|
+
#
|
36
|
+
# The second argument to the ::new method is an options hash for customizing the behaviour of the
|
37
|
+
# used parser and the converter. See ::new for more information!
|
38
|
+
class Document
|
39
|
+
|
40
|
+
# Redfine method initialize()
|
41
|
+
#
|
42
|
+
# Create a new KramdownRespec document from the string +source+ and use the provided +options+.
|
43
|
+
# The options that can be used are defined in the Options module.
|
44
|
+
#
|
45
|
+
# The special options key :input can be used to select the parser that should parse the
|
46
|
+
# +source+. It has to be the name of a class in the KramdownRespec::Parser module. For example, to
|
47
|
+
# select the kramdown-respec parser, one would set the :input key to +KramdownRespec+. If this key
|
48
|
+
# is not set, it defaults to +KramdownRespec+.
|
49
|
+
#
|
50
|
+
# The +source+ is immediately parsed by the selected parser so that the root element is
|
51
|
+
# immediately available and the output can be generated.
|
52
|
+
def initialize(source, options = {})
|
53
|
+
@options = Options.merge(options).freeze
|
54
|
+
# parser = (@options[:input] || 'kramdown-respec').to_s
|
55
|
+
parser = (@options[:input] || 'kramdown').to_s
|
56
|
+
parser = parser[0..0].upcase + parser[1..-1]
|
57
|
+
try_require('parser', parser)
|
58
|
+
if Parser.const_defined?(parser)
|
59
|
+
@root, @warnings = Parser.const_get(parser).parse(source, @options)
|
60
|
+
else
|
61
|
+
raise Kramdown::Error.new("kramdown-respec has no parser to handle the specified input format: #{@options[:input]}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
module Parser
|
69
|
+
|
70
|
+
# class KramdownRespec < Kramdown::Parser::Kramdown
|
71
|
+
|
72
|
+
class Kramdown < Base
|
73
|
+
|
74
|
+
include ::Kramdown
|
75
|
+
|
76
|
+
# Create a new Kramdown parser object with the given +options+.
|
77
|
+
def initialize(source, options)
|
78
|
+
super
|
79
|
+
|
80
|
+
reset_env
|
81
|
+
|
82
|
+
@alds = {}
|
83
|
+
@footnotes = {}
|
84
|
+
@link_defs = {}
|
85
|
+
update_link_definitions(@options[:link_defs])
|
86
|
+
|
87
|
+
@block_parsers = [:blank_line, :codeblock, :codeblock_fenced, :blockquote, :atx_header,
|
88
|
+
:horizontal_rule, :list, :definition_list, :block_html, :setext_header,
|
89
|
+
:block_math, :table, :footnote_definition, :link_definition, :abbrev_definition,
|
90
|
+
:block_extensions, :eob_marker, :paragraph, :respectests]
|
91
|
+
@span_parsers = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link, :smart_quotes, :inline_math,
|
92
|
+
:span_extensions, :html_entity, :typographic_syms, :line_break, :escaped_chars,
|
93
|
+
:respectests]
|
94
|
+
|
95
|
+
end
|
96
|
+
# def initialize(source, options)
|
97
|
+
# super
|
98
|
+
# @span_parsers.unshift(:respectests)
|
99
|
+
# @block_parsers.unshift(:respectests)
|
100
|
+
# end
|
101
|
+
|
102
|
+
# List of possible annotations
|
103
|
+
# If annotation is not in the list, then it should be a reference to a test
|
104
|
+
RESPECTESTS_ANNOTATIONS = ["untestable", "informative", "note", "no-test-needed", "needs-test"]
|
105
|
+
|
106
|
+
RESPECTESTS = /\{:&(.*)\}/
|
107
|
+
RESPECTESTS_START = /^#{OPT_SPACE}#{RESPECTESTS}/
|
108
|
+
|
109
|
+
# Parse one of the block extensions (ALD, block IAL or generic extension) at the current
|
110
|
+
# location.
|
111
|
+
def parse_block_extensions
|
112
|
+
# Parse the string +str+ and extract the annotation or the list of tests
|
113
|
+
if @src.scan(RESPECTESTS_START)
|
114
|
+
last_child = @tree.children.last
|
115
|
+
if last_child.type == :header
|
116
|
+
parse_respec_tests_list(@src[1], last_child.options[:respec_section] ||= {})
|
117
|
+
@tree.children << new_block_el(:eob, :respec_section)
|
118
|
+
else
|
119
|
+
parse_respec_tests_list(@src[1], last_child.options[:ial] ||= {})
|
120
|
+
@tree.children << new_block_el(:eob, :ial)
|
121
|
+
end
|
122
|
+
# Original parser of block extensions
|
123
|
+
elsif @src.scan(ALD_START)
|
124
|
+
parse_attribute_list(@src[2], @alds[@src[1]] ||= Utils::OrderedHash.new)
|
125
|
+
@tree.children << new_block_el(:eob, :ald)
|
126
|
+
true
|
127
|
+
elsif @src.check(EXT_BLOCK_START)
|
128
|
+
parse_extension_start_tag(:block)
|
129
|
+
elsif @src.scan(IAL_BLOCK_START)
|
130
|
+
if @tree.children.last && @tree.children.last.type != :blank &&
|
131
|
+
(@tree.children.last.type != :eob || [:link_def, :abbrev_def, :footnote_def].include?(@tree.children.last.value))
|
132
|
+
parse_attribute_list(@src[1], @tree.children.last.options[:ial] ||= Utils::OrderedHash.new)
|
133
|
+
@tree.children << new_block_el(:eob, :ial) unless @src.check(IAL_BLOCK_START)
|
134
|
+
else
|
135
|
+
parse_attribute_list(@src[1], @block_ial ||= Utils::OrderedHash.new)
|
136
|
+
end
|
137
|
+
true
|
138
|
+
else
|
139
|
+
false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
# Parse the string +str+ and extract the annotation or the list of tests
|
143
|
+
# def parse_block_extensions
|
144
|
+
# if @src.scan(RESPECTESTS_START)
|
145
|
+
# last_child = @tree.children.last
|
146
|
+
# if last_child.type == :header
|
147
|
+
# parse_respec_tests_list(@src[1], last_child.options[:respec_section] ||= {})
|
148
|
+
# @tree.children << new_block_el(:eob, :respec_section)
|
149
|
+
# else
|
150
|
+
# parse_respec_tests_list(@src[1], last_child.options[:ial] ||= {})
|
151
|
+
# @tree.children << new_block_el(:eob, :ial)
|
152
|
+
# end
|
153
|
+
# else
|
154
|
+
# super
|
155
|
+
# end
|
156
|
+
# end
|
157
|
+
|
158
|
+
# Parse the string +str+ and extract the annotation or the list of tests
|
159
|
+
def parse_respec_tests_list(str, opts)
|
160
|
+
str = str.strip
|
161
|
+
if RESPECTESTS_ANNOTATIONS.include?(str)
|
162
|
+
opts['class'] = "#{str}"
|
163
|
+
else
|
164
|
+
opts['data-tests'] = "#{str}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def parse_respectests
|
169
|
+
last_child = @tree.children.last
|
170
|
+
if last_child.type == :header
|
171
|
+
parse_respec_tests_list(@src[1], last_child.options[:respec_section] ||= {})
|
172
|
+
@tree.children << new_block_el(:eob, :respec_section)
|
173
|
+
else
|
174
|
+
parse_respec_tests_list(@src[1], last_child.options[:ial] ||= {})
|
175
|
+
@tree.children << new_block_el(:eob, :ial)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Parse the extension span at the current location.
|
180
|
+
def parse_span_extensions
|
181
|
+
if @src.check(RESPECTESTS_START)
|
182
|
+
if (last_child = @tree.children.last) && last_child.type != :text
|
183
|
+
@src.pos += @src.matched_size
|
184
|
+
attr = {}
|
185
|
+
parse_respec_tests_list(@src[1], attr)
|
186
|
+
update_ial_with_ial(last_child.options[:ial] ||= {}, attr)
|
187
|
+
update_attr_with_ial(last_child.attr, attr)
|
188
|
+
else
|
189
|
+
warning("Found span respec-test after text - ignoring it")
|
190
|
+
add_text(@src.getch)
|
191
|
+
end
|
192
|
+
# Original parser of span extension
|
193
|
+
elsif @src.check(EXT_SPAN_START)
|
194
|
+
parse_extension_start_tag(:span)
|
195
|
+
elsif @src.check(IAL_SPAN_START)
|
196
|
+
if @tree.children.last && @tree.children.last.type != :text
|
197
|
+
@src.pos += @src.matched_size
|
198
|
+
attr = Utils::OrderedHash.new
|
199
|
+
parse_attribute_list(@src[1], attr)
|
200
|
+
update_ial_with_ial(@tree.children.last.options[:ial] ||= Utils::OrderedHash.new, attr)
|
201
|
+
update_attr_with_ial(@tree.children.last.attr, attr)
|
202
|
+
else
|
203
|
+
warning("Found span IAL after text - ignoring it")
|
204
|
+
add_text(@src.getch)
|
205
|
+
end
|
206
|
+
else
|
207
|
+
add_text(@src.getch)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
# Parse the extension span at the current location.
|
211
|
+
# def parse_span_extensions
|
212
|
+
# if @src.check(RESPECTESTS_START)
|
213
|
+
# if (last_child = @tree.children.last) && last_child.type != :text
|
214
|
+
# @src.pos += @src.matched_size
|
215
|
+
# attr = {}
|
216
|
+
# parse_respec_tests_list(@src[1], attr)
|
217
|
+
# update_ial_with_ial(last_child.options[:ial] ||= {}, attr)
|
218
|
+
# update_attr_with_ial(last_child.attr, attr)
|
219
|
+
# else
|
220
|
+
# warning("Found span respec-test after text - ignoring it")
|
221
|
+
# add_text(@src.getch)
|
222
|
+
# end
|
223
|
+
# else
|
224
|
+
# super
|
225
|
+
# end
|
226
|
+
# end
|
227
|
+
|
228
|
+
define_parser(:respectests, RESPECTESTS_START, '{:&')
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
module Converter
|
235
|
+
|
236
|
+
# Converts an element tree to the kramdown-respec format.
|
237
|
+
# class KramdownRespec < Kramdown
|
238
|
+
# end
|
239
|
+
|
240
|
+
|
241
|
+
# class HtmlRESPEC < Html
|
242
|
+
class Html < Base
|
243
|
+
|
244
|
+
# Initialize the HTML converter with the given Kramdown document +doc+.
|
245
|
+
def initialize(root, options)
|
246
|
+
super
|
247
|
+
@footnote_counter = @footnote_start = @options[:footnote_nr]
|
248
|
+
@footnotes = []
|
249
|
+
@footnotes_by_name = {}
|
250
|
+
@footnote_location = nil
|
251
|
+
@toc = []
|
252
|
+
@toc_code = nil
|
253
|
+
@indent = 2
|
254
|
+
@stack = []
|
255
|
+
@respec_first_section = true
|
256
|
+
@respec_last_header_level = 0
|
257
|
+
end
|
258
|
+
# Initialize the HTML converter with the given Kramdown document +doc+.
|
259
|
+
# def initialize(root, options)
|
260
|
+
# super
|
261
|
+
# @respec_first_section = true
|
262
|
+
# @respec_last_header_level = 0
|
263
|
+
# end
|
264
|
+
|
265
|
+
def convert_root(el, indent)
|
266
|
+
result = inner(el, indent)
|
267
|
+
if @footnote_location
|
268
|
+
result.sub!(/#{@footnote_location}/, footnote_content.gsub(/\\/, "\\\\\\\\"))
|
269
|
+
else
|
270
|
+
result << footnote_content
|
271
|
+
end
|
272
|
+
if @toc_code
|
273
|
+
toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {})
|
274
|
+
text = if toc_tree.children.size > 0
|
275
|
+
convert(toc_tree, 0)
|
276
|
+
else
|
277
|
+
''
|
278
|
+
end
|
279
|
+
result.sub!(/#{@toc_code.last}/, text.gsub(/\\/, "\\\\\\\\"))
|
280
|
+
end
|
281
|
+
# Close the last sections that remain opened
|
282
|
+
current_header_level = 2
|
283
|
+
while @respec_last_header_level > current_header_level
|
284
|
+
result += "</section>\n\n"
|
285
|
+
@respec_last_header_level -= 1
|
286
|
+
end
|
287
|
+
result + "</section>\n\n"
|
288
|
+
result
|
289
|
+
end
|
290
|
+
# def convert_root(el, indent)
|
291
|
+
# result = super
|
292
|
+
# # Close the last sections that remain opened
|
293
|
+
# current_header_level = 2
|
294
|
+
# while @respec_last_header_level > current_header_level
|
295
|
+
# result += "</section>\n\n"
|
296
|
+
# @respec_last_header_level -= 1
|
297
|
+
# end
|
298
|
+
# result + "</section>\n\n"
|
299
|
+
# end
|
300
|
+
|
301
|
+
def convert_header(el, indent)
|
302
|
+
res = ""
|
303
|
+
current_header_level = el.options[:level]
|
304
|
+
if @respec_first_section
|
305
|
+
@respec_first_section = false
|
306
|
+
@respec_last_header_level = current_header_level
|
307
|
+
else
|
308
|
+
if @respec_last_header_level < current_header_level
|
309
|
+
@respec_last_header_level = current_header_level
|
310
|
+
else
|
311
|
+
while @respec_last_header_level > current_header_level
|
312
|
+
res += "#{' ' * indent}</section>\n\n"
|
313
|
+
@respec_last_header_level -= 1
|
314
|
+
end
|
315
|
+
res += "#{' ' * indent}</section>\n\n"
|
316
|
+
end
|
317
|
+
end
|
318
|
+
if el.options[:respec_section]
|
319
|
+
res += "#{' ' * indent}<section#{html_attributes(el.options[:respec_section])}>\n"
|
320
|
+
else
|
321
|
+
res += "#{' ' * indent}<section>\n"
|
322
|
+
end
|
323
|
+
# res + super
|
324
|
+
|
325
|
+
attr = el.attr.dup
|
326
|
+
if @options[:auto_ids] && !attr['id']
|
327
|
+
attr['id'] = generate_id(el.options[:raw_text])
|
328
|
+
end
|
329
|
+
@toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el)
|
330
|
+
level = output_header_level(el.options[:level])
|
331
|
+
res + format_as_block_html("h#{level}", attr, inner(el, indent), indent)
|
332
|
+
end
|
333
|
+
# def convert_header(el, indent)
|
334
|
+
# res = ""
|
335
|
+
# current_header_level = el.options[:level]
|
336
|
+
# if @respec_first_section
|
337
|
+
# @respec_first_section = false
|
338
|
+
# @respec_last_header_level = current_header_level
|
339
|
+
# else
|
340
|
+
# if @respec_last_header_level < current_header_level
|
341
|
+
# @respec_last_header_level = current_header_level
|
342
|
+
# else
|
343
|
+
# while @respec_last_header_level > current_header_level
|
344
|
+
# res += "#{' ' * indent}</section>\n\n"
|
345
|
+
# @respec_last_header_level -= 1
|
346
|
+
# end
|
347
|
+
# res += "#{' ' * indent}</section>\n\n"
|
348
|
+
# end
|
349
|
+
# end
|
350
|
+
# if el.options[:respec_section]
|
351
|
+
# res += "#{' ' * indent}<section#{html_attributes(el.options[:respec_section])}>\n"
|
352
|
+
# else
|
353
|
+
# res += "#{' ' * indent}<section>\n"
|
354
|
+
# end
|
355
|
+
# res + super
|
356
|
+
# end
|
357
|
+
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kramdown-respec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ludovic Roux
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kramdown
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
description: A respec HTML generating backend for Thomas Leitner's "kramdown" markdown
|
28
|
+
parser. Mostly useful for RFC writers.
|
29
|
+
email: ludovic.roux@cosmosoftware.io
|
30
|
+
executables:
|
31
|
+
- kramdown-respec
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- bin/kramdown-respec
|
38
|
+
- kramdown-respec.gemspec
|
39
|
+
- lib/kramdown-respec.rb
|
40
|
+
homepage: http://github.com/ludocosmo/kramdown-respec
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.3.0
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubygems_version: 3.1.2
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Kramdown extension for generating respec HTML.
|
63
|
+
test_files: []
|