repubmark 0.0.0

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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +46 -0
  3. data/.rubocop_todo.yml +129 -0
  4. data/.yardopts +4 -0
  5. data/LICENSE +21 -0
  6. data/README.md +21 -0
  7. data/Rakefile +60 -0
  8. data/examples/config.yml +71 -0
  9. data/examples/full.chapters.json +22 -0
  10. data/examples/full.gmi +44 -0
  11. data/examples/full.html +114 -0
  12. data/examples/full.repub +91 -0
  13. data/examples/full.summary.txt +2 -0
  14. data/examples/hello.chapters.json +3 -0
  15. data/examples/hello.gmi +1 -0
  16. data/examples/hello.html +5 -0
  17. data/examples/hello.repub +3 -0
  18. data/examples/hello.summary.txt +1 -0
  19. data/exe/repubmark +46 -0
  20. data/lib/repubmark/config.rb +53 -0
  21. data/lib/repubmark/elems/abbrev.rb +52 -0
  22. data/lib/repubmark/elems/annotation.rb +48 -0
  23. data/lib/repubmark/elems/article.rb +96 -0
  24. data/lib/repubmark/elems/base.rb +104 -0
  25. data/lib/repubmark/elems/blockquote.rb +80 -0
  26. data/lib/repubmark/elems/canvas.rb +104 -0
  27. data/lib/repubmark/elems/caption.rb +69 -0
  28. data/lib/repubmark/elems/chapter.rb +148 -0
  29. data/lib/repubmark/elems/code_block.rb +70 -0
  30. data/lib/repubmark/elems/code_inline.rb +35 -0
  31. data/lib/repubmark/elems/figure.rb +73 -0
  32. data/lib/repubmark/elems/figures.rb +47 -0
  33. data/lib/repubmark/elems/footnote.rb +87 -0
  34. data/lib/repubmark/elems/footnotes_category.rb +48 -0
  35. data/lib/repubmark/elems/fraction.rb +31 -0
  36. data/lib/repubmark/elems/iframe.rb +62 -0
  37. data/lib/repubmark/elems/joint.rb +176 -0
  38. data/lib/repubmark/elems/link.rb +56 -0
  39. data/lib/repubmark/elems/list.rb +84 -0
  40. data/lib/repubmark/elems/list_item.rb +147 -0
  41. data/lib/repubmark/elems/note.rb +40 -0
  42. data/lib/repubmark/elems/paragraph.rb +42 -0
  43. data/lib/repubmark/elems/power.rb +34 -0
  44. data/lib/repubmark/elems/quote.rb +53 -0
  45. data/lib/repubmark/elems/section.rb +58 -0
  46. data/lib/repubmark/elems/separator.rb +17 -0
  47. data/lib/repubmark/elems/special.rb +37 -0
  48. data/lib/repubmark/elems/text.rb +43 -0
  49. data/lib/repubmark/highlight.rb +85 -0
  50. data/lib/repubmark/titled_ref.rb +16 -0
  51. data/lib/repubmark/version.rb +6 -0
  52. data/lib/repubmark.rb +125 -0
  53. data/tests/examples.rb +51 -0
  54. metadata +129 -0
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Repubmark
4
+ module Elems
5
+ # TODO: maybe don't allow mdash everywhere
6
+ class Special < Base
7
+ parents :Joint
8
+
9
+ HTML = {
10
+ ellipsis: '&hellip;',
11
+ mdash: '&mdash;',
12
+ }.freeze
13
+
14
+ UNICODE = {
15
+ ellipsis: '…',
16
+ mdash: '—',
17
+ }.freeze
18
+
19
+ def initialize(parent, name)
20
+ super parent
21
+ name = String(name).to_sym.freeze
22
+ HTML.fetch name
23
+ @name = name
24
+ end
25
+
26
+ #################
27
+ # Basic methods #
28
+ #################
29
+
30
+ def to_summary_plain = UNICODE.fetch @name
31
+
32
+ def to_html = HTML.fetch @name
33
+
34
+ def to_gemtext = UNICODE.fetch @name
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Repubmark
4
+ module Elems
5
+ class Text < Base
6
+ parents :Joint
7
+
8
+ def initialize(parent, str, bold: false, italic: false)
9
+ super parent
10
+
11
+ self.str = str
12
+
13
+ @bold = !!bold
14
+ @italic = !!italic
15
+ end
16
+
17
+ #################
18
+ # Basic methods #
19
+ #################
20
+
21
+ def word_count = count_words @str
22
+
23
+ def to_summary_plain = @str
24
+
25
+ def to_html = str_to_html
26
+
27
+ def to_gemtext = @str
28
+
29
+ private
30
+
31
+ def str=(str)
32
+ @str = String(str).split.join(' ').freeze
33
+ end
34
+
35
+ def str_to_html
36
+ result = @str
37
+ result = "<em>#{result}</em>" if @italic
38
+ result = "<strong>#{result}</strong>" if @bold
39
+ result.freeze
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Repubmark
4
+ class Highlight
5
+ NO_SYNTAX = 'txt'
6
+
7
+ NO_LINE_NUMBERS = %i[sh_hist].freeze
8
+
9
+ SYNTAXES = {
10
+ certbot: 'ini',
11
+ css: 'css',
12
+ hjson: nil,
13
+ html: 'html',
14
+ ini: 'ini',
15
+ knockd: nil,
16
+ nginx: 'nginx',
17
+ openssh: nil,
18
+ ruby: 'ruby',
19
+ sh_hist: nil,
20
+ sysctl: nil,
21
+ torrc: nil,
22
+ wireguard: 'ini',
23
+ yggdrasil: nil, # Hjson
24
+ }.freeze
25
+
26
+ private_class_method :new
27
+
28
+ def self.call(...) = new(...).call
29
+
30
+ attr_reader :syntax, :str
31
+
32
+ def initialize(syntax, str)
33
+ self.syntax = syntax
34
+ self.str = str
35
+ end
36
+
37
+ def call
38
+ Open3.popen2(*cmdline) do |stdin, stdout, wait_thr|
39
+ stdin.write str
40
+ stdin.close
41
+ result = stdout.read.freeze
42
+ raise 'Highlight error' unless wait_thr.value.success?
43
+
44
+ "<pre><code>#{result}</code></pre>\n".freeze
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def syntax=(syntax)
51
+ return @syntax = nil if syntax.nil?
52
+
53
+ unless syntax.instance_of? Symbol
54
+ raise TypeError, "Expected #{Symbol}, got #{syntax.class}"
55
+ end
56
+
57
+ SYNTAXES.fetch syntax
58
+
59
+ @syntax = syntax
60
+ end
61
+
62
+ def str=(str)
63
+ str = String(str).strip.freeze
64
+ raise 'Expected non-empty string' if str.empty?
65
+
66
+ @str = str
67
+ end
68
+
69
+ def cmdline
70
+ @cmdline ||= [
71
+ 'highlight',
72
+ '--stdout',
73
+ '--fragment',
74
+ '--out-format',
75
+ 'html',
76
+ '--syntax',
77
+ SYNTAXES[syntax] || NO_SYNTAX,
78
+ ].tap do |cmdline|
79
+ unless syntax.nil? || NO_LINE_NUMBERS.include?(syntax)
80
+ cmdline << '--line-numbers'
81
+ end
82
+ end.freeze
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Repubmark
4
+ class TitledRef
5
+ attr_reader :url, :title
6
+
7
+ def initialize(url, title)
8
+ self.url = url
9
+ self.title = title
10
+ end
11
+
12
+ private
13
+
14
+ attr_writer :url, :title
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Repubmark
4
+ # Gem version.
5
+ VERSION = '0.0.0'
6
+ end
data/lib/repubmark.rb ADDED
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'date'
5
+ require 'forwardable'
6
+ require 'open3'
7
+ require 'pathname'
8
+ require 'uri'
9
+ require 'yaml'
10
+
11
+ require 'addressable'
12
+
13
+ require_relative 'repubmark/config'
14
+ require_relative 'repubmark/highlight'
15
+ require_relative 'repubmark/titled_ref'
16
+
17
+ require_relative 'repubmark/elems/base'
18
+
19
+ # Top-level element
20
+ require_relative 'repubmark/elems/article'
21
+
22
+ # Always inside Article
23
+ require_relative 'repubmark/elems/annotation'
24
+ require_relative 'repubmark/elems/footnotes_category'
25
+ # Always inside Article, Chapter
26
+ require_relative 'repubmark/elems/chapter'
27
+ # Always inside Annotation, Blockquote, Chapter
28
+ require_relative 'repubmark/elems/canvas'
29
+
30
+ # Always inside Canvas
31
+ require_relative 'repubmark/elems/blockquote'
32
+ require_relative 'repubmark/elems/code_block'
33
+ require_relative 'repubmark/elems/figures'
34
+ require_relative 'repubmark/elems/iframe'
35
+ require_relative 'repubmark/elems/paragraph'
36
+ require_relative 'repubmark/elems/separator'
37
+
38
+ # Always inside Canvas, Figures
39
+ require_relative 'repubmark/elems/figure'
40
+ # Always inside Canvas, ListItem
41
+ require_relative 'repubmark/elems/list'
42
+ # Always inside List
43
+ require_relative 'repubmark/elems/list_item'
44
+
45
+ # Always inside Caption, Quote
46
+ require_relative 'repubmark/elems/joint'
47
+ # Always inside Blockquote, Figure, Footnote, ListItem, Paragraph
48
+ require_relative 'repubmark/elems/caption'
49
+ # Always inside Caption, Joint, Quote
50
+ require_relative 'repubmark/elems/quote'
51
+
52
+ # Always inside Joint
53
+ require_relative 'repubmark/elems/abbrev'
54
+ require_relative 'repubmark/elems/code_inline'
55
+ require_relative 'repubmark/elems/fraction'
56
+ require_relative 'repubmark/elems/note'
57
+ require_relative 'repubmark/elems/section'
58
+ require_relative 'repubmark/elems/special'
59
+ require_relative 'repubmark/elems/text'
60
+ require_relative 'repubmark/elems/link'
61
+ require_relative 'repubmark/elems/power'
62
+
63
+ # Always inside FootnotesCategory
64
+ require_relative 'repubmark/elems/footnote'
65
+
66
+ ##
67
+ # A Markdown-inspired markup language that can be compiled into HTML and
68
+ # Gemtext.
69
+ #
70
+ module Repubmark
71
+ FORMATS = %i[chapters gemtext html summary_plain word_count].freeze
72
+
73
+ SLUG_RE = /\A[[:word:]]+(-[[:word:]]+)*\z/
74
+
75
+ UNICODE_SUPS = {
76
+ '0' => '⁰',
77
+ '1' => '¹',
78
+ '2' => '²',
79
+ '3' => '³',
80
+ '4' => '⁴',
81
+ '5' => '⁵',
82
+ '6' => '⁶',
83
+ '7' => '⁷',
84
+ '8' => '⁸',
85
+ '9' => '⁹',
86
+ '+' => '⁺',
87
+ '-' => '⁻',
88
+ '=' => '⁼',
89
+ '(' => '⁽',
90
+ ')' => '⁾',
91
+ }.freeze
92
+
93
+ UNICODE_SUBS = {
94
+ '0' => '₀',
95
+ '1' => '₁',
96
+ '2' => '₂',
97
+ '3' => '₃',
98
+ '4' => '₄',
99
+ '5' => '₅',
100
+ '6' => '₆',
101
+ '7' => '₇',
102
+ '8' => '₈',
103
+ '9' => '₉',
104
+ '+' => '₊',
105
+ '-' => '₋',
106
+ '=' => '₌',
107
+ '(' => '₍',
108
+ ')' => '₎',
109
+ }.freeze
110
+
111
+ def self.validate_slug!(slug)
112
+ slug = String(slug).freeze
113
+ raise 'Invalid slug' unless SLUG_RE.match? slug
114
+
115
+ slug
116
+ end
117
+
118
+ def self.unicode_sup(val)
119
+ String(val).each_char.map { |chr| UNICODE_SUPS.fetch chr }.join.freeze
120
+ end
121
+
122
+ def self.unicode_sub(val)
123
+ String(val).each_char.map { |chr| UNICODE_SUBS.fetch chr }.join.freeze
124
+ end
125
+ end
data/tests/examples.rb ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'open3'
5
+
6
+ ROOT = File.expand_path('..', __dir__).freeze
7
+
8
+ EXE = File.expand_path('exe/repubmark', ROOT).freeze
9
+ EXAMPLES = File.expand_path('examples', ROOT).freeze
10
+ EXAMPLES_GLOB = File.expand_path('examples/*.repub', ROOT).freeze
11
+ CONFIG = File.expand_path('examples/config.yml', ROOT).freeze
12
+
13
+ PROFILES = [
14
+ %w[summary_plain summary.txt],
15
+ %w[http html],
16
+ %w[gemini gmi],
17
+ %w[chapters chapters.json],
18
+ ].map(&:freeze).freeze
19
+
20
+ Dir[EXAMPLES_GLOB].each do |example_filename|
21
+ example = File.read example_filename
22
+ PROFILES.each do |profile_name, expected_ext|
23
+ expected_filename = "#{example_filename[...-6]}.#{expected_ext}"
24
+ expected = File.read expected_filename
25
+
26
+ puts '=' * 80
27
+ puts "Config: #{CONFIG}"
28
+ puts "Example: #{example_filename}"
29
+ puts "Profile: #{profile_name}"
30
+ puts "Expected: #{expected_filename}"
31
+ puts '-' * 80
32
+ puts example.strip
33
+ puts '-' * 80
34
+ puts expected.strip
35
+
36
+ stdin, stdout, wait_thr = Open3.popen2 EXE, CONFIG, profile_name
37
+ stdin.puts example
38
+ stdin.close
39
+ result = stdout.read
40
+ stdout.close
41
+ raise 'Template engine error' unless wait_thr.value.success?
42
+ next if result == expected
43
+
44
+ puts '-' * 80
45
+ puts result.strip
46
+ puts '=' * 80
47
+ raise 'Invalid output'
48
+ end
49
+ end
50
+
51
+ puts '=' * 80
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: repubmark
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Kotov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: addressable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ description: A Markdown-inspired markup language that can be compiled into HTML and
42
+ Gemtext
43
+ email:
44
+ - me+repubmark@kotovalexarian.com
45
+ executables:
46
+ - repubmark
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".rubocop.yml"
51
+ - ".rubocop_todo.yml"
52
+ - ".yardopts"
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - examples/config.yml
57
+ - examples/full.chapters.json
58
+ - examples/full.gmi
59
+ - examples/full.html
60
+ - examples/full.repub
61
+ - examples/full.summary.txt
62
+ - examples/hello.chapters.json
63
+ - examples/hello.gmi
64
+ - examples/hello.html
65
+ - examples/hello.repub
66
+ - examples/hello.summary.txt
67
+ - exe/repubmark
68
+ - lib/repubmark.rb
69
+ - lib/repubmark/config.rb
70
+ - lib/repubmark/elems/abbrev.rb
71
+ - lib/repubmark/elems/annotation.rb
72
+ - lib/repubmark/elems/article.rb
73
+ - lib/repubmark/elems/base.rb
74
+ - lib/repubmark/elems/blockquote.rb
75
+ - lib/repubmark/elems/canvas.rb
76
+ - lib/repubmark/elems/caption.rb
77
+ - lib/repubmark/elems/chapter.rb
78
+ - lib/repubmark/elems/code_block.rb
79
+ - lib/repubmark/elems/code_inline.rb
80
+ - lib/repubmark/elems/figure.rb
81
+ - lib/repubmark/elems/figures.rb
82
+ - lib/repubmark/elems/footnote.rb
83
+ - lib/repubmark/elems/footnotes_category.rb
84
+ - lib/repubmark/elems/fraction.rb
85
+ - lib/repubmark/elems/iframe.rb
86
+ - lib/repubmark/elems/joint.rb
87
+ - lib/repubmark/elems/link.rb
88
+ - lib/repubmark/elems/list.rb
89
+ - lib/repubmark/elems/list_item.rb
90
+ - lib/repubmark/elems/note.rb
91
+ - lib/repubmark/elems/paragraph.rb
92
+ - lib/repubmark/elems/power.rb
93
+ - lib/repubmark/elems/quote.rb
94
+ - lib/repubmark/elems/section.rb
95
+ - lib/repubmark/elems/separator.rb
96
+ - lib/repubmark/elems/special.rb
97
+ - lib/repubmark/elems/text.rb
98
+ - lib/repubmark/highlight.rb
99
+ - lib/repubmark/titled_ref.rb
100
+ - lib/repubmark/version.rb
101
+ - tests/examples.rb
102
+ homepage: https://git.causa-arcana.com/causa-arcana/repubmark
103
+ licenses:
104
+ - MIT
105
+ metadata:
106
+ rubygems_mfa_required: 'true'
107
+ homepage_uri: https://git.causa-arcana.com/causa-arcana/repubmark
108
+ source_code_uri: https://git.causa-arcana.com/causa-arcana/repubmark
109
+ documentation_uri: https://www.rubydoc.info/gems/repubmark/0.0.0
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '3.2'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubygems_version: 3.4.19
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: A Markdown-inspired markup language that can be compiled into HTML and Gemtext
129
+ test_files: []