asciidoctor-katex 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f22339f6723c08a19cc767595dcc38721506b4a36a637181213c4a123a37908
4
- data.tar.gz: 934ea7f37bb904c1e5a437f5e576f673bd68e69a1d9cdac581683aea98b7c270
3
+ metadata.gz: 563feb091e023db762437c7dd7375a8238079780de324428e250da7844bb6b2f
4
+ data.tar.gz: 1567edd17da494abccc2a87832ef032ff9a63e35c9a07de4f53bd4a7584dde01
5
5
  SHA512:
6
- metadata.gz: d433256d16093e1b1c723765deab5e87c242bf469916a8202073dff267152c4332a77fccf89700b13c68a12bf132cc7a02812cc468df7d74ba3ac5c8c62063c9
7
- data.tar.gz: 7ff93fd5d24e49a29b414fa64ececcbc455f9f315959e04c0ddf1d1c0910e70727dca9580238fb0d2c1bb8eea63a1ee7035b22c3834880863f56040c66136e27
6
+ metadata.gz: 638dca239825461b452b6fabadfc2d80685daa02031aec634d5a80198bc9acbdfda4a357df188987f4b3c5ae4aa0425c75d868e90410c820ea834bc9e0eeb891
7
+ data.tar.gz: 3044648be03e130d47ae1deb4bc2fd402dab87334def8e11fe83714bbd5307ac2a8155f541b6ae796e7b2cf5e57b975075ed4d6079efd7ef0d4a8f678e17cf71
@@ -2,6 +2,7 @@
2
2
  require 'asciidoctor' unless RUBY_PLATFORM == 'opal'
3
3
  require 'asciidoctor/extensions' unless RUBY_PLATFORM == 'opal'
4
4
  require 'asciidoctor/katex/version'
5
+ require 'asciidoctor/katex/errors'
5
6
  require 'asciidoctor/katex/treeprocessor'
6
7
 
7
8
  unless RUBY_PLATFORM == 'opal'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ require 'asciidoctor/katex/version'
3
+
4
+ module Asciidoctor::Katex
5
+
6
+ # Exception raised when KaTeX throw any error except `ParseError`.
7
+ class KatexError < ::RuntimeError
8
+ attr_reader :expression
9
+
10
+ # @param msg [#to_s] the message.
11
+ # @param expression [String] the LaTeX expression that caused the error.
12
+ def initialize(msg, expression)
13
+ @expression = expression
14
+ super(msg.to_s)
15
+ end
16
+ end
17
+
18
+ # Exception raised when KaTeX throw `ParseError` which is the main error
19
+ # thrown by KaTeX functions when something has gone wrong.
20
+ class ParseError < KatexError; end
21
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require 'asciidoctor/katex/version'
3
+ require 'asciidoctor/katex/errors'
4
+ require 'asciidoctor/katex/utils'
5
+
6
+ module Asciidoctor::Katex
7
+ # Adapter for the KaTeX library for Opal/JS environment.
8
+ class OpalKatexAdapter
9
+ include Utils
10
+
11
+ # @param default_options [Hash] the default options for the KaTeX renderer.
12
+ # @param katex_object the katex object to use under Opal (defaults to
13
+ # global variable `katex`).
14
+ def initialize(default_options = {}, katex_object = nil)
15
+ @default_options = hash_camelize(default_options)
16
+ @katex_object = katex_object || `katex`
17
+ end
18
+
19
+ # Renders the given math expression to HTML using KaTeX.
20
+ #
21
+ # @param math [String] the math (LaTeX) expression.
22
+ # @param opts [Hash] options for `katex.renderToString`.
23
+ # Keys in under_score notation will be converted to camelCase.
24
+ # See <https://github.com/Khan/KaTeX#rendering-options>.
25
+ # @return [String] a rendered HTML fragment.
26
+ def render(math, opts = {})
27
+ opts = @default_options.merge(hash_camelize(opts))
28
+
29
+ begin
30
+ `#{@katex_object}.renderToString(#{math}, #{opts}.$$smap)`
31
+ rescue ::JS::Error => err
32
+ # "#{err}" is really needed for Opal/JS, #to_s returns a different string.
33
+ # rubocop:disable UnneededInterpolation
34
+ raise ParseError.new(err, math) if "#{err}".start_with?('ParseError:')
35
+ raise KatexError.new(err, math)
36
+ end
37
+ end
38
+
39
+ alias call render
40
+ end
41
+
42
+ # The default KaTeX adapter.
43
+ KatexAdapter = OpalKatexAdapter unless defined? KatexAdapter
44
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ require 'asciidoctor/katex/version'
3
+ require 'asciidoctor/katex/errors'
4
+ require 'asciidoctor/katex/utils'
5
+ require 'katex'
6
+
7
+ module Asciidoctor::Katex
8
+ # Adapter for the KaTeX library for Ruby environment.
9
+ class RubyKatexAdapter
10
+ include Utils
11
+
12
+ # @param default_options [Hash] the default options for the KaTeX renderer.
13
+ def initialize(default_options = {})
14
+ @default_options = hash_camelize(default_options)
15
+ end
16
+
17
+ # Renders the given math expression to HTML using KaTeX.
18
+ #
19
+ # @param math [String] the math (LaTeX) expression.
20
+ # @param opts [Hash] options for `katex.renderToString`.
21
+ # Keys in under_score notation will be converted to camelCase.
22
+ # See <https://github.com/Khan/KaTeX#rendering-options>.
23
+ # @return [String] a rendered HTML fragment.
24
+ def render(math, opts = {})
25
+ opts = @default_options.merge(hash_camelize(opts))
26
+
27
+ opts[:throw_on_error] = opts[:throwOnError]
28
+ opts[:error_color] = opts[:errorColor] || '#cc0000'
29
+
30
+ begin
31
+ ::Katex.render(math, opts)
32
+ rescue ::ExecJS::ProgramError => err
33
+ raise ParseError.new(err, math) if err.to_s.start_with?('ParseError:')
34
+ raise KatexError.new(err, math)
35
+ end
36
+ end
37
+
38
+ alias call render
39
+ end
40
+
41
+ # The default KaTeX adapter.
42
+ KatexAdapter = RubyKatexAdapter unless defined? KatexAdapter
43
+ end
@@ -43,9 +43,8 @@ module Asciidoctor::Katex
43
43
  isblock = node.block?
44
44
 
45
45
  output.sub(isblock ? @block_re : @inline_re) do
46
- @math_renderer.call(::Regexp.last_match[1].strip,
47
- display_mode: isblock,
48
- throw_on_error: @throw_on_error)
46
+ math = decode_html_entities(::Regexp.last_match[1].strip)
47
+ @math_renderer.call(math, display_mode: isblock, throw_on_error: @throw_on_error)
49
48
  end
50
49
  end
51
50
 
@@ -68,7 +67,23 @@ module Asciidoctor::Katex
68
67
  # @return [Regexp]
69
68
  def regexp_from_delimiters(delimiters)
70
69
  open, close = delimiters.map { |s| ::Regexp.escape(s) }
71
- /#{open}(.+)#{close}/m
70
+
71
+ # XXX: Opal 0.11.x does not properly escape interpolated regexps and
72
+ # Regexp.new does not work at all. Thus we have to escape \s\S in
73
+ # advance when running on Opal and this faulty behaviour is detected.
74
+ if ::RUBY_PLATFORM == 'opal' && /#{''}\\s/ == /\s/
75
+ /#{open}([\\s\\S]+)#{close}/m
76
+ else
77
+ /#{open}([\s\S]+)#{close}/m
78
+ end
79
+ end
80
+
81
+ # @param str [String]
82
+ # @return [String]
83
+ def decode_html_entities(str)
84
+ str.gsub('&lt;', '<')
85
+ .gsub('&gt;', '>')
86
+ .gsub('&amp;', '&')
72
87
  end
73
88
  end
74
89
  end
@@ -2,25 +2,30 @@
2
2
  require 'asciidoctor' unless RUBY_PLATFORM == 'opal'
3
3
  require 'asciidoctor/extensions' unless RUBY_PLATFORM == 'opal'
4
4
  require 'asciidoctor/katex/version'
5
- require 'asciidoctor/katex/katex_adapter'
6
5
  require 'asciidoctor/katex/stem_converter_decorator'
7
6
 
7
+ if RUBY_PLATFORM == 'opal'
8
+ require 'asciidoctor/katex/opal_katex_adapter'
9
+ else
10
+ require 'asciidoctor/katex/ruby_katex_adapter'
11
+ end
12
+
8
13
  module Asciidoctor::Katex
9
14
  # Asciidoctor processor that renders delimited latexmath expressions using
10
15
  # the KaTeX library.
11
16
  class Treeprocessor < ::Asciidoctor::Extensions::Treeprocessor
12
17
 
13
- # @param katex_renderer [#call] callable that accepts a math expression
18
+ # @param katex_options [Hash] default options for the KaTeX renderer.
19
+ # This parameter has no effect when *katex_renderer* is provided.
20
+ # @param katex_renderer [#call, nil] callable that accepts a math expression
14
21
  # [String] and options [Hash], and returns a rendered expression [String].
15
- # Default is an instance of KatexAdapter.
22
+ # Defaults to {KatexAdapter} initialized with the *katex_options*.
16
23
  # @param require_stem_attr [Boolean] `true` to skip when `stem` attribute
17
24
  # is not declared, `false` to process anyway.
18
- def initialize(katex_renderer: KatexAdapter.new,
19
- require_stem_attr: true,
20
- **)
21
- super
22
- @katex_renderer = katex_renderer
25
+ def initialize(katex_options: {}, katex_renderer: nil, require_stem_attr: true, **)
26
+ @katex_renderer = katex_renderer || KatexAdapter.new(katex_options)
23
27
  @require_stem_attr = require_stem_attr
28
+ super
24
29
  end
25
30
 
26
31
  # @param document [Asciidoctor::Document] the document to process.
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require 'asciidoctor/katex/version'
3
+
4
+ module Asciidoctor::Katex
5
+ # @private
6
+ module Utils
7
+ module_function
8
+
9
+ # @param hash [Hash] the hash to transform.
10
+ # @return [Hash] a copy of the *hash* with under_score keys transformed to camelCase.
11
+ def hash_camelize(hash)
12
+ hash.map { |key, val|
13
+ key = key.to_s.gsub(/_\w/) { |s| s[1].upcase }.to_sym
14
+ [key, val]
15
+ }.to_h
16
+ end
17
+ end
18
+ end
@@ -3,6 +3,6 @@
3
3
  module Asciidoctor
4
4
  module Katex
5
5
  # Version of the asciidoctor-katex gem.
6
- VERSION = '0.1.2'
6
+ VERSION = '0.2.0'
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-katex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Jirutka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-30 00:00:00.000000000 Z
11
+ date: 2018-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -147,9 +147,12 @@ files:
147
147
  - asciidoctor-katex.gemspec
148
148
  - lib/asciidoctor-katex.rb
149
149
  - lib/asciidoctor/katex.rb
150
- - lib/asciidoctor/katex/katex_adapter.rb
150
+ - lib/asciidoctor/katex/errors.rb
151
+ - lib/asciidoctor/katex/opal_katex_adapter.rb
152
+ - lib/asciidoctor/katex/ruby_katex_adapter.rb
151
153
  - lib/asciidoctor/katex/stem_converter_decorator.rb
152
154
  - lib/asciidoctor/katex/treeprocessor.rb
155
+ - lib/asciidoctor/katex/utils.rb
153
156
  - lib/asciidoctor/katex/version.rb
154
157
  homepage: https://github.com/jirutka/asciidoctor-katex/
155
158
  licenses:
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'asciidoctor/katex/version'
3
- require 'katex' unless RUBY_PLATFORM == 'opal'
4
-
5
- module Asciidoctor::Katex
6
- # Adapter for KaTeX library supporting both Ruby and Opal environment.
7
- class KatexAdapter
8
-
9
- # @param default_options [Hash] the default options for the KaTeX renderer.
10
- # @param katex_object the katex object to use under Opal (defaults to
11
- # global variable `katex`).
12
- def initialize(default_options = {}, katex_object = nil)
13
- @default_options = default_options
14
- @katex_object = katex_object || `katex` if RUBY_PLATFORM == 'opal'
15
- end
16
-
17
- # @return [Boolean] whether is KaTeX library installed and loaded.
18
- # This is useful only under Opal.
19
- def available?
20
- if RUBY_PLATFORM == 'opal'
21
- `#{@katex_object} != 'undefined' && #{@katex_object}.renderToString != undefined`
22
- else
23
- defined? ::Katex
24
- end
25
- end
26
-
27
- # Renders the given math expression to HTML using KaTeX.
28
- #
29
- # @param math [String] the math (LaTeX) expression.
30
- # @param options [Hash] options for `katex.renderToString`.
31
- # Keys in under_score notation will be converted to camelCase.
32
- # See <https://github.com/Khan/KaTeX#rendering-options>.
33
- # @return [String] a rendered HTML fragment.
34
- def render(math, options = {})
35
- options = hash_camelize(options || {})
36
-
37
- if RUBY_PLATFORM == 'opal'
38
- `#{@katex_object}.renderToString(#{math}, #{options}.$$smap)`
39
- else
40
- ::Katex.render(math, options)
41
- end
42
- end
43
-
44
- alias call render
45
-
46
- # @return [String] version of the KaTeX library.
47
- def version
48
- if RUBY_PLATFORM == 'opal'
49
- '0.9.0' # TODO: replace with `katex.version` after update to 0.10+.
50
- else
51
- ::Katex::KATEX_VERSION.sub(/^v/, '')
52
- end
53
- end
54
-
55
- private
56
-
57
- # @param hash [Hash] the hash to transform.
58
- # @return [Hash] a copy of the *hash* with under_score keys transformed to camelCase.
59
- def hash_camelize(hash)
60
- hash.map { |k, v|
61
- [k.to_s.gsub(/_\w/) { |s| s[1].upcase }.to_sym, v]
62
- }.to_h
63
- end
64
- end
65
- end