pseudohikiparser 0.0.3 → 0.0.4.develop
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.ja.md +132 -8
- data/README.md +134 -10
- data/lib/htmlelement.rb +42 -42
- data/lib/pseudohiki/autolink.rb +60 -0
- data/lib/pseudohiki/blockparser.rb +233 -125
- data/lib/pseudohiki/converter.rb +140 -81
- data/lib/pseudohiki/htmlformat.rb +156 -82
- data/lib/pseudohiki/htmlplugin.rb +9 -28
- data/lib/pseudohiki/inlineparser.rb +21 -24
- data/lib/pseudohiki/markdownformat.rb +94 -98
- data/lib/pseudohiki/plaintextformat.rb +67 -57
- data/lib/pseudohiki/sinatra_helpers.rb +23 -0
- data/lib/pseudohiki/treestack.rb +4 -4
- data/lib/pseudohiki/utils.rb +1 -2
- data/lib/pseudohiki/version.rb +1 -1
- data/lib/pseudohikiparser.rb +49 -28
- data/test/test_autolink.rb +104 -0
- data/test/test_blockparser.rb +78 -11
- data/test/test_htmlformat.rb +436 -0
- data/test/test_htmlplugin.rb +43 -0
- data/test/test_markdownformat.rb +156 -3
- data/test/test_plaintextformat.rb +85 -0
- data/test/test_pseudohiki2html.rb +82 -0
- data/test/test_pseudohikiparser.rb +286 -0
- data/test/test_utils.rb +1 -1
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 685e26157a454005d4d71337bbe18cac722efa11
|
4
|
+
data.tar.gz: a8edea51f0aa148d8e78647b0f36702226c742f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b8daca9efc17ba0da4cb70aa5e6f44960ee6e2b82205e84e690106e765655c75079d49033b929a8f77e0e8db5be4df1216ce1bc0ba602ce4a81f9d9c22802f0
|
7
|
+
data.tar.gz: 913060555b63ba9f2aff1e98ef2ee025a64dc442270a70285f9626ea87196be665bac45731c018e251cf9d86fe237844d3ba1c2b53fb8218e6772ddc247345ca
|
data/README.ja.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PseudoHikiParser
|
2
2
|
================
|
3
3
|
|
4
|
-
PseudoHikiParserは[Hiki](
|
4
|
+
PseudoHikiParserは[Hiki](https://github.com/hiki/hikidoc)に似た記法で書かれたテキストをHTML・Markdownその他のファイル形式に変換するコンバータです。
|
5
5
|
|
6
6
|
このツールは次の目的を念頭において作成中です。
|
7
7
|
|
@@ -148,6 +148,45 @@ The first paragraph
|
|
148
148
|
|
149
149
|
HtmlFormat以外にはXhtmlFormat、Xhtml5Format、PlainTextFormat、MarkDownFormatが用意されています。
|
150
150
|
|
151
|
+
#### WikiNames
|
152
|
+
|
153
|
+
もしWikiNameを利用したければ、PseudoHiki::AutoLink::[WikiName](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/autolink.rb#L11)クラスのインスタンスをBlockParser.newの引数、もしくはBlockParser.parseの第2引数として渡してやる必要があります。
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
require 'pseudohiki/blockparser'
|
157
|
+
require 'pseudohiki/htmlformat'
|
158
|
+
require 'pseudohiki/autolink' # PseudoHiki::AutoLink::WikiName is defined in this file.
|
159
|
+
|
160
|
+
text = <<TEXT
|
161
|
+
a line with an ^EscapedWikiName and a WikiName.
|
162
|
+
TEXT
|
163
|
+
|
164
|
+
puts "--- with default options:"
|
165
|
+
wiki_name_link = PseudoHiki::AutoLink::WikiName.new
|
166
|
+
tree = PseudoHiki::BlockParser.parse(text, wiki_name_link)
|
167
|
+
puts PseudoHiki::XhtmlFormat.format(tree)
|
168
|
+
|
169
|
+
puts "--- when :escape_wiki_name option is set to true:"
|
170
|
+
escape_wiki_name_link = PseudoHiki::AutoLink::WikiName.new({:escape_wiki_name => true})
|
171
|
+
escaped_tree = PseudoHiki::BlockParser.parse(text, escape_wiki_name_link)
|
172
|
+
puts PseudoHiki::XhtmlFormat.format(escaped_tree)
|
173
|
+
```
|
174
|
+
|
175
|
+
は次のように出力します。
|
176
|
+
|
177
|
+
```
|
178
|
+
--- with default options:
|
179
|
+
<p>
|
180
|
+
a line with an ^<a href="EscapedWikiName">EscapedWikiName</a> and a <a href="WikiName">WikiName</a>.
|
181
|
+
</p>
|
182
|
+
--- when :escape_wiki_name option is set to true:
|
183
|
+
<p>
|
184
|
+
a line with an EscapedWikiName and a <a href="WikiName">WikiName</a>.
|
185
|
+
</p>
|
186
|
+
```
|
187
|
+
|
188
|
+
またもしデフォルトの動作が気に入らなければ、AutoLink::[WikiName](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/autolink.rb#L11)を置き換えるクラスあるいはモジュールを用意することもできます。
|
189
|
+
|
151
190
|
### PseudoHiki::Formatクラス
|
152
191
|
|
153
192
|
PseudoHiki::BlockParser.parseで作られた構文木を使い回す必要がなければ、以下のPseudoHiki::Formatのクラスメソッドも利用可能です。
|
@@ -176,12 +215,12 @@ TEXT
|
|
176
215
|
puts PseudoHiki::Format.to_html(hiki_text)
|
177
216
|
```
|
178
217
|
|
179
|
-
## オリジナルの[Hiki記法](
|
218
|
+
## オリジナルの[Hiki記法](https://github.com/hiki/hikidoc/blob/master/TextFormattingRules.ja.md)にある機能の実装状況
|
180
219
|
|
181
220
|
* パラグラフ - 使いものになる
|
182
221
|
* リンク
|
183
|
-
* WikiNames -
|
184
|
-
* ページへのリンク -
|
222
|
+
* WikiNames - オプションとして提供されているが十分にテストされていない
|
223
|
+
* ページへのリンク - 未サポート
|
185
224
|
* 任意のURLへのリンク - 一応使えるはず
|
186
225
|
* 整形済みテキスト - 使いものになる
|
187
226
|
* 文字の修飾 - 一部をサポート
|
@@ -254,7 +293,7 @@ And {{ and }} sould be rendered as two left curly braces and two right curly bra
|
|
254
293
|
|
255
294
|
```html
|
256
295
|
<a href="http://www.example.org/image.png"><img alt="thumbnail of an image" src="http://www.example.org/image_thumb.png">
|
257
|
-
</a
|
296
|
+
</a>
|
258
297
|
```
|
259
298
|
|
260
299
|
### 実験的な機能
|
@@ -287,13 +326,87 @@ paragraph
|
|
287
326
|
</div>
|
288
327
|
```
|
289
328
|
|
329
|
+
#### セクションの定義
|
330
|
+
|
331
|
+
ドキュメントの一部を`//@begin[section\_name]`と`//@end[section\_name]`で囲むと、HtmlFormatとその派生クラスではこれらのタグが classまたはid属性の設定された\<div\>あるいは\<section\>要素に変換されます。
|
332
|
+
|
333
|
+
```
|
334
|
+
!! title
|
335
|
+
|
336
|
+
paragraph 0
|
337
|
+
|
338
|
+
//@begin[main-part]
|
339
|
+
|
340
|
+
!!! main part subtitle 1
|
341
|
+
|
342
|
+
paragraph 1
|
343
|
+
|
344
|
+
!!! main part subtitle 2
|
345
|
+
|
346
|
+
paragraph 2
|
347
|
+
|
348
|
+
//@end[main-part]
|
349
|
+
|
350
|
+
//@begin[additional-part]
|
351
|
+
|
352
|
+
!!! additional part subtitle
|
353
|
+
|
354
|
+
paragraph 3
|
355
|
+
|
356
|
+
//@end[additional-part]
|
357
|
+
|
358
|
+
```
|
359
|
+
|
360
|
+
は次のように変換されます。
|
361
|
+
|
362
|
+
```html
|
363
|
+
<div class="section h2">
|
364
|
+
<h2> title
|
365
|
+
</h2>
|
366
|
+
<p>
|
367
|
+
paragraph 0
|
368
|
+
</p>
|
369
|
+
<div class="section main-part">
|
370
|
+
<div class="section h3">
|
371
|
+
<h3> main part subtitle 1
|
372
|
+
</h3>
|
373
|
+
<p>
|
374
|
+
paragraph 1
|
375
|
+
</p>
|
376
|
+
<!-- end of section h3 -->
|
377
|
+
</div>
|
378
|
+
<div class="section h3">
|
379
|
+
<h3> main part subtitle 2
|
380
|
+
</h3>
|
381
|
+
<p>
|
382
|
+
paragraph 2
|
383
|
+
</p>
|
384
|
+
<!-- end of section h3 -->
|
385
|
+
</div>
|
386
|
+
<!-- end of section main-part -->
|
387
|
+
</div>
|
388
|
+
<div class="section additional-part">
|
389
|
+
<div class="section h3">
|
390
|
+
<h3> additional part subtitle
|
391
|
+
</h3>
|
392
|
+
<p>
|
393
|
+
paragraph 3
|
394
|
+
</p>
|
395
|
+
<!-- end of section h3 -->
|
396
|
+
</div>
|
397
|
+
<!-- end of section additional-part -->
|
398
|
+
</div>
|
399
|
+
<!-- end of section h2 -->
|
400
|
+
</div>
|
401
|
+
```
|
402
|
+
|
290
403
|
### 未実装の機能
|
291
404
|
|
292
405
|
## Visitorクラス
|
293
406
|
|
294
407
|
以下のクラスのうちの一部は、部分的にしか実装されていないかテストが十分ではないことにご注意ください。
|
295
408
|
|
296
|
-
### [HtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L8), [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
409
|
+
### [HtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L8), [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L312)
|
297
410
|
|
298
411
|
これらのクラスのクラスメソッド(HtmlFormat|XhtmlFormat).formatは[HtmlElement](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/htmlelement.rb)オブジェクトを木にしたものを返すため、以下の例のように後から手を加えることができます。
|
299
412
|
|
@@ -337,11 +450,11 @@ paragraph 2 that contains <a class="pdf" href="http://www.example.org/example.pd
|
|
337
450
|
</div>
|
338
451
|
```
|
339
452
|
|
340
|
-
### [Xhtml5Format](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
453
|
+
### [Xhtml5Format](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L318)
|
341
454
|
|
342
455
|
HTML5への変換用のVisitorクラスです。
|
343
456
|
|
344
|
-
現時点では\<section\>要素の扱い以外に[XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
457
|
+
現時点では\<section\>要素の扱い以外に[XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L312)との違いは余りありません。
|
345
458
|
|
346
459
|
### [PlainTextFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/plaintextformat.rb)
|
347
460
|
|
@@ -433,3 +546,14 @@ The first paragraph
|
|
433
546
|
|_cell 1_|cell2 |
|
434
547
|
```
|
435
548
|
|
549
|
+
#### 制限事項
|
550
|
+
|
551
|
+
このVisitorクラスではきちんと構成されていないリストを変換できません。リストの項目は階層に従った入れ子になっていなければならず、もし入れ子のレベルに飛びがあると変換結果がおかしくなります。
|
552
|
+
|
553
|
+
以下が最初のレベルを飛ばしてしまいきちんと構成されていないリストの例です。
|
554
|
+
|
555
|
+
```
|
556
|
+
**First item
|
557
|
+
**Second item
|
558
|
+
```
|
559
|
+
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PseudoHikiParser
|
2
2
|
================
|
3
3
|
|
4
|
-
PseudoHikiParser is a converter of texts written in a [Hiki](
|
4
|
+
PseudoHikiParser is a converter of texts written in a [Hiki](https://github.com/hiki/hikidoc) like notation, into HTML, Markdown or other formats.
|
5
5
|
|
6
6
|
I am writing this tool with following objectives in mind,
|
7
7
|
|
@@ -148,6 +148,45 @@ In the example above, HtmlFormat is a visitor class that converts the parsed tex
|
|
148
148
|
|
149
149
|
Other than HtmlFormat, XhtmlFormat, Xhtml5Format, PlainTextFormat and MarkDownFormat are available.
|
150
150
|
|
151
|
+
#### WikiNames
|
152
|
+
|
153
|
+
If you want to use WikiNames, you have to pass an instance of PseudoHiki::AutoLink::[WikiName](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/autolink.rb#L11) as the argument of BlockParser.new or the second argument of BlockParser.parse.
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
require 'pseudohiki/blockparser'
|
157
|
+
require 'pseudohiki/htmlformat'
|
158
|
+
require 'pseudohiki/autolink' # PseudoHiki::AutoLink::WikiName is defined in this file.
|
159
|
+
|
160
|
+
text = <<TEXT
|
161
|
+
a line with an ^EscapedWikiName and a WikiName.
|
162
|
+
TEXT
|
163
|
+
|
164
|
+
puts "--- with default options:"
|
165
|
+
wiki_name_link = PseudoHiki::AutoLink::WikiName.new
|
166
|
+
tree = PseudoHiki::BlockParser.parse(text, wiki_name_link)
|
167
|
+
puts PseudoHiki::XhtmlFormat.format(tree)
|
168
|
+
|
169
|
+
puts "--- when :escape_wiki_name option is set to true:"
|
170
|
+
escape_wiki_name_link = PseudoHiki::AutoLink::WikiName.new({:escape_wiki_name => true})
|
171
|
+
escaped_tree = PseudoHiki::BlockParser.parse(text, escape_wiki_name_link)
|
172
|
+
puts PseudoHiki::XhtmlFormat.format(escaped_tree)
|
173
|
+
```
|
174
|
+
|
175
|
+
will print
|
176
|
+
|
177
|
+
```
|
178
|
+
--- with default options:
|
179
|
+
<p>
|
180
|
+
a line with an ^<a href="EscapedWikiName">EscapedWikiName</a> and a <a href="WikiName">WikiName</a>.
|
181
|
+
</p>
|
182
|
+
--- when :escape_wiki_name option is set to true:
|
183
|
+
<p>
|
184
|
+
a line with an EscapedWikiName and a <a href="WikiName">WikiName</a>.
|
185
|
+
</p>
|
186
|
+
```
|
187
|
+
|
188
|
+
And if you don't like the default behavior, you may prepare a class/module that substitutes AutoLink::[WikiName](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/autolink.rb#L11).
|
189
|
+
|
151
190
|
### class PseudoHiki::Format
|
152
191
|
|
153
192
|
If you don't need to reuse a tree parsed by PseudoHiki::BlockParser.parse, you can use following class methods of PseudoHiki::Format.
|
@@ -176,12 +215,12 @@ TEXT
|
|
176
215
|
puts PseudoHiki::Format.to_html(hiki_text)
|
177
216
|
```
|
178
217
|
|
179
|
-
## Development status of features from the original [Hiki notation](
|
218
|
+
## Development status of features from the original [Hiki notation](https://github.com/hiki/hikidoc/blob/master/TextFormattingRules.md)
|
180
219
|
|
181
220
|
* Paragraphs - Usable
|
182
221
|
* Links
|
183
|
-
* WikiNames -
|
184
|
-
* Linking to other Wiki pages - Not supported
|
222
|
+
* WikiNames - Provided as an option but not tested well
|
223
|
+
* Linking to other Wiki pages - Not supported
|
185
224
|
* Linking to an arbitrary URL - Maybe usable
|
186
225
|
* Preformatted text - Usable
|
187
226
|
* Text decoration - Partly supported
|
@@ -254,12 +293,12 @@ will be rendered as
|
|
254
293
|
|
255
294
|
```html
|
256
295
|
<a href="http://www.example.org/image.png"><img alt="thumbnail of an image" src="http://www.example.org/image_thumb.png">
|
257
|
-
</a
|
296
|
+
</a>
|
258
297
|
```
|
259
298
|
|
260
299
|
### Experimental
|
261
300
|
|
262
|
-
The following
|
301
|
+
The following features are just experimental and available only in [develop branch](https://github.com/nico-hn/PseudoHikiParser/tree/develop).
|
263
302
|
|
264
303
|
#### Decorator for blocks
|
265
304
|
|
@@ -274,7 +313,7 @@ For example,
|
|
274
313
|
paragraph
|
275
314
|
```
|
276
315
|
|
277
|
-
will be
|
316
|
+
will be rendered as
|
278
317
|
|
279
318
|
```html
|
280
319
|
<div class="class_name">
|
@@ -287,13 +326,87 @@ paragraph
|
|
287
326
|
</div>
|
288
327
|
```
|
289
328
|
|
329
|
+
#### Defining sections
|
330
|
+
|
331
|
+
When a certain part of a document is enclosed by `//@begin[section\_name]` and `//@end[section\_name]`, HtmlFormat and its subclasses will convert the tags into \<div\> or \<section\> elements with id or class attributes.
|
332
|
+
|
333
|
+
```
|
334
|
+
!! title
|
335
|
+
|
336
|
+
paragraph 0
|
337
|
+
|
338
|
+
//@begin[main-part]
|
339
|
+
|
340
|
+
!!! main part subtitle 1
|
341
|
+
|
342
|
+
paragraph 1
|
343
|
+
|
344
|
+
!!! main part subtitle 2
|
345
|
+
|
346
|
+
paragraph 2
|
347
|
+
|
348
|
+
//@end[main-part]
|
349
|
+
|
350
|
+
//@begin[additional-part]
|
351
|
+
|
352
|
+
!!! additional part subtitle
|
353
|
+
|
354
|
+
paragraph 3
|
355
|
+
|
356
|
+
//@end[additional-part]
|
357
|
+
|
358
|
+
```
|
359
|
+
|
360
|
+
will be rendered as
|
361
|
+
|
362
|
+
```html
|
363
|
+
<div class="section h2">
|
364
|
+
<h2> title
|
365
|
+
</h2>
|
366
|
+
<p>
|
367
|
+
paragraph 0
|
368
|
+
</p>
|
369
|
+
<div class="section main-part">
|
370
|
+
<div class="section h3">
|
371
|
+
<h3> main part subtitle 1
|
372
|
+
</h3>
|
373
|
+
<p>
|
374
|
+
paragraph 1
|
375
|
+
</p>
|
376
|
+
<!-- end of section h3 -->
|
377
|
+
</div>
|
378
|
+
<div class="section h3">
|
379
|
+
<h3> main part subtitle 2
|
380
|
+
</h3>
|
381
|
+
<p>
|
382
|
+
paragraph 2
|
383
|
+
</p>
|
384
|
+
<!-- end of section h3 -->
|
385
|
+
</div>
|
386
|
+
<!-- end of section main-part -->
|
387
|
+
</div>
|
388
|
+
<div class="section additional-part">
|
389
|
+
<div class="section h3">
|
390
|
+
<h3> additional part subtitle
|
391
|
+
</h3>
|
392
|
+
<p>
|
393
|
+
paragraph 3
|
394
|
+
</p>
|
395
|
+
<!-- end of section h3 -->
|
396
|
+
</div>
|
397
|
+
<!-- end of section additional-part -->
|
398
|
+
</div>
|
399
|
+
<!-- end of section h2 -->
|
400
|
+
</div>
|
401
|
+
```
|
402
|
+
|
290
403
|
### Not Implemented Yet
|
291
404
|
|
292
405
|
## Visitor classes
|
293
406
|
|
294
407
|
Please note that some of the following classes are implemented partly or not tested well.
|
295
408
|
|
296
|
-
### [HtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L8), [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
409
|
+
### [HtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L8), [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L312)
|
297
410
|
|
298
411
|
Their class method (HtmlFormat|XhtmlFormat).format returns a tree of [HtmlElement](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/htmlelement.rb) objects, and you can traverse the tree as in the following example.
|
299
412
|
|
@@ -337,11 +450,11 @@ paragraph 2 that contains <a class="pdf" href="http://www.example.org/example.pd
|
|
337
450
|
</div>
|
338
451
|
```
|
339
452
|
|
340
|
-
### [Xhtml5Format](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
453
|
+
### [Xhtml5Format](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L318)
|
341
454
|
|
342
455
|
This visitor is for HTML5.
|
343
456
|
|
344
|
-
Currently there aren't many differences with [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#
|
457
|
+
Currently there aren't many differences with [XhtmlFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/htmlformat.rb#L312) except for the handling of \<section\> elements.
|
345
458
|
|
346
459
|
### [PlainTextFormat](https://github.com/nico-hn/PseudoHikiParser/blob/develop/lib/pseudohiki/plaintextformat.rb)
|
347
460
|
|
@@ -433,3 +546,14 @@ The first paragraph
|
|
433
546
|
|_cell 1_|cell2 |
|
434
547
|
```
|
435
548
|
|
549
|
+
#### Limitations
|
550
|
+
|
551
|
+
You can not convert malformed lists with this visitor class. That means list items must be nested hierarchically and if you skip a level in the sequence of items, the result of coversions will be corrupted.
|
552
|
+
|
553
|
+
The following is an example of malformed list in which the first level is skipped:
|
554
|
+
|
555
|
+
```
|
556
|
+
**First item
|
557
|
+
**Second item
|
558
|
+
```
|
559
|
+
|
data/lib/htmlelement.rb
CHANGED
@@ -24,8 +24,8 @@ class HtmlElement
|
|
24
24
|
LATIN1 = "ISO-8859-1"
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
"http://www.w3.org/TR/html4/loose.dtd">'.
|
27
|
+
@doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
28
|
+
"http://www.w3.org/TR/html4/loose.dtd">'.gsub(/\r?\n/o, $/) + $/
|
29
29
|
|
30
30
|
ESC = {
|
31
31
|
'&' => '&',
|
@@ -35,9 +35,9 @@ class HtmlElement
|
|
35
35
|
}
|
36
36
|
|
37
37
|
DECODE = ESC.invert
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
@char_entity_pat = /#{DECODE.keys.join("|")}/
|
39
|
+
|
40
|
+
HTML5_TAGS = %w(article section hgroup aside nav menu header footer figure details legend)
|
41
41
|
|
42
42
|
ELEMENT_TYPES = {
|
43
43
|
:BLOCK => %w(html body div table colgroup thead tbody ul ol dl head p pre blockquote style),
|
@@ -45,40 +45,40 @@ class HtmlElement
|
|
45
45
|
:LIST_ITEM_TYPE_BLOCK => %w(li col),
|
46
46
|
:EMPTY_BLOCK => %w(img meta link base input hr)
|
47
47
|
}
|
48
|
-
|
48
|
+
|
49
49
|
ELEMENTS_FORMAT = {
|
50
|
-
:INLINE => "<%s%s>%s</%s>",
|
51
|
-
:BLOCK => "<%s%s>#{$/}%s</%s>#{$/}",
|
52
|
-
:HEADING_TYPE_BLOCK => "<%s%s>%s</%s>#{$/}",
|
53
|
-
:LIST_ITEM_TYPE_BLOCK => "<%s%s>%s#{$/}",
|
54
|
-
:EMPTY_BLOCK => "<%s%s>#{$/}"
|
50
|
+
:INLINE => "<%1$s%2$s>%3$s</%1$s>",
|
51
|
+
:BLOCK => "<%1$s%2$s>#{$/}%3$s</%1$s>#{$/}",
|
52
|
+
:HEADING_TYPE_BLOCK => "<%1$s%2$s>%3$s</%1$s>#{$/}",
|
53
|
+
:LIST_ITEM_TYPE_BLOCK => "<%1$s%2$s>%3$s#{$/}",
|
54
|
+
:EMPTY_BLOCK => "<%1$s%2$s>#{$/}"
|
55
55
|
}
|
56
56
|
|
57
57
|
attr_reader :tagname
|
58
58
|
attr_accessor :parent, :children
|
59
59
|
|
60
60
|
def self.doctype(encoding="UTF-8")
|
61
|
-
|
61
|
+
format(@doctype, encoding)
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.create(tagname, content=nil, attributes={})
|
65
|
-
if self::
|
65
|
+
if self::HTML5_TAGS.include? tagname
|
66
66
|
attributes["class"] = tagname
|
67
67
|
tagname = "div"
|
68
68
|
end
|
69
|
-
|
69
|
+
new(tagname, content, attributes)
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
72
|
+
def self.comment(content)
|
73
73
|
"<!-- #{content} -->#{$/}"
|
74
74
|
end
|
75
75
|
|
76
|
-
def
|
77
|
-
str.toutf8.gsub(/[^\w\.\-]/o) {|utf8_char| utf8_char.unpack("C*").map {|b| '%%%02X'
|
76
|
+
def self.urlencode(str)
|
77
|
+
str.toutf8.gsub(/[^\w\.\-]/o) {|utf8_char| utf8_char.unpack("C*").map {|b| format('%%%02X', b) }.join }
|
78
78
|
end
|
79
79
|
|
80
|
-
def
|
81
|
-
utf = str.gsub(/%\w\w/) {|ch| [ch[-2,2]].pack('H*') }.toutf8
|
80
|
+
def self.urldecode(str)
|
81
|
+
utf = str.gsub(/%\w\w/) {|ch| [ch[-2, 2]].pack('H*') }.toutf8
|
82
82
|
return utf.tosjis if $KCODE =~ /^s/io
|
83
83
|
return utf.toeuc if $KCODE =~ /^e/io
|
84
84
|
utf
|
@@ -93,15 +93,15 @@ class HtmlElement
|
|
93
93
|
tagformats
|
94
94
|
end
|
95
95
|
|
96
|
-
def
|
96
|
+
def self.escape(str)
|
97
97
|
str.gsub(/[&"<>]/o) {|pat| ESC[pat] }
|
98
98
|
end
|
99
99
|
|
100
|
-
def
|
101
|
-
str.gsub(
|
100
|
+
def self.decode(str)
|
101
|
+
str.gsub(@char_entity_pat) {|ent| DECODE[ent] }
|
102
102
|
end
|
103
103
|
|
104
|
-
TagFormats =
|
104
|
+
TagFormats = assign_tagformats
|
105
105
|
|
106
106
|
def initialize(tagname, content=nil, attributes={})
|
107
107
|
@parent = nil
|
@@ -133,25 +133,25 @@ class HtmlElement
|
|
133
133
|
def [](attribute)
|
134
134
|
@attributes[attribute]
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
def format_attributes
|
138
|
-
@attributes.collect do |attr,value|
|
139
|
-
|
138
|
+
@attributes.collect do |attr, value|
|
139
|
+
" #{attr}=\"#{HtmlElement.escape(value.to_s)}\""
|
140
140
|
end.sort.join
|
141
141
|
end
|
142
142
|
private :format_attributes
|
143
143
|
|
144
144
|
def add_end_comment_for_div_or_section
|
145
145
|
if @tagname == "div" or @tagname == "section" and @end_comment_not_added
|
146
|
-
id_or_class = self["id"]||self["class"]
|
147
|
-
|
146
|
+
id_or_class = self["id"] || self["class"]
|
147
|
+
push HtmlElement.comment("end of #{id_or_class}") if id_or_class
|
148
148
|
@end_comment_not_added = false
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
152
|
def to_s
|
153
153
|
add_end_comment_for_div_or_section
|
154
|
-
self.class::TagFormats[@tagname]
|
154
|
+
format(self.class::TagFormats[@tagname], @tagname, format_attributes, @children)
|
155
155
|
end
|
156
156
|
alias to_str to_s
|
157
157
|
|
@@ -160,26 +160,26 @@ class HtmlElement
|
|
160
160
|
@children.traverse(&block)
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
class XhtmlElement < HtmlElement
|
165
|
-
|
165
|
+
@doctype = '<?xml version="1.0" encoding="%s"?>
|
166
166
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
167
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.
|
167
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.gsub(/\r?\n/o, $/) + $/
|
168
168
|
|
169
|
-
ELEMENTS_FORMAT =
|
170
|
-
ELEMENTS_FORMAT[:LIST_ITEM_TYPE_BLOCK] = "<%s%s>%s</%s>#{$/}"
|
171
|
-
ELEMENTS_FORMAT[:EMPTY_BLOCK] = "<%s%s />#{$/}"
|
169
|
+
ELEMENTS_FORMAT = superclass::ELEMENTS_FORMAT.dup
|
170
|
+
ELEMENTS_FORMAT[:LIST_ITEM_TYPE_BLOCK] = "<%1$s%2$s>%3$s</%1$s>#{$/}"
|
171
|
+
ELEMENTS_FORMAT[:EMPTY_BLOCK] = "<%1$s%2$s />#{$/}"
|
172
172
|
|
173
|
-
TagFormats =
|
173
|
+
TagFormats = assign_tagformats
|
174
174
|
end
|
175
175
|
|
176
176
|
class Xhtml5Element < XhtmlElement
|
177
|
-
|
178
|
-
<!DOCTYPE html>'.
|
177
|
+
@doctype = '<?xml version="1.0" encoding="%s"?>
|
178
|
+
<!DOCTYPE html>'.gsub(/\r?\n/o, $/) + $/
|
179
179
|
|
180
|
-
ELEMENT_TYPES =
|
181
|
-
ELEMENT_TYPES[:BLOCK] =
|
182
|
-
|
180
|
+
ELEMENT_TYPES = superclass::ELEMENT_TYPES.dup
|
181
|
+
ELEMENT_TYPES[:BLOCK] = superclass::ELEMENT_TYPES[:BLOCK] + superclass::HTML5_TAGS
|
182
|
+
HTML5_TAGS = %w(main)
|
183
183
|
|
184
|
-
TagFormats =
|
184
|
+
TagFormats = assign_tagformats
|
185
185
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pseudohiki/blockparser'
|
4
|
+
|
5
|
+
module PseudoHiki
|
6
|
+
module AutoLink
|
7
|
+
# WIKI_NAME_RE is borrowed from hikidoc
|
8
|
+
WIKI_NAME_RE = /\^?\b(?:[A-Z]+[a-z\d]+){2,}\b/
|
9
|
+
ESCAPE_CHAR = "^"
|
10
|
+
|
11
|
+
class WikiName
|
12
|
+
@default_options = {
|
13
|
+
:url => true,
|
14
|
+
:wiki_name => true,
|
15
|
+
:escape_wiki_name => true
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.default_options
|
19
|
+
@default_options
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(options={})
|
23
|
+
@options = WikiName.default_options.dup.merge!(options)
|
24
|
+
@auto_linker = @options[:url] ? URL : Off
|
25
|
+
end
|
26
|
+
|
27
|
+
def auto_link_url?
|
28
|
+
@options[:url]
|
29
|
+
end
|
30
|
+
|
31
|
+
def escaped_wiki_name?(wiki_name)
|
32
|
+
@options[:escape_wiki_name] and wiki_name.start_with?(ESCAPE_CHAR)
|
33
|
+
end
|
34
|
+
|
35
|
+
def in_link_tag?(preceding_str)
|
36
|
+
URL.in_link_tag?(preceding_str)
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_tag(url)
|
40
|
+
if escaped_wiki_name?(url)
|
41
|
+
url[1..-1]
|
42
|
+
elsif url.start_with?(ESCAPE_CHAR)
|
43
|
+
"^[[#{url[1..-1]}]]"
|
44
|
+
else
|
45
|
+
"[[#{url}]]"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def link_wiki_name(line)
|
50
|
+
return line if WIKI_NAME_RE !~ line or VERBATIM_LEAF_HEAD_RE =~ line
|
51
|
+
line.gsub(WIKI_NAME_RE) {|url| in_link_tag?($`) ? url : add_tag(url) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def link(line)
|
55
|
+
line = @auto_linker.link(line)
|
56
|
+
@options[:wiki_name] ? link_wiki_name(line) : line
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|