elisp2any 0.0.7 → 0.0.8

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: 5bf30639582d2ecf42060b4db852d32438545e209b2c2eeac8b23ded371a4d50
4
- data.tar.gz: 0ae7c862c01e4e5cdb0995d2ce31d6fe8b0df253f3e29ffd58fd5bfed580edbb
3
+ metadata.gz: 5a54442cefe9baee337378b71628c7aa3cf833f38028ea8517f56434b58f9a79
4
+ data.tar.gz: 3ab64eaec627d61736f14ca559d93a56d547bd21eb3b38ee6829d2f9158a84ca
5
5
  SHA512:
6
- metadata.gz: 747da66f11028d3da70cc731b5bf60e3ed44a261c19359022a33d3a151611e14df560dae64ec650ecb4cb8e8bc9509164e76f72586a7454d44ddf76805d8c856
7
- data.tar.gz: 63928b7c7b20e1e045159f3457b309e47c9be922c63ce3fda708ac1be98b46c66000052cc7849d157ddce7d8dd1127dc39ba21b2f1a6ea49d9bd3869707c9fca
6
+ metadata.gz: 17dcdd8ccaf1fb4295a32460ef1f5da6e4fcf65ecfdffca48bf53929aa4fa2fa4b6e1c10d00a1d03feec458a8231e28ee63316bff99fa77441f836c456a44a4d
7
+ data.tar.gz: bbcad198b0eaf48a010c72ff7c1b4f717caed16ec2386c48f670f858241a74bdd53b883bb7166dc394eba57de9bbf146321143dbadcfa34ba27815f0d43606c8
data/.envrc ADDED
@@ -0,0 +1,2 @@
1
+ layout ruby
2
+ export LANG=en_US.UTF-8
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.0.8 - 2026-08-05
6
+
7
+ * Add JSON format option (for the Pandoc JSON filter).
8
+
5
9
  ## 0.0.7 - 2026-07-05
6
10
 
7
11
  * Add dump flag for debugging.
data/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Elisp2any
2
2
 
3
+ Project links: [repository](https://codeberg.org/gemmaro/elisp2any),
4
+ [mirror](https://github.com/gemmaro/elisp2any), [RubyGems.org][rg].
5
+
6
+ [rg]: https://rubygems.org/gems/elisp2any
7
+
3
8
  ## Installation
4
9
 
5
10
  Install the gem and add to the application's `Gemfile` by executing `bundle add elisp2any`.
@@ -7,15 +12,32 @@ If Bundler is not being used to manage dependencies, install the gem by executin
7
12
 
8
13
  ## Usage
9
14
 
10
- Currently the command line tool only supports HTML rendering.
15
+ Currently the command line tool supports HTML (default) and JSON rendering.
11
16
 
12
17
  ```shell
13
18
  $ elisp2any --input /path/to/input/file --output /path/to/output/file
14
19
  ```
15
20
 
21
+ The JSON is based off the [Pandoc JSON filter][pf]. The example usage
22
+ is:
23
+
24
+ ```shell
25
+ ./exe/elisp2any \
26
+ --format=json \
27
+ < ~/.emacs.d/init.el \
28
+ | pandoc \
29
+ --from=json \
30
+ --standalone \
31
+ > /tmp/index.html
32
+ ```
33
+
34
+ [pf]: https://pandoc.org/filters.html
35
+
16
36
  ## Development
17
37
 
18
- To run tests, run `test-unit`.
38
+ To run tests, run `test-unit` (or `rake test`).
39
+
40
+ There are a few notes about the terms.
19
41
 
20
42
  Two paragraph types:
21
43
 
@@ -40,7 +62,7 @@ Bug reports and pull requests are welcome.
40
62
 
41
63
  ## License
42
64
 
43
- Copyright (C) 2025 gemmaro
65
+ Copyright (C) 2025, 2026 gemmaro
44
66
 
45
67
  This program is free software: you can redistribute it and/or modify
46
68
  it under the terms of the GNU General Public License as published by
data/Rakefile CHANGED
@@ -6,3 +6,11 @@ task :deploy do
6
6
  File.write("/tmp/index.html", out)
7
7
  sh "rsync", "-av", "/tmp/index.html", "pi:/srv/www/emacs/"
8
8
  end
9
+
10
+ require "rake/testtask"
11
+
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << "test"
14
+ t.libs << "lib"
15
+ t.test_files = FileList["test/**/*_test.rb"]
16
+ end
data/exe/elisp2any CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- # Copyright (C) 2025 gemmaro
3
+ # Copyright (C) 2025, 2026 gemmaro
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ input = $stdin
24
24
  output = $stdout
25
25
  css = nil
26
26
  dump = false
27
+ format = :html
27
28
 
28
29
  OptionParser.new do |parser|
29
30
  parser.on('--input=PATH', 'ELisp file (default: stdin)') do |path|
@@ -38,13 +39,29 @@ OptionParser.new do |parser|
38
39
  css = path
39
40
  end
40
41
 
41
- parser.on("--dump") { dump = true }
42
+ parser.on("--dump", 'For debug purpose') { dump = true }
43
+
44
+ parser.on("--format=NAME", "'json' is for Pandoc JSON filter. Default: HTML") do |name|
45
+ case name
46
+ in "html"
47
+ format = :html
48
+ in "json"
49
+ format = :json
50
+ end
51
+ end
42
52
  end.parse!
43
53
 
54
+ css && format != :html and raise "CSS option is for HTML only"
55
+
44
56
  doc = Elisp.parse(input)
45
57
  if dump
46
58
  pp doc
47
59
  exit
48
60
  end
49
61
 
50
- doc.write(output, css:)
62
+ case format
63
+ in :html
64
+ doc.write(output, css:)
65
+ in :json
66
+ doc.write_pandoc_json(output)
67
+ end
data/lib/elisp/comment.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -25,8 +25,4 @@ class Elisp::Comment
25
25
  def to_minor_para
26
26
  Elisp::MinorPara.new(@content)
27
27
  end
28
-
29
- def html
30
- self.class.parse(@content)
31
- end
32
28
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -13,12 +13,12 @@
13
13
  # You should have received a copy of the GNU General Public License
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
- require "cgi"
16
+ require "cgi/escape"
17
17
  require "uri"
18
18
  require "strscan"
19
19
 
20
20
  class Elisp::DocStringParser
21
- URI_PATTERN = URI.regexp
21
+ URI_PATTERN = URI::RFC2396_PARSER.make_regexp
22
22
  URI_PATTERN_WITH_ANGLES = /[<](?<uri>#{ URI_PATTERN })[>]/
23
23
  EMAIL = Regexp.new(URI::MailTo::EMAIL_REGEXP.to_s
24
24
  .sub(/\A[(][?]-mix:\\A/, "(?-mix:")
@@ -30,38 +30,52 @@ class Elisp::DocStringParser
30
30
  end
31
31
 
32
32
  def html
33
- result = +""
33
+ parse.map(&:html).join
34
+ end
35
+
36
+ def pandoc_json_objects
37
+ parse.map(&:pandoc_json_object)
38
+ end
39
+
40
+ private
41
+
42
+ def parse
43
+ result = []
34
44
  normal = +""
35
45
  until @scanner.eos?
36
46
  if @scanner.skip(/[`](?<code>[A-Za-z!.-]+)[']/)
37
- result << normal
38
- normal.clear
39
- code = CGI.escape_html(@scanner[:code])
40
- result << "<code>#{code}</code>"
41
- normal.clear
47
+ result << Text.new(normal)
48
+ normal = +""
49
+ result << Code.new(@scanner[:code])
50
+
42
51
  elsif @scanner.skip(/\\\\=(?<quote>['`])/)
43
52
  normal << @scanner[:quote]
53
+
44
54
  elsif (uri = scan_http_uri)
45
- result << normal
46
- normal.clear
47
- result << html_url(uri)
55
+ result << Text.new(normal)
56
+ normal = +""
57
+ result << HTMLURL.new(uri)
58
+
48
59
  elsif (address = scan_email)
49
- result << normal
50
- normal.clear
51
- uri = CGI.escape(address)
52
- address = CGI.escape_html(address)
53
- result << %(<a href="mailto:#{uri}">#{address}</a>)
60
+ result << Text.new(normal)
61
+ normal = +""
62
+ result << Email.new(address)
63
+
54
64
  elsif @scanner.skip(/Copyright [(]C[)]/)
55
- result << "Copyright &copy;"
65
+ result << Text.new(normal << "Copyright ") << Copyright.new
66
+ normal = +""
67
+
56
68
  else
57
69
  normal << @scanner.getch
58
70
  end
59
71
  end
60
- result << normal
61
- normal.clear
72
+
73
+ result << Text.new(normal)
62
74
  result
63
75
  end
64
76
 
77
+ private
78
+
65
79
  def scan_email
66
80
  if (address = @scanner.scan(EMAIL))
67
81
  address
@@ -87,10 +101,117 @@ class Elisp::DocStringParser
87
101
  uri
88
102
  end
89
103
 
90
- def html_url(url)
91
- url = url.to_s
92
- ref = CGI.escape(url)
93
- label = CGI.escape_html(url)
94
- %(<a class="pure-url" href="#{ref}">#{label}</a>)
104
+ class Text
105
+ def initialize(content)
106
+ @content = content
107
+ end
108
+
109
+ def html
110
+ CGI.escape_html(@content)
111
+ end
112
+
113
+ def pandoc_json_object
114
+ {
115
+ "t": "Str",
116
+ "c": @content,
117
+ }
118
+ end
119
+ end
120
+
121
+ class Code
122
+ def initialize(content)
123
+ @content = content
124
+ end
125
+
126
+ def html
127
+ code = CGI.escape_html(@content)
128
+ "<code>#{code}</code>"
129
+ end
130
+
131
+ def pandoc_json_object
132
+ {
133
+ "t": "Code",
134
+ "c": [
135
+ ["", [], []],
136
+ @content,
137
+ ]
138
+ }
139
+ end
140
+ end
141
+
142
+ class HTMLURL
143
+ def initialize(content)
144
+ @content = content
145
+ end
146
+
147
+ def html
148
+ url = @content.to_s
149
+ ref = CGI.escape(url)
150
+ label = CGI.escape_html(url)
151
+ %(<a class="pure-url" href="#{ref}">#{label}</a>)
152
+ end
153
+
154
+ def pandoc_json_object
155
+ {
156
+ "t": "Link",
157
+ "c": [
158
+ ["", ["uri"], []],
159
+ [
160
+ {
161
+ "t": "Str",
162
+ "c": @content,
163
+ }
164
+ ],
165
+ [
166
+ @content,
167
+ "",
168
+ ],
169
+ ],
170
+ }
171
+ end
172
+ end
173
+
174
+ class Email
175
+ def initialize(content)
176
+ @content = content
177
+ end
178
+
179
+ def html
180
+ uri = CGI.escape(@content)
181
+ address = CGI.escape_html(@content)
182
+ %(<a href="mailto:#{uri}">#{address}</a>)
183
+ end
184
+
185
+ def pandoc_json_object
186
+ {
187
+ "t": "Link",
188
+ "c": [
189
+ ["", ["email"], []],
190
+ [
191
+ {
192
+ "t": "Str",
193
+ "c": @content,
194
+ }
195
+ ],
196
+ [
197
+ "mailto:#{@content}",
198
+ "",
199
+ ],
200
+ ],
201
+ }
202
+ end
203
+ end
204
+
205
+ class Copyright
206
+ def html
207
+ "&copy;"
208
+ end
209
+
210
+ def pandoc_json_object
211
+ {
212
+ "t": "Str",
213
+ "c": "©",
214
+ }
215
+ end
95
216
  end
96
217
  end
data/lib/elisp/heading.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -13,7 +13,7 @@
13
13
  # You should have received a copy of the GNU General Public License
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
- require "cgi"
16
+ require "cgi/escape"
17
17
 
18
18
  class Elisp::Heading
19
19
  attr_reader :level, :content
@@ -28,4 +28,20 @@ class Elisp::Heading
28
28
  content = CGI.escape_html(@content)
29
29
  "<#{name}>#{content}</#{name}>"
30
30
  end
31
+
32
+ def pandoc_json_object
33
+ {
34
+ "t": "Header",
35
+ "c": [
36
+ @level,
37
+ [@content, [], []],
38
+ [
39
+ {
40
+ "t": "Str",
41
+ "c": @content,
42
+ },
43
+ ],
44
+ ]
45
+ }
46
+ end
31
47
  end
data/lib/elisp/parser.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -13,6 +13,9 @@
13
13
  # You should have received a copy of the GNU General Public License
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
+ require "json"
17
+ require "strscan"
18
+
16
19
  class Elisp::Parser
17
20
  HEADER_LINE = %r{
18
21
  ;;;[ ]
@@ -158,4 +161,17 @@ class Elisp::Parser
158
161
  </html>
159
162
  END_HTML
160
163
  end
164
+
165
+ def pandoc_json_object
166
+ {
167
+ "pandoc-api-version": [1,23,1,1],
168
+ "meta": {},
169
+ "blocks": @nodes.map(&:pandoc_json_object),
170
+ }
171
+ end
172
+
173
+ def write_pandoc_json(output)
174
+ json = JSON.dump(pandoc_json_object)
175
+ output.write(json)
176
+ end
161
177
  end
data/lib/elisp/version.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -14,5 +14,5 @@
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
  class Elisp
17
- VERSION = "0.0.7"
17
+ VERSION = "0.0.8"
18
18
  end
data/lib/elisp.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2025 gemmaro
1
+ # Copyright (C) 2025, 2026 gemmaro
2
2
  #
3
3
  # This program is free software: you can redistribute it and/or modify
4
4
  # it under the terms of the GNU General Public License as published by
@@ -13,10 +13,10 @@
13
13
  # You should have received a copy of the GNU General Public License
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
- require "strscan"
17
- require "cgi"
18
- require "uri"
16
+ require "cgi/escape"
19
17
 
18
+ # +pandoc_json_object+ methods for some classes means the AST for the
19
+ # Pandoc JSON filter.
20
20
  class Elisp
21
21
  Error = Class.new(StandardError)
22
22
 
@@ -27,6 +27,11 @@ end
27
27
 
28
28
  class Elisp::PageDelimiter
29
29
  def html = "<hr>"
30
+ def pandoc_json_object
31
+ {
32
+ "t": "HorizontalRule",
33
+ }
34
+ end
30
35
  end
31
36
 
32
37
  class Elisp::Desc
@@ -38,6 +43,26 @@ class Elisp::Desc
38
43
  content = CGI.escape_html(@content)
39
44
  %(<p class="description">#{content}</p>)
40
45
  end
46
+
47
+ def pandoc_json_object
48
+ {
49
+ "t": "Div",
50
+ "c": [
51
+ ["", ["description"], []],
52
+ [
53
+ {
54
+ "t": "Para",
55
+ "c": [
56
+ {
57
+ "t": "Str",
58
+ "c": @content,
59
+ },
60
+ ],
61
+ },
62
+ ],
63
+ ],
64
+ }
65
+ end
41
66
  end
42
67
 
43
68
  class Elisp::Variables
@@ -54,6 +79,24 @@ class Elisp::Variables
54
79
  </article>
55
80
  END_HTML
56
81
  end
82
+
83
+ def pandoc_json_object
84
+ {
85
+ "t": "Div",
86
+ "c": [
87
+ ["", ["header-line-variables"], []],
88
+ [
89
+ {
90
+ "t": "CodeBlock",
91
+ "c": [
92
+ ["", ["emacs-lisp-header-line-variables"], []],
93
+ @content,
94
+ ],
95
+ },
96
+ ],
97
+ ],
98
+ }
99
+ end
57
100
  end
58
101
 
59
102
  class Elisp::MajorPara
@@ -65,6 +108,16 @@ class Elisp::MajorPara
65
108
  paras = @paras.map(&:html).join("\n")
66
109
  "<article>#{paras}</article>"
67
110
  end
111
+
112
+ def pandoc_json_object
113
+ {
114
+ "t": "Div",
115
+ "c": [
116
+ ["", ["major-para"], []],
117
+ @paras.map(&:pandoc_json_object),
118
+ ],
119
+ }
120
+ end
68
121
  end
69
122
 
70
123
  class Elisp::MinorPara
@@ -76,6 +129,13 @@ class Elisp::MinorPara
76
129
  content = Elisp::DocStringParser.new(@content).html
77
130
  "<pre>#{content}</pre>"
78
131
  end
132
+
133
+ def pandoc_json_object
134
+ {
135
+ "t": "Para",
136
+ "c": Elisp::DocStringParser.new(@content).pandoc_json_objects,
137
+ }
138
+ end
79
139
  end
80
140
 
81
141
  class Elisp::Code
@@ -91,6 +151,16 @@ class Elisp::Code
91
151
  content = CGI.escape_html(@content)
92
152
  %(<pre class="code"><code>#{content}</code></pre>)
93
153
  end
154
+
155
+ def pandoc_json_object
156
+ {
157
+ "t": "CodeBlock",
158
+ "c": [
159
+ ["", ["emacs-lisp"], []],
160
+ @content,
161
+ ],
162
+ }
163
+ end
94
164
  end
95
165
 
96
166
  require_relative "elisp/comment"
data/sample.md ADDED
@@ -0,0 +1,30 @@
1
+ これはページ区切りです:
2
+
3
+ ---
4
+
5
+ これはコードブロックです:
6
+
7
+ ```emacs-lisp
8
+ (message "hello")
9
+ ```
10
+
11
+ これは有塀divです:
12
+
13
+ ::: majorpara
14
+ 段落1つ目。
15
+
16
+ 段落2つ目。
17
+ :::
18
+
19
+ なお、普通の段落はminor paraです。
20
+
21
+ 行内コード`aaa`を確かめます。
22
+
23
+ # これは見出しです
24
+
25
+ 生のHTMLリンク https://example.com です。
26
+ 生のHTMLリンク <https://example.com> です。
27
+
28
+ これは著作情報 Copyright (C) gemmaro です。
29
+
30
+ これは電子メール<gemmaro.dev@gmail.com>です。
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elisp2any
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - gemmaro
@@ -46,6 +46,7 @@ executables:
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
+ - ".envrc"
49
50
  - CHANGELOG.md
50
51
  - Gemfile
51
52
  - LICENSE.txt
@@ -60,6 +61,7 @@ files:
60
61
  - lib/elisp/heading.rb
61
62
  - lib/elisp/parser.rb
62
63
  - lib/elisp/version.rb
64
+ - sample.md
63
65
  homepage: https://codeberg.org/gemmaro/elisp2any
64
66
  licenses:
65
67
  - GPL-3.0-or-later
@@ -85,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  - !ruby/object:Gem::Version
86
88
  version: '0'
87
89
  requirements: []
88
- rubygems_version: 4.0.10
90
+ rubygems_version: 4.0.16
89
91
  specification_version: 4
90
92
  summary: Converter from Emacs Lisp to some document markup
91
93
  test_files: []