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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 290626aa91c28cc4961baf40ec00dde81928da68e0a923ee84999027e7f3c9b0
4
- data.tar.gz: 4ec8d501a4ab6f1b068ec01bb21a7d84bd844a5bca7d105bdc0c9c6e2652eec8
3
+ metadata.gz: 476a24b916af7e71a30a60cd2476063fa2d627959060179104e8a41871c5d4ab
4
+ data.tar.gz: 93243e4af6fea3e355f0cc4401e990cdb107f77c717b7e63d4902a172b56a7d0
5
5
  SHA512:
6
- metadata.gz: ccdddba235b4d0462ccb5e4d2ee4cbf5b97e9964c10fd0395e814635281563c6363a381422feeefdd9eb6a895877a47aba6fae95de36c98a6f710785ed18ba51
7
- data.tar.gz: 4d0a8dad642c30c5f26ca5903d715e3728d918bb17fe1eaeaf3ce8ad814a25e9c50d0df15533522275665978971ee269164a2969cf73db9823b71b9ea29a7217
6
+ metadata.gz: d0ae577416fec788441659e670f4e85c0b34c091c81f666ab1cd62f5a39b3500548efb4238f53d77f1ea0dd30bd3571f001aa418311dcf6786a70afbbd3d0e8c
7
+ data.tar.gz: a7feff881708ffb27bffb76c2f00146c0bb4f7f4a90fe341ea88f121f1442ace72294596112f8c139e9a5628f4f14f0022e2f18dabe5a7e15e56e985d31c9d73
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/jektex.svg)](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/). YOU SHOULD ALWAYS delete jektex cache after changing
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
- for patern in $ignored
21
- if File.fnmatch?(patern, page.relative_path, File::FNM_DOTMATCH) then
22
- return true
23
- end
24
- end
25
- return false
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 == nil or is_ignored?(page) or page.data[FRONT_MATTER_TAG] == "false" then
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.path) }
38
- # render display expressions
39
- post = post.gsub(/(\\\[)((.|\n)*?)(?<!\\)\\\]/) { |m| escape_method($1, $2, page.path) }
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, string, doc_path )
44
- @display = false
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
- @expression_hash = Digest::SHA2.hexdigest(string) + @display.to_s
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?(@expression_hash))
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[@expression_hash]
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
- @result = KATEX.call("katex.renderToString", string,
69
- {displayMode: @display, macros: $global_macros})
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 Exception => e
89
+ rescue ExecJS::ProgramError => pe
76
90
  # catch parse error
77
- puts "\e[31m " + e.message.gsub("ParseError: ", "") + "\n\t" + doc_path + "\e[0m"
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[@expression_hash] = @result
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 @result
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 site.config["jektex"] == nil then
107
- # if no config is defined make empty one
108
- config = Hash.new
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
- # load jektex config from config file
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["macros"] != nil then
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.size == 0 then
122
- puts " LaTeX: no macros loaded"
138
+ if $global_macros.empty?
139
+ puts "#{INDENT}LaTeX: no macros loaded"
123
140
  else
124
- puts " LaTeX: " + $global_macros.size.to_s + " macro" +
125
- ($global_macros.size == 1 ? "" : "s") + " loaded"
126
- end
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
- if config["ignore"] != nil then
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 $disable_disk_cache == false
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
+
@@ -1,3 +1,3 @@
1
1
  module Jektex
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
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.5
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-02-22 00:00:00.000000000 Z
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