kramdown-respec 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|