jektex 0.0.4 → 0.0.7

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: db3eb57993f08e73ede3ba763410029942df4d4320c9d659c2b28fabd5a49f4e
4
- data.tar.gz: fd8756624b5ff039c66d0896c4c0316dfe4be10045ed412d80240ce17f2e98fd
3
+ metadata.gz: a6f411d475735a808e6fb495464688d7acca5fb2afa3d4f467612fc7d5308b7a
4
+ data.tar.gz: e322f027b1c7080553a9cf3e3d4145b49166f6d26e3c5502b3daf8a0ce61a0a5
5
5
  SHA512:
6
- metadata.gz: 6645b4a77ccfd8919db211dca542ef3a98ae1dfc9740c74580d74b62f5e1cbaea9ca07dabe14518c3b2cec2b68cfc3406cb5d1ec3a8c840e86b07302acaf7249
7
- data.tar.gz: 04b011d1f6e6a7dccc2de68f159ee74a0bdaf7944c7c39fb5d627942425c6665b98803abb601a696d50c1c6ac738cb629086c5149d1ffb8eec636e7e441c854b
6
+ metadata.gz: 30af1bad450e61c9085975a37b6a2142084854d96201eb67e11cc9c80a21d9d3dbbc5894c82610f2cac7ab52b8272f3f5aae8b74bfa054480edbea9865ebbc48
7
+ data.tar.gz: 06c8353988adc7940217d6a75ca313cf72a65492db30ab5421567c822199dd6c4b57c86a28485a0b146de826b69c6c1ee80ccb00335277f0b23065881670949d
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.
@@ -13,15 +15,14 @@ Enjoy comfort of latex and markdown without cluttering your site with bloated ja
13
15
  - Does not interfere with Jekyll workflow and project structure
14
16
  - Marks invalid syntax in document
15
17
  - Prints location of invalid expression during rendering
16
- - Tags places within the rendered documents with syntax errors
17
18
  - Highly configurable but still having sensible defaults
19
+ - Makes sure that cache does not contain expression rendered with outdated configuration
18
20
 
19
21
  ## Usage
20
22
 
21
23
  ### Notation
22
24
  **Inline formula**
23
25
  Put formula between two pairs of dolar signs (`$$`) inside of paragraph.
24
-
25
26
  ```latex
26
27
  Lorem ipsum dolor sit amet, consectetur $$e^{i\theta}=\cos(\theta)+i\sin(\theta)$$
27
28
  adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -44,40 +45,87 @@ display mode?
44
45
  This is how [kramdown](https://kramdown.gettalong.org/)(Jekyll's markdown parser) works
45
46
  so I decided to respect this convention. It makes this plugin more consistent and universal._
46
47
 
47
- ### Macros
48
- You can define global macros in your `_config.yml` file:
48
+ ### Config
49
+ Jektex si highly configurable from your `_config.yml` file
50
+
51
+ **Disabling cache**
52
+ You can disable caching with `disable_disk_cache = true` in `_config.yml`. Cache is
53
+ enabled by default. You can find more information on [Jekyll official website](https://jekyllrb.com/docs/configuration/options/).
49
54
 
55
+ **Setting cache location**
56
+ By default jektex cache will be saved in `.jekyll-cache` directory. This results in it's
57
+ deletion when you call `jekyll clean`. To prevent cache deletion or you just want to
58
+ change location of cache for another reason you can achieve that by specifying
59
+ `cache_dir` in `_config.yml`.
50
60
  ```yaml
51
- # Jektex macros
52
- jektex-macros:
53
- - ["\\Q", "\\mathbb{Q}"]
54
- - ["\\C", "\\mathbb{C}"]
61
+ # Jektex cache dir location
62
+ jektex:
63
+ cache_dir: ".jektex-cache"
55
64
  ```
56
65
 
57
- ### Cache control
66
+ **Ignore**
67
+ By default jektex tries to render LaTeX in all files not excluded by Jekyll. But
68
+ sometimes you get in situation when you do not want to render some files. For example
69
+ _RSS feed_ with excerpts containing LaTeX. As a solution jektex offers `ignore` option.
70
+ You can use conventional wild cards using `*`. For example:
71
+ ```yaml
72
+ # Jektex ignore files
73
+ jektex:
74
+ ignore: ["*.xml", "README.md", "_drafts/*" ]
75
+ ```
58
76
 
59
- **Clearing cache**
60
- To clear cached expressions you have to delete `.jektex-cache` directory in your
61
- project directory.
77
+ This example configuration ignores all `.xml` files, `README.md` and all files
78
+ in `_drafts` directory.
62
79
 
63
- **Disabling cache**
64
- You can disable caching with `disable_disk_cache = false` in `_config.yml`. Cache is
65
- enabled by default.
80
+ Another option for ignoring specific posts is setting `jektex` tag in front matter of
81
+ post to `false`. For example:
82
+ ```yaml
83
+ ---
84
+ title: "How Jektex works"
85
+ category: "Development"
86
+ jektex: false
87
+ layout: post
88
+ ---
89
+ ```
66
90
 
67
- **Setting cache location**
68
- By default jektex cache will be saved in `.jekyll-cache` directory. This results in its
69
- deletion when you call `jekyll clean`. To prevent cache deletion or you just want to
70
- change location of cache from another reason you can achieve that specifying
71
- `jektex_cache_dir` in `_config.yml`.
91
+ Setting `jektex` tag to `true` or not setting at all will result in jektex rendering LaTeX
92
+ expressions in that post.
93
+
94
+ **Macros**
95
+ You can define global macros like this:
96
+ ```yaml
97
+ # Jektex macros
98
+ jektex:
99
+ macros:
100
+ - ["\\Q", "\\mathbb{Q}"]
101
+ - ["\\C", "\\mathbb{C}"]
102
+ ```
103
+ And yes you have to escape backlash(`\`) with another backlash. This is caused by
104
+ [yaml definition](https://yaml.org/).
72
105
 
73
- For example: `jektex_cache_dir: ".jektex-cache"`
106
+ **Complete examples**
107
+ Recommended config:
108
+ ```yaml
109
+ jektex:
110
+ cache_dir: ".jektex-cache"
111
+ ignore: ["*.xml"]
112
+ macros:
113
+ - ["\\Q", "\\mathbb{Q}"]
114
+ - ["\\C", "\\mathbb{C}"]
115
+ ```
116
+ Having no configuration is equivalent to this:
117
+ ```yaml
118
+ jektex:
119
+ cache_dir: ".jekyll-cache"
120
+ ignore: []
121
+ macros: []
122
+ ```
74
123
 
75
124
  ## Installation
76
125
  This plugin is available as a [RubyGem](https://rubygems.org/gems/jektex).
77
126
 
78
127
  **Using bundler**
79
128
  Add `jektex` to your `Gemfile` like this:
80
-
81
129
  ```ruby
82
130
  group :jekyll_plugins do
83
131
  gem "jektex"
@@ -100,6 +148,9 @@ and do not forget to add `katex.min.css` to you html head:
100
148
  ```html
101
149
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">
102
150
  ```
103
- It is much better practice to download **css** file and loaded 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.
104
152
  You can find more information on [KaTeX's website](https://katex.org/docs/browser.html).
105
153
 
154
+ ## Contributions and bug reports
155
+ Feel free to repost any bugs or even make feature request in [issues on official repository](https://github.com/yagarea/jektex/issues).
156
+ I am opened for pull requests as well.
data/lib/jektex/jektex.rb CHANGED
@@ -8,113 +8,143 @@ DEFAULT_CACHE_DIR = ".jekyll-cache"
8
8
  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
+ FRONT_MATTER_TAG = "jektex"
12
+ INDENT = " " * 13
13
+
11
14
  $global_macros = Hash.new
15
+ $updated_global_macros = Array.new
16
+
12
17
  $count_newly_generated_expressions = 0
18
+
13
19
  $path_to_cache = File.join(DEFAULT_CACHE_DIR, CACHE_FILE)
14
20
  $cache = nil
15
21
  $disable_disk_cache = false
16
22
 
17
- def convert(page)
23
+ $ignored = Array.new
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
+
35
+ def is_ignored?(page)
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
49
+ end
50
+
51
+ def render(page)
52
+ # check if document is not set to be ignored
53
+ return page.output if !page.data || is_ignored?(page)
18
54
  # convert HTML entities back to characters
19
55
  post = HTMLEntities.new.decode(page.output.to_s)
20
- post = post.gsub(/(\\\()((.|\n)*?)(?<!\\)\\\)/) { |m| escape_method($1, $2, page.path) }
21
- post = post.gsub(/(\\\[)((.|\n)*?)(?<!\\)\\\]/) { |m| escape_method($1, $2, page.path) }
56
+ # render inline expressions
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) }
22
60
  return post
23
61
  end
24
62
 
25
- def escape_method( type, string, doc_path )
26
- @display = false
27
-
28
- # detect if expression is display view
29
- case type.downcase
30
- when /\(/
31
- @display = false
32
- else /\[/
33
- @display = true
34
- end
63
+ def escape_method( type, expression, doc_path )
64
+ # detect if expression is in display mode
65
+ is_in_display_mode = type.downcase =~ /\[/
35
66
 
36
67
  # generate a hash from the math expression
37
- @expression_hash = Digest::SHA2.hexdigest(string) + @display.to_s
68
+ expression_hash = Digest::SHA2.hexdigest(expression) + is_in_display_mode.to_s
38
69
 
39
70
  # use it if it exists
40
- if($cache.has_key?(@expression_hash))
71
+ if($cache.has_key?(expression_hash) && !contains_updated_global_macro?(expression))
72
+ # check if expressin conains updated macro
41
73
  $count_newly_generated_expressions += 1
42
74
  print_stats
43
- return $cache[@expression_hash]
75
+ return $cache[expression_hash]
44
76
 
45
77
  # else generate one and store it
46
78
  else
47
79
  # create the cache directory, if it doesn't exist
48
80
  begin
49
81
  # render using ExecJS
50
- @result = KATEX.call("katex.renderToString", string,
51
- {displayMode: @display, macros: $global_macros})
82
+ result = KATEX.call("katex.renderToString", expression,
83
+ { displayMode: is_in_display_mode, macros: $global_macros})
52
84
  rescue SystemExit, Interrupt
53
85
  # save cache to disk
54
86
  File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
55
- # this stops jekyll being immune to interupts and kill command
87
+ # this stops jekyll being immune to interrupts and kill command
56
88
  raise
57
- rescue Exception => e
89
+ rescue ExecJS::ProgramError => pe
58
90
  # catch parse error
59
- 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"
60
92
  return PARSE_ERROR_PLACEHOLDER
61
93
  end
62
94
  # save to cache
63
- $cache[@expression_hash] = @result
95
+ $cache[expression_hash] = @result
64
96
  # update count of newly generated expressions
65
97
  $count_newly_generated_expressions += 1
66
98
  print_stats
67
- return @result
99
+ return result
68
100
  end
69
101
  end
70
102
 
71
- def print_stats
72
- print " LaTeX: " +
73
- ($count_newly_generated_expressions).to_s +
74
- " expressions rendered (" + $cache.size.to_s +
75
- " already cached) \r"
76
- $stdout.flush
77
- end
78
-
79
103
  Jekyll::Hooks.register :pages, :post_render do |page|
80
- page.output = convert(page)
104
+ page.output = render(page)
81
105
  end
82
106
 
83
107
  Jekyll::Hooks.register :documents, :post_render do |doc|
84
- doc.output = convert(doc)
108
+ doc.output = render(doc)
85
109
  end
86
110
 
87
111
  Jekyll::Hooks.register :site, :after_init do |site|
88
- # load macros from config file
89
- if site.config["jektex-macros"] != nil
90
- for macro_definition in site.config["jektex-macros"]
91
- $global_macros[macro_definition[0]] = macro_definition[1]
92
- end
93
- end
94
- # print macro information
95
- if $global_macros.size == 0
96
- puts " LaTeX: no macros loaded"
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)}
97
121
  else
98
- puts " LaTeX: " + $global_macros.size.to_s + " macro" +
99
- ($global_macros.size == 1 ? "" : "s") + " loaded"
122
+ $cache = Hash.new
100
123
  end
101
124
 
102
125
  # check if cache is disable in config
103
- if site.config["disable_disk_cache"] != nil
104
- $disable_disk_cache = site.config["disable_disk_cache"]
105
- end
126
+ $disable_disk_cache = site.config["disable_disk_cache"] if site.config.has_key?("disable_disk_cache")
106
127
 
107
- # check if there is defined custom cache location in config
108
- if site.config["jektex_cache_dir"] != nil
109
- $path_to_cache = File.join(site.config["jektex_cache_dir"].to_s, CACHE_FILE)
128
+ # load macros
129
+ if config.has_key?("macros")
130
+ for macro_definition in config["macros"]
131
+ $global_macros[macro_definition[0]] = macro_definition[1]
132
+ end
110
133
  end
111
134
 
112
- # load content of cache file if it exists
113
- if(File.exist?($path_to_cache))
114
- $cache = File.open($path_to_cache, "r"){|from_file| Marshal.load(from_file)}
135
+ # make list of updated macros
136
+ $updated_global_macros = get_list_of_updated_global_macros($global_macros, $cache["cached_global_macros"])
137
+ # print macro information
138
+ if $global_macros.empty?
139
+ puts "#{INDENT}LaTeX: no macros loaded"
115
140
  else
116
- $cache = Hash.new
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)")
117
144
  end
145
+
146
+ # load list of ignored files
147
+ $ignored = config["ignore"] if config.has_key?("ignore")
118
148
  end
119
149
 
120
150
  Jekyll::Hooks.register :site, :after_reset do
@@ -126,9 +156,13 @@ Jekyll::Hooks.register :site, :post_write do
126
156
  # print new line to prevent overwriting previous output
127
157
  print "\n"
128
158
  # check if caching is enabled
129
- 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
130
164
  # save cache to disk
131
- Dir.mkdir(File.dirname($path_to_cache)) unless File.exists?(File.dirname($path_to_cache))
132
165
  File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
133
166
  end
134
167
  end
168
+
@@ -1,3 +1,3 @@
1
1
  module Jektex
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.7"
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.4
4
+ version: 0.0.7
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-18 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