jektex 0.0.2 → 0.0.5
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 +99 -28
- data/lib/jektex/jektex.rb +67 -26
- data/lib/jektex/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 290626aa91c28cc4961baf40ec00dde81928da68e0a923ee84999027e7f3c9b0
|
4
|
+
data.tar.gz: 4ec8d501a4ab6f1b068ec01bb21a7d84bd844a5bca7d105bdc0c9c6e2652eec8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccdddba235b4d0462ccb5e4d2ee4cbf5b97e9964c10fd0395e814635281563c6363a381422feeefdd9eb6a895877a47aba6fae95de36c98a6f710785ed18ba51
|
7
|
+
data.tar.gz: 4d0a8dad642c30c5f26ca5903d715e3728d918bb17fe1eaeaf3ce8ad814a25e9c50d0df15533522275665978971ee269164a2969cf73db9823b71b9ea29a7217
|
data/README.md
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
Jekyll plugin for blazing fast server side cached LaTeX rendering with support of macros.
|
3
3
|
Enjoy comfort of latex and markdown without cluttering your site with bloated javascript.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Features
|
6
6
|
- Renders LaTeX formulas during Jekyll rendering
|
7
|
-
- Works without any javascript
|
7
|
+
- Works without any javascript on clients side
|
8
8
|
- Is faster than any other server side Jekyll latex renderer
|
9
9
|
- Supports user defined global macros
|
10
10
|
- Has I/O efficient caching system
|
@@ -13,25 +13,25 @@ Enjoy comfort of latex and markdown without cluttering your site with bloated ja
|
|
13
13
|
- Does not interfere with Jekyll workflow and project structure
|
14
14
|
- Marks invalid syntax in document
|
15
15
|
- Prints location of invalid expression during rendering
|
16
|
+
- Highly configurable but still having sensible defaults
|
16
17
|
|
17
18
|
## Usage
|
18
19
|
|
19
20
|
### Notation
|
20
21
|
**Inline formula**
|
21
|
-
Put formula between two pairs of
|
22
|
-
|
22
|
+
Put formula between two pairs of dolar signs (`$$`) inside of paragraph.
|
23
23
|
```latex
|
24
24
|
Lorem ipsum dolor sit amet, consectetur $$e^{i\theta}=\cos(\theta)+i\sin(\theta)$$
|
25
25
|
adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
26
26
|
```
|
27
27
|
|
28
28
|
**Display formula**
|
29
|
-
Put formula between two pairs of
|
29
|
+
Put formula between two pairs of dolar sings (`$$`) and surround it by two empty lines.
|
30
30
|
```latex
|
31
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
|
31
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
|
32
32
|
incididunt ut labore et dolore magna aliqua.
|
33
33
|
|
34
|
-
$$
|
34
|
+
$$ \left[ \frac{-\hbar^2}{2\mu}\nabla^2 + V(\mathbf{r},t)\right] \Psi(\mathbf{r},t) $$
|
35
35
|
|
36
36
|
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
|
37
37
|
ea commodo consequat.
|
@@ -39,45 +39,116 @@ ea commodo consequat.
|
|
39
39
|
|
40
40
|
_Why Jektex does not use conventional single `$` for inline formulas and double `$$` for
|
41
41
|
display mode?
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
This is how [kramdown](https://kramdown.gettalong.org/)(Jekyll's markdown parser) works
|
43
|
+
so I decided to respect this convention. It makes this plugin more consistent and universal._
|
44
|
+
|
45
|
+
### Config
|
46
|
+
Jektex si highly configurable from your `_config.yml` file
|
47
|
+
|
48
|
+
**Disabling cache**
|
49
|
+
You can disable caching with `disable_disk_cache = true` in `_config.yml`. Cache is
|
50
|
+
enabled by default. You can find more information on [Jekyll official website](https://jekyllrb.com/docs/configuration/options/).
|
51
|
+
|
52
|
+
**Setting cache location**
|
53
|
+
By default jektex cache will be saved in `.jekyll-cache` directory. This results in it's
|
54
|
+
deletion when you call `jekyll clean`. To prevent cache deletion or you just want to
|
55
|
+
change location of cache for another reason you can achieve that by specifying
|
56
|
+
`cache_dir` in `_config.yml`.
|
57
|
+
```yaml
|
58
|
+
# Jektex cache dir location
|
59
|
+
jektex:
|
60
|
+
cache_dir: ".jektex-cache"
|
61
|
+
```
|
62
|
+
|
63
|
+
**Ignore**
|
64
|
+
By default jektex tries to render LaTeX in all files not excluded by Jekyll. But
|
65
|
+
sometimes you get in situation when you do not want to render some files. For example
|
66
|
+
_RSS feed_ with excerpts containing LaTeX. As a solution jektex offers `ignore` option.
|
67
|
+
You can use conventional wild cards using `*`. For example:
|
68
|
+
```yaml
|
69
|
+
# Jektex ignore files
|
70
|
+
jektex:
|
71
|
+
ignore: ["*.xml", "README.md", "_drafts/*" ]
|
72
|
+
```
|
73
|
+
|
74
|
+
This example configuration ignores all `.xml` files, `README.md` and all files
|
75
|
+
in `_drafts` directory.
|
76
|
+
|
77
|
+
Another option for ignoring specific posts is setting `jektex` tag in front matter of
|
78
|
+
post to `false`. For example:
|
79
|
+
```yaml
|
80
|
+
---
|
81
|
+
title: "How Jektex works"
|
82
|
+
category: "Development"
|
83
|
+
jektex: false
|
84
|
+
layout: post
|
85
|
+
---
|
86
|
+
```
|
45
87
|
|
46
|
-
|
47
|
-
|
88
|
+
Setting `jektex` tag to `true` or not setting at all will result in jektex rendering LaTeX
|
89
|
+
expressions in that post.
|
48
90
|
|
91
|
+
**Macros**
|
92
|
+
You can define global macros like this:
|
49
93
|
```yaml
|
50
94
|
# Jektex macros
|
51
|
-
jektex
|
52
|
-
|
53
|
-
|
95
|
+
jektex:
|
96
|
+
macros:
|
97
|
+
- ["\\Q", "\\mathbb{Q}"]
|
98
|
+
- ["\\C", "\\mathbb{C}"]
|
99
|
+
```
|
100
|
+
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.
|
103
|
+
|
104
|
+
**Complete examples**
|
105
|
+
Recommended config:
|
106
|
+
```yaml
|
107
|
+
jektex:
|
108
|
+
cache_dir: ".jektex-cache"
|
109
|
+
ignore: ["*.xml"]
|
110
|
+
macros:
|
111
|
+
- ["\\Q", "\\mathbb{Q}"]
|
112
|
+
- ["\\C", "\\mathbb{C}"]
|
113
|
+
```
|
114
|
+
Having no configuration is equivalent to this:
|
115
|
+
```yaml
|
116
|
+
jektex:
|
117
|
+
cache_dir: ".jekyll-cache"
|
118
|
+
ignore: []
|
119
|
+
macros: []
|
54
120
|
```
|
55
121
|
|
56
122
|
## Installation
|
123
|
+
This plugin is available as a [RubyGem](https://rubygems.org/gems/jektex).
|
57
124
|
|
58
|
-
|
125
|
+
**Using bundler**
|
59
126
|
Add `jektex` to your `Gemfile` like this:
|
60
|
-
|
61
|
-
```yaml
|
127
|
+
```ruby
|
62
128
|
group :jekyll_plugins do
|
63
|
-
|
129
|
+
gem "jektex"
|
64
130
|
end
|
65
131
|
```
|
66
132
|
|
67
133
|
and run `bundle install`
|
68
134
|
|
69
|
-
|
70
|
-
Just run `gem install jektex`
|
71
|
-
file:
|
72
|
-
```
|
73
|
-
plugins:
|
74
|
-
- jektex
|
135
|
+
**Without bundler**
|
136
|
+
Just run `gem install jektex`
|
75
137
|
|
138
|
+
**After installation**
|
139
|
+
Add jektex to your plugin list in your `_config.yml` file:
|
140
|
+
```yaml
|
141
|
+
plugins:
|
142
|
+
- jektex
|
76
143
|
```
|
77
144
|
|
78
|
-
|
79
|
-
Do not forget to add `katex.min.css` to you html head:
|
145
|
+
and do not forget to add `katex.min.css` to you html head:
|
80
146
|
```html
|
81
147
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">
|
82
148
|
```
|
83
|
-
It is much better practice to download css file and
|
149
|
+
It is much better practice to download **css** file and load it as an asset from your server directly.
|
150
|
+
You can find more information on [KaTeX's website](https://katex.org/docs/browser.html).
|
151
|
+
|
152
|
+
## Contributions and bug reports
|
153
|
+
Feel free to repost any bugs or even make feature request in [issues on official repository](https://github.com/yagarea/jektex/issues).
|
154
|
+
I am opened for pull requests as well.
|
data/lib/jektex/jektex.rb
CHANGED
@@ -3,22 +3,40 @@ require 'digest'
|
|
3
3
|
require 'htmlentities'
|
4
4
|
|
5
5
|
|
6
|
-
PATH_TO_JS = __dir__
|
7
|
-
|
6
|
+
PATH_TO_JS = File.join(__dir__, "/katex.min.js")
|
7
|
+
DEFAULT_CACHE_DIR = ".jekyll-cache"
|
8
8
|
CACHE_FILE = "jektex-cache.marshal"
|
9
|
-
PATH_TO_CACHE = CACHE_DIR + CACHE_FILE
|
10
9
|
KATEX = ExecJS.compile(open(PATH_TO_JS).read)
|
11
10
|
PARSE_ERROR_PLACEHOLDER = "<b style='color: red;'>PARSE ERROR</b>"
|
11
|
+
FRONT_MATTER_TAG = "jektex"
|
12
12
|
$global_macros = Hash.new
|
13
13
|
$count_newly_generated_expressions = 0
|
14
|
+
$path_to_cache = File.join(DEFAULT_CACHE_DIR, CACHE_FILE)
|
14
15
|
$cache = nil
|
15
16
|
$disable_disk_cache = false
|
17
|
+
$ignored = Array.new
|
16
18
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
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
|
26
|
+
end
|
27
|
+
|
28
|
+
def render(page)
|
29
|
+
# 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
|
+
|
34
|
+
# convert HTML entities back to characters
|
35
|
+
post = HTMLEntities.new.decode(page.output.to_s)
|
36
|
+
# 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) }
|
22
40
|
return post
|
23
41
|
end
|
24
42
|
|
@@ -47,12 +65,12 @@ def escape_method( type, string, doc_path )
|
|
47
65
|
# create the cache directory, if it doesn't exist
|
48
66
|
begin
|
49
67
|
# render using ExecJS
|
50
|
-
@result = KATEX.call("katex.renderToString", string,
|
68
|
+
@result = KATEX.call("katex.renderToString", string,
|
51
69
|
{displayMode: @display, macros: $global_macros})
|
52
70
|
rescue SystemExit, Interrupt
|
53
71
|
# save cache to disk
|
54
|
-
File.open(
|
55
|
-
# this stops jekyll being immune to
|
72
|
+
File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
|
73
|
+
# this stops jekyll being immune to interrupts and kill command
|
56
74
|
raise
|
57
75
|
rescue Exception => e
|
58
76
|
# catch parse error
|
@@ -70,41 +88,65 @@ end
|
|
70
88
|
|
71
89
|
def print_stats
|
72
90
|
print " LaTeX: " +
|
73
|
-
($count_newly_generated_expressions).to_s +
|
74
|
-
" expressions rendered (" + $cache.size.to_s +
|
91
|
+
($count_newly_generated_expressions).to_s +
|
92
|
+
" expressions rendered (" + $cache.size.to_s +
|
75
93
|
" already cached) \r"
|
76
94
|
$stdout.flush
|
77
95
|
end
|
78
96
|
|
97
|
+
Jekyll::Hooks.register :pages, :post_render do |page|
|
98
|
+
page.output = render(page)
|
99
|
+
end
|
100
|
+
|
79
101
|
Jekyll::Hooks.register :documents, :post_render do |doc|
|
80
|
-
doc.output =
|
102
|
+
doc.output = render(doc)
|
81
103
|
end
|
82
104
|
|
83
105
|
Jekyll::Hooks.register :site, :after_init do |site|
|
84
|
-
|
85
|
-
|
86
|
-
|
106
|
+
if site.config["jektex"] == nil then
|
107
|
+
# if no config is defined make empty one
|
108
|
+
config = Hash.new
|
109
|
+
else
|
110
|
+
# load jektex config from config file
|
111
|
+
config = site.config["jektex"]
|
112
|
+
end
|
113
|
+
# load macros
|
114
|
+
if config["macros"] != nil then
|
115
|
+
for macro_definition in config["macros"]
|
87
116
|
$global_macros[macro_definition[0]] = macro_definition[1]
|
88
117
|
end
|
89
118
|
end
|
119
|
+
|
90
120
|
# print macro information
|
91
|
-
if $global_macros.size == 0
|
121
|
+
if $global_macros.size == 0 then
|
92
122
|
puts " LaTeX: no macros loaded"
|
93
123
|
else
|
94
|
-
puts " LaTeX: " + $global_macros.size.to_s + " macro" +
|
124
|
+
puts " LaTeX: " + $global_macros.size.to_s + " macro" +
|
95
125
|
($global_macros.size == 1 ? "" : "s") + " loaded"
|
96
126
|
end
|
97
127
|
|
98
|
-
if
|
99
|
-
|
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)
|
131
|
+
end
|
132
|
+
|
133
|
+
# load list of ignored files
|
134
|
+
if config["ignore"] != nil then
|
135
|
+
$ignored = config["ignore"]
|
100
136
|
end
|
101
137
|
|
102
138
|
# load content of cache file if it exists
|
103
|
-
if(File.exist?(
|
104
|
-
$cache = File.open(
|
139
|
+
if(File.exist?($path_to_cache)) then
|
140
|
+
$cache = File.open($path_to_cache, "r"){|from_file| Marshal.load(from_file)}
|
105
141
|
else
|
106
142
|
$cache = Hash.new
|
107
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
|
+
|
108
150
|
end
|
109
151
|
|
110
152
|
Jekyll::Hooks.register :site, :after_reset do
|
@@ -115,11 +157,10 @@ end
|
|
115
157
|
Jekyll::Hooks.register :site, :post_write do
|
116
158
|
# print new line to prevent overwriting previous output
|
117
159
|
print "\n"
|
118
|
-
puts
|
119
160
|
# check if caching is enabled
|
120
161
|
if $disable_disk_cache == false
|
121
162
|
# save cache to disk
|
122
|
-
Dir.mkdir(
|
123
|
-
File.open(
|
163
|
+
Dir.mkdir(File.dirname($path_to_cache)) unless File.exists?(File.dirname($path_to_cache))
|
164
|
+
File.open($path_to_cache, "w"){|to_file| Marshal.dump($cache, to_file)}
|
124
165
|
end
|
125
166
|
end
|
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.5
|
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-
|
11
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|