jektex 0.0.5 → 0.0.6
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/README.md +5 -3
- data/lib/jektex/jektex.rb +75 -73
- data/lib/jektex/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 476a24b916af7e71a30a60cd2476063fa2d627959060179104e8a41871c5d4ab
|
4
|
+
data.tar.gz: 93243e4af6fea3e355f0cc4401e990cdb107f77c717b7e63d4902a172b56a7d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d0ae577416fec788441659e670f4e85c0b34c091c81f666ab1cd62f5a39b3500548efb4238f53d77f1ea0dd30bd3571f001aa418311dcf6786a70afbbd3d0e8c
|
7
|
+
data.tar.gz: a7feff881708ffb27bffb76c2f00146c0bb4f7f4a90fe341ea88f121f1442ace72294596112f8c139e9a5628f4f14f0022e2f18dabe5a7e15e56e985d31c9d73
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[](https://rubygems.org/gems/jektex)
|
2
|
+
|
1
3
|
# Jektex
|
2
4
|
Jekyll plugin for blazing fast server side cached LaTeX rendering with support of macros.
|
3
5
|
Enjoy comfort of latex and markdown without cluttering your site with bloated javascript.
|
@@ -14,6 +16,7 @@ Enjoy comfort of latex and markdown without cluttering your site with bloated ja
|
|
14
16
|
- Marks invalid syntax in document
|
15
17
|
- Prints location of invalid expression during rendering
|
16
18
|
- Highly configurable but still having sensible defaults
|
19
|
+
- Makes sure that cache does not contain expression rendered with outdated configuration
|
17
20
|
|
18
21
|
## Usage
|
19
22
|
|
@@ -98,8 +101,7 @@ jektex:
|
|
98
101
|
- ["\\C", "\\mathbb{C}"]
|
99
102
|
```
|
100
103
|
And yes you have to escape backlash(`\`) with another backlash. This is caused by
|
101
|
-
[yaml definition](https://yaml.org/).
|
102
|
-
definition of a macro for change to take effect.
|
104
|
+
[yaml definition](https://yaml.org/).
|
103
105
|
|
104
106
|
**Complete examples**
|
105
107
|
Recommended config:
|
@@ -146,7 +148,7 @@ and do not forget to add `katex.min.css` to you html head:
|
|
146
148
|
```html
|
147
149
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">
|
148
150
|
```
|
149
|
-
It is much better practice to download **css** file and load it as an asset from your server directly.
|
151
|
+
It is much better practice to download [**css** file](https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css) and load it as an asset from your server directly.
|
150
152
|
You can find more information on [KaTeX's website](https://katex.org/docs/browser.html).
|
151
153
|
|
152
154
|
## Contributions and bug reports
|
data/lib/jektex/jektex.rb
CHANGED
@@ -9,91 +9,97 @@ CACHE_FILE = "jektex-cache.marshal"
|
|
9
9
|
KATEX = ExecJS.compile(open(PATH_TO_JS).read)
|
10
10
|
PARSE_ERROR_PLACEHOLDER = "<b style='color: red;'>PARSE ERROR</b>"
|
11
11
|
FRONT_MATTER_TAG = "jektex"
|
12
|
+
INDENT = " " * 13
|
13
|
+
|
12
14
|
$global_macros = Hash.new
|
15
|
+
$updated_global_macros = Array.new
|
16
|
+
|
13
17
|
$count_newly_generated_expressions = 0
|
18
|
+
|
14
19
|
$path_to_cache = File.join(DEFAULT_CACHE_DIR, CACHE_FILE)
|
15
20
|
$cache = nil
|
16
21
|
$disable_disk_cache = false
|
22
|
+
|
17
23
|
$ignored = Array.new
|
18
24
|
|
25
|
+
def get_list_of_updated_global_macros(current_macros, cached_global_macros)
|
26
|
+
return Array.new unless cached_global_macros || current_macros
|
27
|
+
return current_macros.keys unless cached_global_macros
|
28
|
+
return cached_global_macros.keys unless current_macros
|
29
|
+
|
30
|
+
macro_set = Set.new(cached_global_macros.keys + current_macros.keys)
|
31
|
+
macro_set.delete_if { |m| cached_global_macros[m] == current_macros[m] }
|
32
|
+
return macro_set.to_a
|
33
|
+
end
|
34
|
+
|
19
35
|
def is_ignored?(page)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
return
|
36
|
+
return true if page.data[FRONT_MATTER_TAG] == "false"
|
37
|
+
return $ignored.any? { |patern| File.fnmatch?(patern, page.relative_path, File::FNM_DOTMATCH) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def contains_updated_global_macro?(expression)
|
41
|
+
return $updated_global_macros.any? { |m| expression[m] }
|
42
|
+
end
|
43
|
+
|
44
|
+
def print_stats
|
45
|
+
print "#{INDENT}LaTeX: " \
|
46
|
+
"#{$count_newly_generated_expressions} expressions rendered " \
|
47
|
+
"(#{$cache.size} already cached)".ljust(72) + "\r"
|
48
|
+
$stdout.flush
|
26
49
|
end
|
27
50
|
|
28
51
|
def render(page)
|
29
52
|
# check if document is not set to be ignored
|
30
|
-
if page.data
|
31
|
-
return page.output
|
32
|
-
end
|
33
|
-
|
53
|
+
return page.output if !page.data || is_ignored?(page)
|
34
54
|
# convert HTML entities back to characters
|
35
55
|
post = HTMLEntities.new.decode(page.output.to_s)
|
36
56
|
# render inline expressions
|
37
|
-
post = post.gsub(/(\\\()((.|\n)*?)(?<!\\)\\\)/) { |m| escape_method($1, $2, page.
|
38
|
-
# render display expressions
|
39
|
-
post = post.gsub(/(\\\[)((.|\n)*?)(?<!\\)\\\]/) { |m| escape_method($1, $2, page.
|
57
|
+
post = post.gsub(/(\\\()((.|\n)*?)(?<!\\)\\\)/) { |m| escape_method($1, $2, page.relative_path) }
|
58
|
+
# render display mode expressions
|
59
|
+
post = post.gsub(/(\\\[)((.|\n)*?)(?<!\\)\\\]/) { |m| escape_method($1, $2, page.relative_path) }
|
40
60
|
return post
|
41
61
|
end
|
42
62
|
|
43
|
-
def escape_method( type,
|
44
|
-
|
45
|
-
|
46
|
-
# detect if expression is display view
|
47
|
-
case type.downcase
|
48
|
-
when /\(/
|
49
|
-
@display = false
|
50
|
-
else /\[/
|
51
|
-
@display = true
|
52
|
-
end
|
63
|
+
def escape_method( type, expression, doc_path )
|
64
|
+
# detect if expression is in display mode
|
65
|
+
is_in_display_mode? = type.downcase =~ /\[/
|
53
66
|
|
54
67
|
# generate a hash from the math expression
|
55
|
-
|
68
|
+
expression_hash = Digest::SHA2.hexdigest(string) + is_in_display_mode?.to_s
|
56
69
|
|
57
70
|
# use it if it exists
|
58
|
-
if($cache.has_key?(
|
71
|
+
if($cache.has_key?(expression_hash) && !contains_updated_global_macro?(string))
|
72
|
+
# check if expressin conains updated macro
|
59
73
|
$count_newly_generated_expressions += 1
|
60
74
|
print_stats
|
61
|
-
return $cache[
|
75
|
+
return $cache[expression_hash]
|
62
76
|
|
63
77
|
# else generate one and store it
|
64
78
|
else
|
65
79
|
# create the cache directory, if it doesn't exist
|
66
80
|
begin
|
67
81
|
# render using ExecJS
|
68
|
-
|
69
|
-
{
|
82
|
+
result = KATEX.call("katex.renderToString", expression,
|
83
|
+
{is_in_display_mode?Mode: is_in_display_mode?, macros: $global_macros})
|
70
84
|
rescue SystemExit, Interrupt
|
71
85
|
# save cache to disk
|
72
86
|
File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
|
73
87
|
# this stops jekyll being immune to interrupts and kill command
|
74
88
|
raise
|
75
|
-
rescue
|
89
|
+
rescue ExecJS::ProgramError => pe
|
76
90
|
# catch parse error
|
77
|
-
puts "\e[31m " +
|
91
|
+
puts "\e[31m " + pe.message.gsub("ParseError: ", "") + "\n\t" + doc_path + "\e[0m"
|
78
92
|
return PARSE_ERROR_PLACEHOLDER
|
79
93
|
end
|
80
94
|
# save to cache
|
81
|
-
$cache[
|
95
|
+
$cache[expression_hash] = @result
|
82
96
|
# update count of newly generated expressions
|
83
97
|
$count_newly_generated_expressions += 1
|
84
98
|
print_stats
|
85
|
-
return
|
99
|
+
return result
|
86
100
|
end
|
87
101
|
end
|
88
102
|
|
89
|
-
def print_stats
|
90
|
-
print " LaTeX: " +
|
91
|
-
($count_newly_generated_expressions).to_s +
|
92
|
-
" expressions rendered (" + $cache.size.to_s +
|
93
|
-
" already cached) \r"
|
94
|
-
$stdout.flush
|
95
|
-
end
|
96
|
-
|
97
103
|
Jekyll::Hooks.register :pages, :post_render do |page|
|
98
104
|
page.output = render(page)
|
99
105
|
end
|
@@ -103,50 +109,42 @@ Jekyll::Hooks.register :documents, :post_render do |doc|
|
|
103
109
|
end
|
104
110
|
|
105
111
|
Jekyll::Hooks.register :site, :after_init do |site|
|
106
|
-
if
|
107
|
-
|
108
|
-
|
112
|
+
# load jektex config from config file and if no config is defined make empty one
|
113
|
+
config = site.config["jektex"] || Hash.new
|
114
|
+
|
115
|
+
# check if there is defined custom cache location in config
|
116
|
+
$path_to_cache = File.join(config["cache_dir"].to_s, CACHE_FILE) if config.has_key?("cache_dir")
|
117
|
+
|
118
|
+
# load content of cache file if it exists
|
119
|
+
if File.exist?($path_to_cache)
|
120
|
+
$cache = File.open($path_to_cache, "r"){ |from_file| Marshal.load(from_file)}
|
109
121
|
else
|
110
|
-
|
111
|
-
config = site.config["jektex"]
|
122
|
+
$cache = Hash.new
|
112
123
|
end
|
124
|
+
|
125
|
+
# check if cache is disable in config
|
126
|
+
$disable_disk_cache = site.config["disable_disk_cache"] if site.config.has_key?("disable_disk_cache")
|
127
|
+
|
113
128
|
# load macros
|
114
|
-
if config
|
129
|
+
if config.has_key?("macros")
|
115
130
|
for macro_definition in config["macros"]
|
116
131
|
$global_macros[macro_definition[0]] = macro_definition[1]
|
117
132
|
end
|
118
133
|
end
|
119
134
|
|
135
|
+
# make list of updated macros
|
136
|
+
$updated_global_macros = get_list_of_updated_global_macros($global_macros, $cache["cached_global_macros"])
|
120
137
|
# print macro information
|
121
|
-
if $global_macros.
|
122
|
-
puts "
|
138
|
+
if $global_macros.empty?
|
139
|
+
puts "#{INDENT}LaTeX: no macros loaded"
|
123
140
|
else
|
124
|
-
puts "
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
# check if there is defined custom cache location in config
|
129
|
-
if config["cache_dir"] != nil then
|
130
|
-
$path_to_cache = File.join(config["cache_dir"].to_s, CACHE_FILE)
|
141
|
+
puts "#{INDENT}LaTeX: #{$global_macros.size} macro" +
|
142
|
+
($global_macros.size == 1 ? "" : "s") + " loaded" +
|
143
|
+
($updated_global_macros.empty? ? "" : " (#{$updated_global_macros.size} updated)")
|
131
144
|
end
|
132
145
|
|
133
146
|
# load list of ignored files
|
134
|
-
|
135
|
-
$ignored = config["ignore"]
|
136
|
-
end
|
137
|
-
|
138
|
-
# load content of cache file if it exists
|
139
|
-
if(File.exist?($path_to_cache)) then
|
140
|
-
$cache = File.open($path_to_cache, "r"){|from_file| Marshal.load(from_file)}
|
141
|
-
else
|
142
|
-
$cache = Hash.new
|
143
|
-
end
|
144
|
-
|
145
|
-
# check if cache is disable in config
|
146
|
-
if site.config["disable_disk_cache"] != nil then
|
147
|
-
$disable_disk_cache = site.config["disable_disk_cache"]
|
148
|
-
end
|
149
|
-
|
147
|
+
$ignored = config["ignore"] if config.has_key?("ignore")
|
150
148
|
end
|
151
149
|
|
152
150
|
Jekyll::Hooks.register :site, :after_reset do
|
@@ -158,9 +156,13 @@ Jekyll::Hooks.register :site, :post_write do
|
|
158
156
|
# print new line to prevent overwriting previous output
|
159
157
|
print "\n"
|
160
158
|
# check if caching is enabled
|
161
|
-
if
|
159
|
+
if !$disable_disk_cache
|
160
|
+
# save global macros to cache
|
161
|
+
$cache["cached_global_macros"] = $global_macros
|
162
|
+
# create cache path
|
163
|
+
Pathname.new($path_to_cache).dirname.mkpath
|
162
164
|
# save cache to disk
|
163
|
-
Dir.mkdir(File.dirname($path_to_cache)) unless File.exists?(File.dirname($path_to_cache))
|
164
165
|
File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
|
165
166
|
end
|
166
167
|
end
|
168
|
+
|
data/lib/jektex/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jektex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Černý
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|
@@ -108,7 +108,7 @@ licenses:
|
|
108
108
|
- GPL-3.0-or-later
|
109
109
|
metadata:
|
110
110
|
bug_tracker_uri: https://github.com/yagarea/jektex/issues
|
111
|
-
documentation_uri: https://github.com/yagarea/jektex
|
111
|
+
documentation_uri: https://github.com/yagarea/jektex/blob/master/README.md
|
112
112
|
homepage_uri: https://github.com/yagarea/jektex
|
113
113
|
source_code_uri: https://github.com/yagarea/jektex
|
114
114
|
changelog_uri: https://github.com/yagarea/jektex/blob/master/changelog.md
|