mmmd 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a8790d6e9e6e5a9e3164e1f6f3ecf019cc73876d231676c562eb33925cea1a1
4
- data.tar.gz: 738942fca7cea39dbd6fd4fcb15b46d643646e5c5fbb90593f7bf330f967c8ae
3
+ metadata.gz: 98817fd73ed29d5b59ed440706d868c6a627632b072b39e8f0b41ade4d7253c6
4
+ data.tar.gz: f60b756923a31d9194aa574ddadc6d46f75f1de564b1e59198f8706fb88a1f2f
5
5
  SHA512:
6
- metadata.gz: cc7e8c75e20ced1af9c502ebfc5453489c427a61f2c8b7e9e0fa26d50dcaf56df3f522c5e560fca0b27f4d06603ca8e6bb9a720f9dc00929c9c847f408301709
7
- data.tar.gz: 03e2bcfff6462f28dc3439afdf02667a3944b6053e2b42da86fa2e1bfd4fffb8faa1bbfe2bcd4a0eaef006e6f22c9120a6cab365d475e294ccc3780e16dbba41
6
+ metadata.gz: 16a7da77e52b739ae8b40be7a5010731d4ddc8dde05388d4626477bfead344bdc9e52fcf6280684004d55d33a18477ec45aae083a962a839f5e62699951fff3f
7
+ data.tar.gz: 45efe890c613a4e0fd19805d7ae585200b3c89f24b217feffafe88c6a742d0e5e33870e72de138ffa3b4ca080cf89784e85406cf5e8d51dadbd84970b99f1448
data/README.md CHANGED
@@ -1,3 +1,59 @@
1
- # rubymark
1
+ MMMD (Mark My Message Down)
2
+ ============
3
+
4
+ (Originally titled Rubymark)
2
5
 
3
6
  Modular, compliant Markdown parser in Ruby
7
+
8
+ Installation
9
+ ------------
10
+
11
+ This package is available as a gem over at
12
+ [rubygems.org](https://rubygems.org/gems/mmmd).
13
+
14
+ Installing it is as simple as executing `gem install mmmd`
15
+
16
+ Usage
17
+ -----
18
+
19
+ This package is generally intended as a library, but it also
20
+ includes a CLI tool which permits the usage of the library
21
+ for simple document translation tasks.
22
+
23
+ Examples:
24
+ ```sh
25
+ # Render the file in a terminal-oriented format
26
+ $ mmmdpp file.md -
27
+
28
+ # Read the markdown contents directly from input, output to stdout
29
+ $ external-program | mmmdpp - -
30
+
31
+ # Render file.md to a complete webpage
32
+ $ mmmdpp -r HTML file.md file.html
33
+
34
+ # Render file.md into a complete webpage and add extra tags to head and
35
+ # wrap all images with a figure tag with figcaption containing image title
36
+ $ mmmdpp -r HTML -o '"head": ["<meta charset=\"UTF-8\">", "<style>img { max-width: 90%; }</style>"]' -o '"mapping"."PointBlank::DOM::InlineImage".figcaption: true' - -
37
+
38
+ # Render file.md into a set of HTML tags, without anything extra
39
+ $ mmmdpp -r HTML -o '"nowrap": true' file.md file.html
40
+ ```
41
+
42
+ A lot more usage options are documented on the Wiki page for the project
43
+
44
+ License
45
+ -------
46
+
47
+ Copyright 2025 yessiest@text.512mb.org
48
+
49
+ Licensed under the Apache License, Version 2.0 (the "License");
50
+ you may not use this file except in compliance with the License.
51
+ You may obtain a copy of the License at
52
+
53
+ http://www.apache.org/licenses/LICENSE-2.0
54
+
55
+ Unless required by applicable law or agreed to in writing, software
56
+ distributed under the License is distributed on an "AS IS" BASIS,
57
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
58
+ See the License for the specific language governing permissions and
59
+ limitations under the License.
data/bin/mmmdpp CHANGED
@@ -17,11 +17,8 @@ class OptionNavigator
17
17
  # Read a definition
18
18
  # @param define [String]
19
19
  def read_definition(define)
20
- define.split(";").each do |part|
21
- locstring, _, value = part.partition(":")
22
- locstring = deconstruct(locstring.strip)
23
- assign(locstring, JSON.parse(value))
24
- end
20
+ locstring, value = deconstruct(define)
21
+ assign(locstring, JSON.parse(value))
25
22
  end
26
23
 
27
24
  attr_reader :options
@@ -83,6 +80,9 @@ class OptionNavigator
83
80
  buffer = locstring[0..closepart]
84
81
  part = locstring[1..-2].to_i
85
82
  locstring = locstring.delete_prefix(buffer)
83
+ when ':'
84
+ locstring = locstring.delete_prefix(':')
85
+ break
86
86
  else
87
87
  raise ParserError, 'separator missing' unless buffer.empty?
88
88
 
@@ -92,7 +92,7 @@ class OptionNavigator
92
92
  end
93
93
  end
94
94
  parts.append(part) if part
95
- parts
95
+ [parts, locstring]
96
96
  end
97
97
 
98
98
  def assign(keys, value)
@@ -45,7 +45,8 @@ module MMMD
45
45
  tag: "ol"
46
46
  },
47
47
  "PointBlank::DOM::IndentBlock" => {
48
- tag: "pre"
48
+ tag: "pre",
49
+ codeblock: true
49
50
  },
50
51
  "PointBlank::DOM::ULListElement" => {
51
52
  tag: "li"
@@ -87,7 +88,8 @@ module MMMD
87
88
  tag: "pre",
88
89
  outer: {
89
90
  tag: "code"
90
- }
91
+ },
92
+ codeblock: true
91
93
  },
92
94
  "PointBlank::DOM::QuoteBlock" => {
93
95
  tag: "blockquote"
@@ -126,7 +128,11 @@ module MMMD
126
128
 
127
129
  def initialize(overrides)
128
130
  @mapping = self.class.mapping
129
- @mapping = @mapping.merge(overrides["mapping"]) if overrides["mapping"]
131
+ overrides["mapping"]&.each do |key, value|
132
+ next unless @mapping[key]
133
+
134
+ @mapping[key] = @mapping[key].merge(value)
135
+ end
130
136
  end
131
137
 
132
138
  attr_reader :mapping
@@ -154,7 +160,7 @@ module MMMD
154
160
  text = _render(@document, @options, level: @options["init_level"])
155
161
  @options["init_level"].times { text = indent(text) }
156
162
  if @options["nowrap"]
157
- text
163
+ remove_pre_spaces(text)
158
164
  else
159
165
  [
160
166
  preambule,
@@ -226,8 +232,7 @@ module MMMD
226
232
  end
227
233
 
228
234
  def _render(element, options, inline: false, level: 0, literaltext: false)
229
- modeswitch = element.is_a?(::PointBlank::DOM::LeafBlock) ||
230
- element.is_a?(::PointBlank::DOM::Paragraph)
235
+ modeswitch = figure_out_modeswitch(element)
231
236
  inline ||= modeswitch
232
237
  level += 1 unless inline
233
238
  text = if element.children.empty?
@@ -248,21 +253,29 @@ module MMMD
248
253
  literaltext: literaltext)
249
254
  end
250
255
 
256
+ def figure_out_modeswitch(element)
257
+ element.is_a?(::PointBlank::DOM::LeafBlock) ||
258
+ element.is_a?(::PointBlank::DOM::Paragraph)
259
+ end
260
+
251
261
  def run_filters(text, element, level:, inline:, modeswitch:,
252
262
  literaltext:)
253
263
  element_style = @mapping[element.class.name]
254
264
  return text unless element_style
255
265
  return text if literaltext
256
266
 
267
+ codeblock = element_style[:codeblock]
257
268
  hsize = @options["linewrap"] - (level * @options["indent"])
258
- text = wordwrap(text, hsize) if modeswitch
269
+ text = wordwrap(text, hsize) if modeswitch && !codeblock
270
+
259
271
  if element_style[:sanitize]
260
272
  text = MMMD::EntityUtils.encode_entities(text)
261
273
  end
262
274
  if element_style[:inline]
263
275
  innerclose(element, element_style, text)
264
276
  else
265
- openclose(text, element, element_style, inline)
277
+ openclose(text, element, element_style,
278
+ codeblock ? false : inline)
266
279
  end
267
280
  end
268
281
 
@@ -272,20 +285,25 @@ module MMMD
272
285
  opentag + text + closetag
273
286
  else
274
287
  [opentag,
275
- indent(text),
288
+ indent(text.rstrip),
276
289
  closetag].join("\n")
277
290
  end
278
291
  end
279
292
 
280
293
  def innerclose(element, style, text)
281
294
  props = element.properties
282
- tag = "<#{style[:tag]}"
295
+ tag = ""
296
+ tag += "<figure>" if style[:figcaption]
297
+ tag += "<#{style[:tag]}"
283
298
  tag += " style=#{style[:style].inspect}" if style[:style]
284
299
  tag += " href=#{read_link(element)}" if style[:href]
285
300
  tag += " alt=#{text.inspect}" if style[:alt]
286
301
  tag += " src=#{read_link(element)}" if style[:src]
287
302
  tag += " title=#{read_title(element)}" if style[:title] && props[:title]
288
303
  tag += ">"
304
+ if style[:figcaption]
305
+ tag += "<figcaption>#{text}</figcaption></figure>"
306
+ end
289
307
  if style[:outer]
290
308
  outeropen, outerclose = construct_tags(style[:outer], element)
291
309
  tag = outeropen + tag + outerclose
@@ -298,7 +316,11 @@ module MMMD
298
316
 
299
317
  props = element.properties
300
318
  opentag = "<#{style[:tag]}"
319
+ opentag += "<figure>#{opentag}" if style[:figcaption]
301
320
  closetag = "</#{style[:tag]}>"
321
+ if style[:figcaption]
322
+ closetag += "<figcaption>#{text}</figcaption></figure>"
323
+ end
302
324
  opentag += " style=#{style[:style].inspect}" if style[:style]
303
325
  opentag += " href=#{read_link(element)}" if style[:href]
304
326
  opentag += " src=#{read_link(element)}" if style[:src]
@@ -326,7 +348,7 @@ module MMMD
326
348
 
327
349
  def indent(text)
328
350
  text.lines.map do |line|
329
- "#{' ' * @options["indent"]}#{line}"
351
+ "#{' ' * @options['indent']}#{line}"
330
352
  end.join('')
331
353
  end
332
354
 
@@ -334,7 +356,7 @@ module MMMD
334
356
  head = @options['head']
335
357
  headinfo = "#{indent(<<~HEAD.rstrip)}\n " if head
336
358
  <head>
337
- #{head.is_a?(Array) ? head.join("\n") : head}
359
+ #{indent(head.is_a?(Array) ? head.join("\n") : head)}
338
360
  </head>
339
361
  HEAD
340
362
  headinfo ||= " "
@@ -381,7 +381,11 @@ module MMMD
381
381
  def initialize(overrides)
382
382
  @style = self.class.style
383
383
  @effect_priority = self.class.effect_priority
384
- @style = @style.merge(overrides["style"]) if overrides["style"]
384
+ overrides["style"]&.each do |key, value|
385
+ next unless @style[key]
386
+
387
+ @style[key] = @style[key].merge(value)
388
+ end
385
389
  end
386
390
 
387
391
  attr_reader :style, :effect_priority
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmmd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yessiest
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir:
10
10
  - bin
11
11
  cert_chain: []
12
- date: 2012-01-01 00:00:00.000000000 Z
12
+ date: 2025-04-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: |
15
15
  MMMD (short for Mark My Manuscript Down) is a Markdown processor
@@ -21,14 +21,8 @@ executables:
21
21
  extensions: []
22
22
  extra_rdoc_files:
23
23
  - README.md
24
- - architecture.md
25
- - security.md
26
- - test.md
27
- - test2.md
28
- - test3.md
29
24
  files:
30
25
  - README.md
31
- - architecture.md
32
26
  - bin/mmmdpp
33
27
  - lib/mmmd.rb
34
28
  - lib/mmmd/blankshell.rb
@@ -37,10 +31,6 @@ files:
37
31
  - lib/mmmd/renderers/html.rb
38
32
  - lib/mmmd/renderers/plainterm.rb
39
33
  - lib/mmmd/util.rb
40
- - security.md
41
- - test.md
42
- - test2.md
43
- - test3.md
44
34
  homepage: https://adastra7.net/git/Yessiest/rubymark
45
35
  licenses:
46
36
  - AGPL-3.0-or-later
data/architecture.md DELETED
@@ -1,278 +0,0 @@
1
- Architecture of madness
2
- =======================
3
-
4
- Prelude
5
- -------
6
-
7
- It needs to be stressed that making the parser modular while keeping it
8
- relatively simple was a laborous undertaking. There has not been a standard
9
- more hostile towards the people who dare attempt to implement it than
10
- CommonMark. It should also be noted, that despite it being titled a
11
- "Standard" in this document, it is less widely adopted than the Github
12
- Flavored Markdown syntax. Github Flavored Markdown, however, is only but
13
- a mere subset of this parser's model, albeit requiring a few extensions.
14
-
15
- Current state (as of March 02, 2025)
16
- ------------------------------------
17
-
18
- This parser processes text in what can be boiled down to three phases.
19
-
20
- - Block/Line phase
21
- - Overlay phase
22
- - Inline phase
23
-
24
- It should be noted that all phases have their own related parser
25
- classes, and a shared behaviour system, where each parser takes control
26
- at some point, and may win ambiguous cases by having higher priority
27
- (see `#define_child`, `#define_overlay` methods for priority parameter)
28
-
29
- ### Block/Line phase ###
30
-
31
- The first phase breaks down blocks, line by line, into block structures.
32
- Blocks (preferably inherited from the Block class) can contain other blocks.
33
- (i.e. QuoteBlock, ULBlock, OLBlock). Other blocks (known as leaf blocks)
34
- may not contain anything else (except inline content, more on that later).
35
-
36
- Blocks are designed to be parsed independently. This means that it *should*
37
- be possible to tear out any standard block and make it not get parsed.
38
- This, however, isn't thoroughly tested for.
39
-
40
- Blocks as proper, real classes have a certain lifecycle to follow when
41
- being constructed:
42
-
43
- 1. Open condition
44
- - A block needs to find its first marker on the current line to open
45
- (see `#begin?` method)
46
- - Once it's open, it's immediately initialized and fed the line it just
47
- read (but now as an object, not as a class) (see `#consume` method)
48
- 2. Marker/Line consumption
49
- - While it should be kept open, the block parser instance will
50
- keep reading inupt through `#consume` method, returning a pair
51
- of modified line (after consuming its tokens from it) and
52
- a boolean value indicating permission of lazy continuation
53
- (if it's a block like a QuoteBlock or ULBlock that can be lazily
54
- overflowed).
55
- Every line the parser needs to record needs to be pushed
56
- through the `#push` method.
57
- 3. Closure
58
- - If the current line no longer belongs to the current block
59
- (if the block should have been closed on the previous line),
60
- it simply needs to `return` a pair of `nil`, and a boolean value for
61
- permission of lazy continuation
62
- - If a block should be closed on the current line, it should capture it,
63
- keep track of the "closed" state, then `return` `nil` on the next call
64
- of `#consume`
65
- - Once a block is closed, it:
66
- 1. Receives its content from the parser
67
- 2. Parser receives the "close" method call
68
- 3. (optional) Parser may have a callable method `#applyprops`. If
69
- it exists, it gets called with the current constructed block.
70
- 4. (optional) All overlays assigned to this block's class are
71
- processed on the contents of this block (more on that in
72
- Overlay phase)
73
- 5. (optional) Parser may return a different class, which
74
- the current block should be cast into (Overlays may change
75
- the class as well)
76
- 6. (optional) If a block can respond to `#parse_inner` method, it
77
- will get called, allowing the block to parse its own contents.
78
- - After this point, the block is no longer touched until the document
79
- fully gets processed.
80
- 4. Inline processing
81
- - (Applies only to Paragraph and any child of LeafBlock)
82
- When the document gets fully processed, the contents of the current
83
- block are taken, assigned to an InlineRoot instance, and then parsed
84
- in Inline mode
85
- 5. Completion
86
- - The resulting document is then returned.
87
-
88
- While there is a lot of functionality available in desgining blocks, it is
89
- not necessary for the simplest of the block kinds available. The simplest
90
- example of a block parser is likely the ThematicBreakParser class, which
91
- implements the only 2 methods needed for a block parser to function.
92
-
93
- While parsing text, a block may use additional info:
94
-
95
- - In consume method: `lazy` hasharg, if the current line is being processed
96
- in lazy continuation mode (likely only ever matters for Paragraph); and
97
- `parent` - the parent block containing this block.
98
-
99
- Block interpretations are tried in decreasing order of their priority
100
- value, as applied using the `#define_child` method.
101
-
102
- For blocks to be properly indexed, they need to be a valid child or
103
- a valid descendant (meaning reachable through child chain) of the
104
- Document class.
105
-
106
- ### Overlay phase ###
107
-
108
- Overlay phase doesn't start at some specific point in time. Rather,
109
- Overlay phase happens for every block individually - when that block
110
- closes.
111
-
112
- Overlay mechanism can be applied to any DOMObject type, so long as its
113
- close method is called at some point (this may not be of interest to
114
- people that do not implement custom syntax, as it generally translates
115
- to "only block level elements get their overlays processed")
116
-
117
- Overlay mechanism provides the ability to perform some action on the block
118
- right after it gets closed and right before it gets interpreted by the
119
- inline phase. Overlays may do the following:
120
-
121
- - Change the block's class
122
- (by returning a class from the `#process` method)
123
- - Change the block's content (by directly editing it)
124
- - Change the block's properties (by modifying its `properties` hash)
125
-
126
- Overlay interpretations are tried in decreasing order of their priority
127
- value, as defined using the `#define_overlay` method.
128
-
129
- ### Inline phase ###
130
-
131
- Once all blocks have been processed, and all overlays have been applied
132
- to their respective block types, the hook in the Document class's
133
- `#parser` method executes inline parsing phase of all leaf blocks
134
- (descendants of the `Leaf` class) and paragraphs.
135
-
136
- The outer class encompassing all inline children of a block is
137
- `InlineRoot`. As such, if an inline element is to ever appear within the
138
- text, it needs to be reachable as a child or a descendant of InlineRoot.
139
-
140
- Inline parsing works in three parts:
141
-
142
- - First, the contens are tokenized (every parser marks its own tokens)
143
- - Second, the forward walk procedure is called
144
- - Third, the reverse walk procedure is called
145
-
146
- This process is repeated for every group of parsers with equal priority.
147
- At one point in time, only all the parsers of equal priority may run in
148
- the same step. Then, the process goes to the next step, of parsers of
149
- higher priority value. As counter-intuitive as this is, this means that
150
- it goes to the parsers of _lower_ priority.
151
-
152
- At the very end of the process, the remaining strings are concatenated
153
- within the mixed array of inlines and strings, and turned into Text
154
- nodes, after which the contents of the array are appended as children to
155
- the root node.
156
-
157
- This process is recursively applied to all elements which may have child
158
- elements. This is ensured when an inline parser calls the "build"
159
- utility method.
160
-
161
- The inline parser is a class that implements static methods `tokenize`
162
- and either `forward_walk` or `reverse_walk`. Both may be implemented at
163
- the same time, but this isn't advisable.
164
-
165
- The tokenization process is characterized by calling every parser in the
166
- current group with every string in tokens array using the `tokenize`
167
- method. It is expected that the parser breaks the string down into an
168
- array of other strings and tokens. A token is an array where the first
169
- element is the literal text representation of the token, the second
170
- value is the class of the parser, and the _last_ value (_not third_) is
171
- the `:close` or `:open` symbol (though functionally it may hold any
172
- symbol value). Any additional information the parser may need in later
173
- stages may be stored between the last element and the second element.
174
-
175
- Example:
176
-
177
- Input:
178
-
179
- "_this _is a string of_ tokens_"
180
-
181
- Output:
182
-
183
- [["_", ::PointBlank::Parsing::EmphInline, :open],
184
- "this ",
185
- ["_", ::PointBlank::Parsing::EmphInline, :open],
186
- "is a string of",
187
- ["_", ::PointBlank::Parsing::EmphInline, :close],
188
- " tokens",
189
- ["_", ::PointBlank::Parsing::EmphInline, :close]]
190
-
191
- The forward walk is characterized by calling parsers which implement the
192
- `#forward_walk` method. When the main class encounters an opening token
193
- in `forward_walk`, it will call the `#forward_walk` method of the class
194
- that represents this token. It is expected that the parser class will
195
- then attempt to build the first available occurence of the inline
196
- element it represents, after which it will return the array of all
197
- tokens and strings that it was passed where the first element will be
198
- the newly constructed inline element. If it is unable to close the
199
- block, it should simply return the original contents, unmodified.
200
-
201
- Example:
202
-
203
- Original text:
204
-
205
- this is outside the inline `this is inside the inline` and this
206
- is right after the inline `and this is the next inline`
207
-
208
- Input:
209
-
210
- [["`", ::PointBlank::Parsing::CodeInline, :open],
211
- "this is inside the inline"
212
- ["`", ::PointBlank::Parsing::CodeInline, :close],
213
- " and this is right after the inline ",
214
- ["`", ::PointBlank::Parsing::CodeInline, :open],
215
- "and this is the next inline"
216
- ["`", ::PointBlank::Parsing::CodeInline, :close]]
217
-
218
- Output:
219
-
220
- [<::PointBlank::DOM::InlineCode
221
- @content = "this is inside the inline">,
222
- " and this is right after the inline ",
223
- ["`", ::PointBlank::Parsing::CodeInline, :open],
224
- "and this is the next inline"
225
- ["`", ::PointBlank::Parsing::CodeInline, :close]]
226
-
227
- The reverse walk is characterized by calling parsers which implement the
228
- `#reverse_walk` method when the main class encounters a closing token
229
- for this class (the one that contains the `:close` symbol in the last
230
- position of the token information array). After that the main class will
231
- call the parser's `#reverse_walk` method with the current list of
232
- tokens, inlines and strings. It is expected that the parser will then
233
- collect all the blocks, strings and inlines that fit within the block
234
- closed by the last element in the list, and once it encounters the
235
- appropriate opening token for the closing token in the last position of
236
- the array, it will then replace the elements fitting within that inline
237
- with a class containing all the collected elements. If it is unable to
238
- find a matching opening token for the closing token in the last
239
- position, it should simply return the original contents, unmodified.
240
-
241
- Example:
242
-
243
- Original text:
244
-
245
- blah blah something something lots of text before the emphasis
246
- _this is emphasized `and this is an inline` but it's still
247
- emphasized_
248
-
249
-
250
- Input:
251
-
252
- ["blah blah something something lots of text before the emphasis",
253
- ["_", ::PointBlank::Parsing::EmphInline, :open],
254
- "this is emphasized",
255
- <::PointBlank::DOM::InlineCode,
256
- @content = "and this is an inline">,
257
- " but it's still emphasized",
258
- ["_", ::PointBlank::Parsing::EmphInline, :close]]
259
-
260
- Output:
261
-
262
- ["blah blah something something lots of text before the emphasis",
263
- <::PointBlank::DOM::InlineEmphasis,
264
- children = [...,
265
- <::PointBlank::DOM::InlineCode ...>
266
- ...]>]
267
-
268
- Both `#forward_walk` and `#reverse_walk` are not restricted to making
269
- just the changes discussed above, and can arbitrarily modify the token
270
- arrays. That, however, should be done with great care, so as to not
271
- accidentally break compatibility with other parsers.
272
-
273
- To ensure that the collected tokens in the `#reverse_walk` and
274
- `#forward_walk` are processes correctly, the colllected arrays of
275
- tokens, blocks and inlines should be built into an object that
276
- represents this parser using the `build` method (it will automatically
277
- attempt to find the correct class to construct using the
278
- `#define_parser` directive in the DOMObject subclass definition)
data/security.md DELETED
@@ -1,21 +0,0 @@
1
- Security acknowledgements
2
- =========================
3
-
4
- While special care has been taken to prevent some of the more common common
5
- vulnerabilities that might arise from using this parser, it does not prevent
6
- certain issues which **which should be acknowledged**.
7
-
8
- - It is possible to inject a form of one-click XSS into the website. In
9
- particular, there are no restrictions placed on urls embedded within the links
10
- (as per the description of CommonMark specification). As such, something as
11
- simple as `[test](<javascript:dangerous code here>)` would be more than enough
12
- to employ such an exploit.
13
- - While generally speaking the parser acts stable on most tests, and precents
14
- stray HTML tokens from occuring in the output text where appropriate, due to
15
- the nontrivial nature of the task some form of XSS injection may or may not
16
- occur. If such an incident occurs, please report it to the current maintainer
17
- of the project.
18
- - User input should NOT be trusted when it comes to applying options to
19
- rendering. Some renderers, such as the HTML renderer, allow modifying the
20
- style parameter for rendered tags, which when passed control of to an
21
- untrusted party may become an XSS attack vector.
data/test.md DELETED
@@ -1 +0,0 @@
1
- tokens blahblah **[test](/pee)** more tokens
data/test2.md DELETED
@@ -1,12 +0,0 @@
1
- > **Quote block**
2
- >
3
- > a**.not even emphasis.**b
4
- >
5
- > a**[neither is this emphasis](/uri 'but should it be?')**x
6
- >
7
- > **[emphasized image link ![image](/uri)](/link)**
8
- >
9
- > titlet
10
- > ======
11
- >
12
- > amongus
data/test3.md DELETED
@@ -1 +0,0 @@
1
- **test<http://autolink`>[stuff`[dat](#lonk)[`...](#stuff)**