markbridge 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/lib/markbridge/ast/details.rb +24 -0
- data/lib/markbridge/ast/element.rb +63 -0
- data/lib/markbridge/ast.rb +1 -0
- data/lib/markbridge/conversion.rb +40 -0
- data/lib/markbridge/parse.rb +20 -0
- data/lib/markbridge/parsers/bbcode/handler_registry.rb +25 -2
- data/lib/markbridge/parsers/bbcode/handlers/raw_handler.rb +13 -2
- data/lib/markbridge/parsers/html/handler_registry.rb +97 -17
- data/lib/markbridge/parsers/html/handlers/self_closing_handler.rb +26 -0
- data/lib/markbridge/parsers/html/handlers/span_handler.rb +74 -0
- data/lib/markbridge/parsers/html/parser.rb +88 -18
- data/lib/markbridge/parsers/html.rb +2 -0
- data/lib/markbridge/parsers/media_wiki/inline_parser.rb +21 -8
- data/lib/markbridge/parsers/media_wiki/parser.rb +13 -5
- data/lib/markbridge/parsers/text_formatter/handler_registry.rb +27 -4
- data/lib/markbridge/parsers/text_formatter/handlers/attachment_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/attribute_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/base_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/code_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/email_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/image_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/list_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/quote_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/simple_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/table_cell_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/handlers/url_handler.rb +1 -1
- data/lib/markbridge/parsers/text_formatter/parser.rb +17 -3
- data/lib/markbridge/renderers/discourse/identity_escaper.rb +37 -0
- data/lib/markbridge/renderers/discourse/markdown_escaper.rb +83 -8
- data/lib/markbridge/renderers/discourse/postprocessor.rb +53 -0
- data/lib/markbridge/renderers/discourse/render_context.rb +14 -40
- data/lib/markbridge/renderers/discourse/renderer.rb +15 -5
- data/lib/markbridge/renderers/discourse/rendering_interface.rb +4 -3
- data/lib/markbridge/renderers/discourse/tag_library.rb +42 -2
- data/lib/markbridge/renderers/discourse/tags/align_tag.rb +2 -2
- data/lib/markbridge/renderers/discourse/tags/code_tag.rb +5 -3
- data/lib/markbridge/renderers/discourse/tags/details_tag.rb +46 -0
- data/lib/markbridge/renderers/discourse/tags/heading_tag.rb +1 -1
- data/lib/markbridge/renderers/discourse/tags/paragraph_tag.rb +5 -2
- data/lib/markbridge/renderers/discourse/tags/quote_tag.rb +4 -3
- data/lib/markbridge/renderers/discourse/tags/underline_tag.rb +13 -0
- data/lib/markbridge/renderers/discourse.rb +3 -0
- data/lib/markbridge/version.rb +1 -1
- data/lib/markbridge.rb +274 -111
- metadata +9 -11
- data/lib/markbridge/configuration.rb +0 -11
- data/lib/markbridge/processors/discourse_markdown/code_block_tracker.rb +0 -218
- data/lib/markbridge/processors/discourse_markdown/detectors/base.rb +0 -63
- data/lib/markbridge/processors/discourse_markdown/detectors/event.rb +0 -64
- data/lib/markbridge/processors/discourse_markdown/detectors/mention.rb +0 -57
- data/lib/markbridge/processors/discourse_markdown/detectors/poll.rb +0 -52
- data/lib/markbridge/processors/discourse_markdown/detectors/upload.rb +0 -98
- data/lib/markbridge/processors/discourse_markdown/scanner.rb +0 -194
- data/lib/markbridge/processors/discourse_markdown.rb +0 -16
- data/lib/markbridge/processors.rb +0 -8
data/lib/markbridge.rb
CHANGED
|
@@ -1,166 +1,329 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "markbridge/version"
|
|
4
|
-
require_relative "markbridge/
|
|
4
|
+
require_relative "markbridge/parse"
|
|
5
|
+
require_relative "markbridge/conversion"
|
|
5
6
|
|
|
6
7
|
require_relative "markbridge/ast"
|
|
7
8
|
require_relative "markbridge/renderers/discourse"
|
|
8
|
-
require_relative "markbridge/processors"
|
|
9
9
|
|
|
10
10
|
module Markbridge
|
|
11
11
|
class << self
|
|
12
|
-
# Parse BBCode to AST
|
|
12
|
+
# Parse BBCode to AST.
|
|
13
|
+
#
|
|
13
14
|
# @param input [String] BBCode source
|
|
14
|
-
# @param handlers [HandlerRegistry, nil] custom
|
|
15
|
-
# @return [
|
|
15
|
+
# @param handlers [Parsers::BBCode::HandlerRegistry, nil] custom handlers (defaults to .default)
|
|
16
|
+
# @return [Parse]
|
|
16
17
|
def parse_bbcode(input, handlers: nil)
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
raise ArgumentError, "input cannot be nil" if input.nil?
|
|
19
|
+
|
|
20
|
+
parser = Parsers::BBCode::Parser.new(handlers:)
|
|
21
|
+
ast = parser.parse(input.to_s)
|
|
22
|
+
|
|
23
|
+
Parse.new(
|
|
24
|
+
ast:,
|
|
25
|
+
format: :bbcode,
|
|
26
|
+
unknown_tags: parser.unknown_tags,
|
|
27
|
+
diagnostics: bbcode_diagnostics(parser),
|
|
28
|
+
)
|
|
19
29
|
end
|
|
20
30
|
|
|
21
|
-
# Convert BBCode to Discourse Markdown
|
|
31
|
+
# Convert BBCode to Discourse Markdown.
|
|
32
|
+
#
|
|
33
|
+
# If a block is given, it is called with the parsed AST between
|
|
34
|
+
# parse and render — the caller can append/remove/replace nodes
|
|
35
|
+
# before rendering. Mutations to the yielded AST persist in
|
|
36
|
+
# {Conversion#ast}.
|
|
37
|
+
#
|
|
22
38
|
# @param input [String] BBCode source
|
|
23
|
-
# @param handlers [HandlerRegistry, nil] custom
|
|
24
|
-
# @param
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
# @param handlers [Parsers::BBCode::HandlerRegistry, nil] custom handlers
|
|
40
|
+
# @param renderer [Renderers::Discourse::Renderer, nil] custom renderer
|
|
41
|
+
# (build with {.discourse_renderer}); defaults to a fresh default Renderer
|
|
42
|
+
# @param raise_on_error [Boolean] when true (default), let render-time
|
|
43
|
+
# exceptions propagate; when false, swallow them, return a
|
|
44
|
+
# {Conversion} with an empty +markdown+ string, and surface the
|
|
45
|
+
# exceptions via {Conversion#errors}.
|
|
46
|
+
# @yieldparam ast [AST::Document] mutate before rendering (optional)
|
|
47
|
+
# @return [Conversion]
|
|
48
|
+
def bbcode_to_markdown(input, handlers: nil, renderer: nil, raise_on_error: true)
|
|
49
|
+
parse = parse_bbcode(input, handlers:)
|
|
50
|
+
yield(parse.ast) if block_given?
|
|
51
|
+
build_conversion(parse, renderer:, raise_on_error:)
|
|
29
52
|
end
|
|
30
53
|
|
|
31
|
-
# Parse HTML to AST
|
|
32
|
-
#
|
|
33
|
-
# @param
|
|
34
|
-
#
|
|
54
|
+
# Parse HTML to AST.
|
|
55
|
+
#
|
|
56
|
+
# @param input [String, Nokogiri::XML::Node] HTML source or
|
|
57
|
+
# pre-parsed Nokogiri tree (e.g. the +DocumentFragment+ returned
|
|
58
|
+
# by +Nokogiri::HTML.fragment+). Passing a pre-parsed tree lets
|
|
59
|
+
# callers run their own Nokogiri-driven pre-processing without
|
|
60
|
+
# forcing Markbridge to re-parse the same bytes.
|
|
61
|
+
# @param handlers [Parsers::HTML::HandlerRegistry, nil] custom handlers
|
|
62
|
+
# @return [Parse]
|
|
35
63
|
def parse_html(input, handlers: nil)
|
|
36
|
-
|
|
37
|
-
|
|
64
|
+
raise ArgumentError, "input cannot be nil" if input.nil?
|
|
65
|
+
|
|
66
|
+
parser = Parsers::HTML::Parser.new(handlers:)
|
|
67
|
+
ast = parser.parse(input)
|
|
68
|
+
|
|
69
|
+
Parse.new(ast:, format: :html, unknown_tags: parser.unknown_tags, diagnostics: {})
|
|
38
70
|
end
|
|
39
71
|
|
|
40
|
-
# Convert HTML to Discourse Markdown
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
# Convert HTML to Discourse Markdown.
|
|
73
|
+
#
|
|
74
|
+
# If a block is given, it is called with the parsed AST between
|
|
75
|
+
# parse and render — the caller can append/remove/replace nodes
|
|
76
|
+
# before rendering. Mutations to the yielded AST persist in
|
|
77
|
+
# {Conversion#ast}.
|
|
78
|
+
#
|
|
79
|
+
# @param input [String, Nokogiri::XML::Node] HTML source or
|
|
80
|
+
# pre-parsed Nokogiri tree (see {.parse_html})
|
|
81
|
+
# @param handlers [Parsers::HTML::HandlerRegistry, nil] custom handlers
|
|
82
|
+
# @param renderer [Renderers::Discourse::Renderer, nil] custom renderer
|
|
83
|
+
# @param raise_on_error [Boolean] when true (default), let render-time
|
|
84
|
+
# exceptions propagate; when false, swallow them, return a
|
|
85
|
+
# {Conversion} with an empty +markdown+ string, and surface the
|
|
86
|
+
# exceptions via {Conversion#errors}.
|
|
87
|
+
# @yieldparam ast [AST::Document] mutate before rendering (optional)
|
|
88
|
+
# @return [Conversion]
|
|
89
|
+
def html_to_markdown(input, handlers: nil, renderer: nil, raise_on_error: true)
|
|
90
|
+
parse = parse_html(input, handlers:)
|
|
91
|
+
yield(parse.ast) if block_given?
|
|
92
|
+
build_conversion(parse, renderer:, raise_on_error:)
|
|
48
93
|
end
|
|
49
94
|
|
|
50
|
-
# Parse s9e/TextFormatter XML to AST
|
|
51
|
-
#
|
|
52
|
-
# @param
|
|
53
|
-
#
|
|
95
|
+
# Parse s9e/TextFormatter XML to AST.
|
|
96
|
+
#
|
|
97
|
+
# @param input [String, Nokogiri::XML::Node] XML source or
|
|
98
|
+
# pre-parsed Nokogiri tree. A +Nokogiri::XML::Document+ is
|
|
99
|
+
# unwrapped via +#root+; any other node is treated as the root.
|
|
100
|
+
# @param handlers [Parsers::TextFormatter::HandlerRegistry, nil] custom handlers
|
|
101
|
+
# @return [Parse]
|
|
54
102
|
def parse_text_formatter_xml(input, handlers: nil)
|
|
55
|
-
|
|
56
|
-
|
|
103
|
+
raise ArgumentError, "input cannot be nil" if input.nil?
|
|
104
|
+
|
|
105
|
+
parser = Parsers::TextFormatter::Parser.new(handlers:)
|
|
106
|
+
ast = parser.parse(input)
|
|
107
|
+
unknown_tags = parser.unknown_tags
|
|
108
|
+
|
|
109
|
+
Parse.new(ast:, format: :text_formatter_xml, unknown_tags:, diagnostics: {})
|
|
57
110
|
end
|
|
58
111
|
|
|
59
|
-
# Convert s9e/TextFormatter XML to Discourse Markdown
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
112
|
+
# Convert s9e/TextFormatter XML to Discourse Markdown.
|
|
113
|
+
#
|
|
114
|
+
# If a block is given, it is called with the parsed AST between
|
|
115
|
+
# parse and render — the caller can append/remove/replace nodes
|
|
116
|
+
# before rendering. Mutations to the yielded AST persist in
|
|
117
|
+
# {Conversion#ast}.
|
|
118
|
+
#
|
|
119
|
+
# @param input [String, Nokogiri::XML::Node] XML source or
|
|
120
|
+
# pre-parsed Nokogiri tree (see {.parse_text_formatter_xml})
|
|
121
|
+
# @param handlers [Parsers::TextFormatter::HandlerRegistry, nil] custom handlers
|
|
122
|
+
# @param renderer [Renderers::Discourse::Renderer, nil] custom renderer
|
|
123
|
+
# @param raise_on_error [Boolean] see {.bbcode_to_markdown}
|
|
124
|
+
# @yieldparam ast [AST::Document] mutate before rendering (optional)
|
|
125
|
+
# @return [Conversion]
|
|
126
|
+
def text_formatter_xml_to_markdown(input, handlers: nil, renderer: nil, raise_on_error: true)
|
|
127
|
+
parse = parse_text_formatter_xml(input, handlers:)
|
|
128
|
+
yield(parse.ast) if block_given?
|
|
129
|
+
build_conversion(parse, renderer:, raise_on_error:)
|
|
67
130
|
end
|
|
68
131
|
|
|
69
|
-
# Parse MediaWiki wikitext to AST
|
|
132
|
+
# Parse MediaWiki wikitext to AST.
|
|
133
|
+
#
|
|
70
134
|
# @param input [String] MediaWiki source
|
|
71
|
-
# @param
|
|
72
|
-
# @return [
|
|
73
|
-
def parse_mediawiki(input,
|
|
135
|
+
# @param handlers [Parsers::MediaWiki::InlineTagRegistry, nil] custom inline-tag registry
|
|
136
|
+
# @return [Parse]
|
|
137
|
+
def parse_mediawiki(input, handlers: nil)
|
|
74
138
|
raise ArgumentError, "input cannot be nil" if input.nil?
|
|
75
139
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
140
|
+
parser = Parsers::MediaWiki::Parser.new(handlers:)
|
|
141
|
+
ast = parser.parse(input.to_s)
|
|
142
|
+
|
|
143
|
+
Parse.new(ast:, format: :mediawiki, unknown_tags: parser.unknown_tags, diagnostics: {})
|
|
79
144
|
end
|
|
80
145
|
|
|
81
|
-
# Convert MediaWiki wikitext to Discourse Markdown
|
|
146
|
+
# Convert MediaWiki wikitext to Discourse Markdown.
|
|
147
|
+
#
|
|
148
|
+
# If a block is given, it is called with the parsed AST between
|
|
149
|
+
# parse and render — the caller can append/remove/replace nodes
|
|
150
|
+
# before rendering. Mutations to the yielded AST persist in
|
|
151
|
+
# {Conversion#ast}.
|
|
152
|
+
#
|
|
82
153
|
# @param input [String] MediaWiki source
|
|
83
|
-
# @param
|
|
84
|
-
# @param
|
|
85
|
-
# @
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
154
|
+
# @param handlers [Parsers::MediaWiki::InlineTagRegistry, nil]
|
|
155
|
+
# @param renderer [Renderers::Discourse::Renderer, nil] custom renderer
|
|
156
|
+
# @param raise_on_error [Boolean] see {.bbcode_to_markdown}
|
|
157
|
+
# @yieldparam ast [AST::Document] mutate before rendering (optional)
|
|
158
|
+
# @return [Conversion]
|
|
159
|
+
def mediawiki_to_markdown(input, handlers: nil, renderer: nil, raise_on_error: true)
|
|
160
|
+
parse = parse_mediawiki(input, handlers:)
|
|
161
|
+
yield(parse.ast) if block_given?
|
|
162
|
+
build_conversion(parse, renderer:, raise_on_error:)
|
|
89
163
|
end
|
|
90
164
|
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
165
|
+
# Convert input in the given format. Thin dispatcher over the
|
|
166
|
+
# four +*_to_markdown+ methods; useful when the format is data-
|
|
167
|
+
# driven (e.g. iterating posts whose +:format+ column varies).
|
|
168
|
+
# An optional block is forwarded to the dispatched method.
|
|
169
|
+
#
|
|
170
|
+
# @param input [String, Nokogiri::XML::Node] source content; the
|
|
171
|
+
# HTML and TextFormatter dispatch targets also accept pre-parsed
|
|
172
|
+
# Nokogiri trees.
|
|
173
|
+
# @param format [Symbol] one of +:bbcode+, +:html+,
|
|
174
|
+
# +:text_formatter_xml+, +:mediawiki+
|
|
175
|
+
# @param kwargs [Hash] forwarded to the underlying convenience method
|
|
176
|
+
# (e.g. +handlers:+, +renderer:+, +raise_on_error:+).
|
|
177
|
+
# @yieldparam ast [AST::Document] mutate before rendering (optional)
|
|
178
|
+
# @return [Conversion]
|
|
179
|
+
def convert(input, format:, **kwargs, &block)
|
|
180
|
+
case format
|
|
181
|
+
when :bbcode
|
|
182
|
+
bbcode_to_markdown(input, **kwargs, &block)
|
|
183
|
+
when :html
|
|
184
|
+
html_to_markdown(input, **kwargs, &block)
|
|
185
|
+
when :text_formatter_xml
|
|
186
|
+
text_formatter_xml_to_markdown(input, **kwargs, &block)
|
|
187
|
+
when :mediawiki
|
|
188
|
+
mediawiki_to_markdown(input, **kwargs, &block)
|
|
189
|
+
else
|
|
190
|
+
raise ArgumentError,
|
|
191
|
+
"unknown format #{format.inspect} " \
|
|
192
|
+
"(expected :bbcode, :html, :text_formatter_xml, or :mediawiki)"
|
|
193
|
+
end
|
|
95
194
|
end
|
|
96
195
|
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
196
|
+
# Render a {Parse} or a bare AST node to Discourse Markdown.
|
|
197
|
+
# Useful when the caller has mutated the AST between parse and
|
|
198
|
+
# render (e.g. appending attachments not present in the source),
|
|
199
|
+
# or built an AST programmatically.
|
|
200
|
+
#
|
|
201
|
+
# When given a {Parse}, the returned {Conversion} carries the
|
|
202
|
+
# parser's +unknown_tags+, +diagnostics+, and source +format+
|
|
203
|
+
# forward. When given an AST node, those fields default to empty
|
|
204
|
+
# and +format+ is +nil+ — there was no source document, so there
|
|
205
|
+
# is no source format to report. A bare node that isn't already a
|
|
206
|
+
# {AST::Document} is wrapped in one, so {Conversion#ast} is always
|
|
207
|
+
# a Document (and tree helpers like +each_descendant+ are always
|
|
208
|
+
# available on it).
|
|
209
|
+
#
|
|
210
|
+
# @param parse_or_ast [Parse, AST::Node]
|
|
211
|
+
# @param format [Symbol] :discourse (only renderer currently shipped)
|
|
212
|
+
# @param renderer [Renderers::Discourse::Renderer, nil]
|
|
213
|
+
# @param raise_on_error [Boolean]
|
|
214
|
+
# @return [Conversion]
|
|
215
|
+
def render(parse_or_ast, format: :discourse, renderer: nil, raise_on_error: true)
|
|
216
|
+
raise ArgumentError, "unknown render format #{format.inspect}" unless format == :discourse
|
|
102
217
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
218
|
+
parse =
|
|
219
|
+
case parse_or_ast
|
|
220
|
+
when Parse
|
|
221
|
+
parse_or_ast
|
|
222
|
+
when AST::Document
|
|
223
|
+
Parse.new(ast: parse_or_ast, format: nil, unknown_tags: {}, diagnostics: {})
|
|
224
|
+
when AST::Node
|
|
225
|
+
document = AST::Document.new([parse_or_ast])
|
|
226
|
+
Parse.new(ast: document, format: nil, unknown_tags: {}, diagnostics: {})
|
|
227
|
+
else
|
|
228
|
+
raise ArgumentError, "expected Parse or AST::Node, got #{parse_or_ast.class}"
|
|
229
|
+
end
|
|
108
230
|
|
|
109
|
-
|
|
110
|
-
# @return [Parsers::TextFormatter::HandlerRegistry]
|
|
111
|
-
def default_text_formatter_handlers
|
|
112
|
-
@default_text_formatter_handlers ||= Parsers::TextFormatter::HandlerRegistry.default
|
|
231
|
+
build_conversion(parse, renderer:, raise_on_error:)
|
|
113
232
|
end
|
|
114
233
|
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
234
|
+
# Build a configured Discourse {Renderers::Discourse::Renderer}
|
|
235
|
+
# for use with the +renderer:+ kwarg on the +*_to_markdown+
|
|
236
|
+
# convenience methods.
|
|
237
|
+
#
|
|
238
|
+
# @param tags [Hash{Class => Tag, nil}, nil] mappings to merge on
|
|
239
|
+
# top of the default library; +nil+ values unregister the class.
|
|
240
|
+
# @param tag_library [Renderers::Discourse::TagLibrary, nil] base
|
|
241
|
+
# library to start from. Defaults to a fresh {TagLibrary.default}.
|
|
242
|
+
# When supplied, it is +dup+'d before any +tags:+ / +unregister:+
|
|
243
|
+
# mutation, so the caller's library is left untouched.
|
|
244
|
+
# @param unregister [Array<Class>, nil] AST classes to drop from
|
|
245
|
+
# the library so they fall through to +render_children+.
|
|
246
|
+
# @param escaper [#escape, nil] when given, used as-is; +escape:+,
|
|
247
|
+
# +escape_hard_line_breaks:+, and +allow:+ are then ignored.
|
|
248
|
+
# @param escape [Boolean] when +false+, the renderer is built with
|
|
249
|
+
# {Renderers::Discourse::IdentityEscaper} (no Markdown escaping).
|
|
250
|
+
# Mutually exclusive with +escape_hard_line_breaks:+ / +allow:+.
|
|
251
|
+
# @param escape_hard_line_breaks [Boolean] forwarded to a fresh
|
|
252
|
+
# {MarkdownEscaper} when no explicit +escaper:+ is given.
|
|
253
|
+
# @param allow [Symbol, Array<Symbol>, nil] block-level constructs to
|
|
254
|
+
# pass through unescaped (e.g. +:lists+, +:bullet_list+,
|
|
255
|
+
# +:ordered_list+, +:atx_heading+, +:block_quote+); forwarded to a
|
|
256
|
+
# fresh {MarkdownEscaper}.
|
|
257
|
+
# @param postprocessor [Renderers::Discourse::Postprocessor, nil] when given,
|
|
258
|
+
# used as-is; +strip_trailing_invisibles:+ is then ignored.
|
|
259
|
+
# @param strip_trailing_invisibles [Boolean] forwarded to a fresh
|
|
260
|
+
# {Renderers::Discourse::Postprocessor} when no explicit
|
|
261
|
+
# +postprocessor:+ is given. Strips NBSP and zero-width format
|
|
262
|
+
# characters from the end of each line.
|
|
263
|
+
# @return [Renderers::Discourse::Renderer]
|
|
264
|
+
def discourse_renderer(
|
|
265
|
+
tags: nil,
|
|
266
|
+
tag_library: nil,
|
|
267
|
+
unregister: nil,
|
|
268
|
+
escaper: nil,
|
|
269
|
+
escape: true,
|
|
270
|
+
escape_hard_line_breaks: false,
|
|
271
|
+
allow: nil,
|
|
272
|
+
postprocessor: nil,
|
|
273
|
+
strip_trailing_invisibles: false
|
|
274
|
+
)
|
|
275
|
+
# Dup the caller's library before mutating so successive
|
|
276
|
+
# +discourse_renderer+ calls against the same +tag_library:+ don't
|
|
277
|
+
# see each other's overrides. +TagLibrary.default+ already returns
|
|
278
|
+
# a fresh instance, so the dup is only needed in the explicit
|
|
279
|
+
# +tag_library:+ branch.
|
|
280
|
+
library = tag_library ? tag_library.dup : Renderers::Discourse::TagLibrary.default
|
|
281
|
+
library.merge!(tags) if tags
|
|
282
|
+
Array(unregister).each { |klass| library.unregister(klass) }
|
|
120
283
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def configure
|
|
124
|
-
yield configuration
|
|
125
|
-
end
|
|
284
|
+
escaper ||= build_escaper(escape:, escape_hard_line_breaks:, allow:)
|
|
285
|
+
postprocessor ||= Renderers::Discourse::Postprocessor.new(strip_trailing_invisibles:)
|
|
126
286
|
|
|
127
|
-
|
|
128
|
-
def reset_defaults!
|
|
129
|
-
@default_handlers = nil
|
|
130
|
-
@default_html_handlers = nil
|
|
131
|
-
@default_tag_library = nil
|
|
132
|
-
@default_text_formatter_handlers = nil
|
|
133
|
-
@configuration = nil
|
|
287
|
+
Renderers::Discourse::Renderer.new(tag_library: library, escaper:, postprocessor:)
|
|
134
288
|
end
|
|
135
289
|
|
|
136
290
|
private
|
|
137
291
|
|
|
138
|
-
def
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
292
|
+
def bbcode_diagnostics(parser)
|
|
293
|
+
{
|
|
294
|
+
auto_closed_tags_count: parser.auto_closed_tags_count,
|
|
295
|
+
depth_exceeded_count: parser.depth_exceeded_count,
|
|
296
|
+
unclosed_raw_tags: parser.unclosed_raw_tags,
|
|
297
|
+
}
|
|
143
298
|
end
|
|
144
299
|
|
|
145
|
-
def
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
300
|
+
def build_conversion(parse, renderer:, raise_on_error:)
|
|
301
|
+
renderer ||= Renderers::Discourse::Renderer.new
|
|
302
|
+
markdown, errors = render_through(renderer, parse.ast, raise_on_error:)
|
|
303
|
+
|
|
304
|
+
Conversion.new(parsed: parse, markdown:, errors:)
|
|
149
305
|
end
|
|
150
306
|
|
|
151
|
-
def
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
307
|
+
def build_escaper(escape:, escape_hard_line_breaks:, allow:)
|
|
308
|
+
if escape == false
|
|
309
|
+
if escape_hard_line_breaks || allow
|
|
310
|
+
raise ArgumentError,
|
|
311
|
+
"escape: false is mutually exclusive with " \
|
|
312
|
+
"escape_hard_line_breaks: / allow: (those configure " \
|
|
313
|
+
"MarkdownEscaper, which escape: false replaces wholesale)"
|
|
314
|
+
end
|
|
315
|
+
Renderers::Discourse::IdentityEscaper.new
|
|
316
|
+
else
|
|
317
|
+
Renderers::Discourse::MarkdownEscaper.new(escape_hard_line_breaks:, allow:)
|
|
318
|
+
end
|
|
157
319
|
end
|
|
158
320
|
|
|
159
|
-
def
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
321
|
+
def render_through(renderer, ast, raise_on_error:)
|
|
322
|
+
raw = renderer.render(ast)
|
|
323
|
+
[renderer.postprocessor.call(raw), []]
|
|
324
|
+
rescue StandardError => e
|
|
325
|
+
raise if raise_on_error
|
|
326
|
+
["", [e]]
|
|
164
327
|
end
|
|
165
328
|
end
|
|
166
329
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: markbridge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Discourse Team
|
|
@@ -25,6 +25,7 @@ files:
|
|
|
25
25
|
- lib/markbridge/ast/bold.rb
|
|
26
26
|
- lib/markbridge/ast/code.rb
|
|
27
27
|
- lib/markbridge/ast/color.rb
|
|
28
|
+
- lib/markbridge/ast/details.rb
|
|
28
29
|
- lib/markbridge/ast/document.rb
|
|
29
30
|
- lib/markbridge/ast/element.rb
|
|
30
31
|
- lib/markbridge/ast/email.rb
|
|
@@ -53,10 +54,11 @@ files:
|
|
|
53
54
|
- lib/markbridge/ast/upload.rb
|
|
54
55
|
- lib/markbridge/ast/url.rb
|
|
55
56
|
- lib/markbridge/bbcode.rb
|
|
56
|
-
- lib/markbridge/
|
|
57
|
+
- lib/markbridge/conversion.rb
|
|
57
58
|
- lib/markbridge/gem_loader.rb
|
|
58
59
|
- lib/markbridge/html.rb
|
|
59
60
|
- lib/markbridge/mediawiki.rb
|
|
61
|
+
- lib/markbridge/parse.rb
|
|
60
62
|
- lib/markbridge/parsers/bbcode.rb
|
|
61
63
|
- lib/markbridge/parsers/bbcode/closing_strategies/base.rb
|
|
62
64
|
- lib/markbridge/parsers/bbcode/closing_strategies/reordering.rb
|
|
@@ -102,7 +104,9 @@ files:
|
|
|
102
104
|
- lib/markbridge/parsers/html/handlers/paragraph_handler.rb
|
|
103
105
|
- lib/markbridge/parsers/html/handlers/quote_handler.rb
|
|
104
106
|
- lib/markbridge/parsers/html/handlers/raw_handler.rb
|
|
107
|
+
- lib/markbridge/parsers/html/handlers/self_closing_handler.rb
|
|
105
108
|
- lib/markbridge/parsers/html/handlers/simple_handler.rb
|
|
109
|
+
- lib/markbridge/parsers/html/handlers/span_handler.rb
|
|
106
110
|
- lib/markbridge/parsers/html/handlers/table_cell_handler.rb
|
|
107
111
|
- lib/markbridge/parsers/html/handlers/table_handler.rb
|
|
108
112
|
- lib/markbridge/parsers/html/handlers/table_row_handler.rb
|
|
@@ -126,19 +130,12 @@ files:
|
|
|
126
130
|
- lib/markbridge/parsers/text_formatter/handlers/table_cell_handler.rb
|
|
127
131
|
- lib/markbridge/parsers/text_formatter/handlers/url_handler.rb
|
|
128
132
|
- lib/markbridge/parsers/text_formatter/parser.rb
|
|
129
|
-
- lib/markbridge/processors.rb
|
|
130
|
-
- lib/markbridge/processors/discourse_markdown.rb
|
|
131
|
-
- lib/markbridge/processors/discourse_markdown/code_block_tracker.rb
|
|
132
|
-
- lib/markbridge/processors/discourse_markdown/detectors/base.rb
|
|
133
|
-
- lib/markbridge/processors/discourse_markdown/detectors/event.rb
|
|
134
|
-
- lib/markbridge/processors/discourse_markdown/detectors/mention.rb
|
|
135
|
-
- lib/markbridge/processors/discourse_markdown/detectors/poll.rb
|
|
136
|
-
- lib/markbridge/processors/discourse_markdown/detectors/upload.rb
|
|
137
|
-
- lib/markbridge/processors/discourse_markdown/scanner.rb
|
|
138
133
|
- lib/markbridge/renderers/discourse.rb
|
|
139
134
|
- lib/markbridge/renderers/discourse/builders/list_item_builder.rb
|
|
140
135
|
- lib/markbridge/renderers/discourse/html_escaper.rb
|
|
136
|
+
- lib/markbridge/renderers/discourse/identity_escaper.rb
|
|
141
137
|
- lib/markbridge/renderers/discourse/markdown_escaper.rb
|
|
138
|
+
- lib/markbridge/renderers/discourse/postprocessor.rb
|
|
142
139
|
- lib/markbridge/renderers/discourse/render_context.rb
|
|
143
140
|
- lib/markbridge/renderers/discourse/renderer.rb
|
|
144
141
|
- lib/markbridge/renderers/discourse/rendering_interface.rb
|
|
@@ -149,6 +146,7 @@ files:
|
|
|
149
146
|
- lib/markbridge/renderers/discourse/tags/bold_tag.rb
|
|
150
147
|
- lib/markbridge/renderers/discourse/tags/code_tag.rb
|
|
151
148
|
- lib/markbridge/renderers/discourse/tags/color_tag.rb
|
|
149
|
+
- lib/markbridge/renderers/discourse/tags/details_tag.rb
|
|
152
150
|
- lib/markbridge/renderers/discourse/tags/email_tag.rb
|
|
153
151
|
- lib/markbridge/renderers/discourse/tags/event_tag.rb
|
|
154
152
|
- lib/markbridge/renderers/discourse/tags/heading_tag.rb
|