jekyll-spaceship 0.8.7 → 0.9.4

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: c04f1aada8ea0a1dde37b51418f843e1d163e1dd7230cf602a0f7caf5d787b19
4
- data.tar.gz: 263b035717beeedaad26f42c896a2265b3be4e9bf977b2883e23d8b678f280db
3
+ metadata.gz: cbba69bcf95b309c36da702cce9670212f7a32985e2522f13b06fdc0058e0b60
4
+ data.tar.gz: 679ee30cad6abfe6c6fb271e3816bff2e16f931b94492d0e0223f4dba11263f4
5
5
  SHA512:
6
- metadata.gz: 566854587a4dea0b991d755467dd402cc39a86235636c9e95c1fbd042ae6ee7bc28bd26ffd99b0d12a8e56ffcff469193bab5008d319e8408949382dec162bdb
7
- data.tar.gz: c79139b158834943705be273a533beef706d028fcbff9f339f08aba027ec85a872c73a522679ab2b69d09c82f6c7bd8f8f551f33bfd369040b510b3db36859c5
6
+ metadata.gz: 207137e6fedec9521c2cde3a3215cf7f1ccbc81f6ce0385c385a1c48d31a1ba7d03b3c532e0cbde80ce2f8d33e79a770d299d64cc436acddfc03ed651a2e9fc4
7
+ data.tar.gz: 1c78e2e73e99f7c3e007e3cbcea683b1d4a4db5771737530865be9262d42adf5617e6d7b9cb9931b4947937fdc64d927bf38967121b2dc98d1107d5bec01cace
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format progress
3
+ --require spec_helper
@@ -1,13 +1,13 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - 2.7
5
- - 2.3
4
+ - 2.7
5
+ - 2.3
6
6
  env:
7
7
  global:
8
- - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
8
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
9
9
  matrix:
10
- - JEKYLL_VERSION="~> 3.8"
10
+ - JEKYLL_VERSION="~> 3.8"
11
11
  matrix:
12
12
  include:
13
13
  - rvm: 2.7
@@ -15,8 +15,8 @@ matrix:
15
15
  - rvm: 2.7
16
16
  env: JEKYLL_VERSION=">= 4.0.0"
17
17
  before_install:
18
- - gem update --system
19
- - gem install bundler
18
+ - gem update --system
19
+ - gem install bundler
20
20
  before_script: bundle update
21
21
  script: script/cibuild
22
22
  notifications:
data/README.md CHANGED
@@ -107,11 +107,14 @@ Spaceship is a minimalistic, powerful and extremely customizable [Jekyll](https:
107
107
  - [2.2 How to use?](#22-how-to-use)
108
108
  - [3. PlantUML Usage](#3-plantuml-usage)
109
109
  - [4. Mermaid Usage](#4-mermaid-usage)
110
- - [5. Video Usage](#5-video-usage)
110
+ - [5. Media Usage](#5-media-usage)
111
111
  - [5.1 Youtube Usage](#youtube-usage)
112
112
  - [5.2 Vimeo Usage](#vimeo-usage)
113
113
  - [5.3 DailyMotion Usage](#dailymotion-usage)
114
- - [5.4 General Video Usage](#general-video-usage)
114
+ - [5.4 Spotify Usage](#spotify-usage)
115
+ - [5.5 SoundCloud Usage](#soundcloud-usage)
116
+ - [5.6 General Video Usage](#general-video-usage)
117
+ - [5.7 General Audio Usage](#general-audio-usage)
115
118
  - [6. Hybrid HTML with Markdown](#6-hybrid-html-with-markdown)
116
119
  - [7. Markdown Polyfill](#7-markdown-polyfill)
117
120
  - [7.1 Escape Ordered List](#71-escape-ordered-list)
@@ -143,7 +146,7 @@ plugins:
143
146
 
144
147
  **💡 Tip:** Note that GitHub Pages runs in `safe` mode and only allows [a set of whitelisted plugins](https://pages.github.com/versions/). To use the gem in GitHub Pages, you need to build locally or use CI (e.g. [travis](https://travis-ci.org/), [github workflow](https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow)) and deploy to your `gh-pages` branch.
145
148
 
146
- ### Additions
149
+ ### Additions for Unlimited GitHub Pages
147
150
 
148
151
  * Here is a GitHub Action named [jekyll-deploy-action](https://github.com/jeffreytse/jekyll-deploy-action) for Jekyll site deployment conveniently. 👍
149
152
  * Here is a [Jekyll site](https://github.com/jeffreytse/jekyll-jeffreytse-blog) using Travis to build and deploy to GitHub Pages for your references.
@@ -162,16 +165,20 @@ jekyll-spaceship:
162
165
  - plantuml-processor
163
166
  - mermaid-processor
164
167
  - polyfill-processor
165
- - video-processor
168
+ - media-processor
166
169
  - emoji-processor
167
170
  - element-processor
168
171
  mathjax-processor:
169
- src: //cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
172
+ src:
173
+ - https://polyfill.io/v3/polyfill.min.js?features=es6
174
+ - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
170
175
  config:
171
- tex2jax:
176
+ tex:
172
177
  inlineMath:
173
178
  - ['$','$']
174
179
  - ['\(','\)']
180
+ svg:
181
+ fontCache: 'global'
175
182
  plantuml-processor:
176
183
  mode: default # mode value 'pre-fetch' for fetching image at building stage
177
184
  css:
@@ -179,7 +186,7 @@ jekyll-spaceship:
179
186
  syntax:
180
187
  code: 'plantuml!'
181
188
  custom: ['@startuml', '@enduml']
182
- src: http://www.plantuml.com/plantuml/png/
189
+ src: http://www.plantuml.com/plantuml/svg/
183
190
  mermaid-processor:
184
191
  mode: default # mode value 'pre-fetch' for fetching image at building stage
185
192
  css:
@@ -190,14 +197,14 @@ jekyll-spaceship:
190
197
  config:
191
198
  theme: default
192
199
  src: https://mermaid.ink/svg/
193
- video-processor:
200
+ media-processor:
194
201
  default:
195
- id: 'video-{id}'
196
- class: 'video'
202
+ id: 'media-{id}'
203
+ class: 'media'
197
204
  width: '100%'
198
205
  height: 350
199
- border: 0
200
- style: 'max-width: 600px'
206
+ frameborder: 0
207
+ style: 'max-width: 600px; outline: none;'
201
208
  allow: 'encrypted-media; picture-in-picture'
202
209
  emoji-processor:
203
210
  css:
@@ -630,7 +637,7 @@ Code above would be parsed as:
630
637
 
631
638
  ### 3. PlantUML Usage
632
639
 
633
- [PlantUML](http://plantuml.sourceforge.net/) is a component that allows to quickly write:
640
+ [PlantUML](https://plantuml.com) is a component that allows to quickly write:
634
641
 
635
642
  - sequence diagram,
636
643
  - use case diagram,
@@ -701,25 +708,31 @@ Code above would be parsed as:
701
708
 
702
709
  ![Mermaid Diagram](https://user-images.githubusercontent.com/9413601/85282355-2e317300-b4be-11ea-9c30-8f9d61540d14.png)
703
710
 
704
- ### 5. Video Usage
711
+ ### 5. Media Usage
705
712
 
706
- How often did you find yourself googling "**How to embed a video in markdown?**"
713
+ How often did you find yourself googling "**How to embed a video/audio in markdown?**"
707
714
 
708
- While its not possible to embed a video in markdown, the best and easiest way is to extract a frame from the video. To add videos to your markdown files easier I developped this tool for you, and it will parse the video link inside the image block automatically.
715
+ While its not possible to embed a video/audio in markdown, the best and easiest
716
+ way is to extract a frame from the video/audio. To add videos/audios to your
717
+ markdown files easier I developped this tool for you, and it will parse the
718
+ video/audio link inside the image block automatically.
709
719
 
710
- **For now, these video links parsing are provided:**
720
+ **For now, these media links parsing are provided:**
711
721
 
712
722
  - Youtube
713
723
  - Vimeo
714
724
  - DailyMotion
715
- - General Video ( mp4 | avi | webm | ogg | ogv | 3gp | flv | mov ... )
725
+ - Spotify
726
+ - SoundCloud
727
+ - General Video ( mp4 | avi | ogg | ogv | webm | 3gp | flv | mov ... )
728
+ - General Audio ( mp3 | wav | ogg | mid | midi | aac | wma ... )
716
729
 
717
- There are two ways to embed a video in your Jekyll blog page:
730
+ There are two ways to embed a video/audio in your Jekyll blog page:
718
731
 
719
732
  Inline-style:
720
733
 
721
734
  ```markdown
722
- ![]({video-link})
735
+ ![]({media-link})
723
736
  ```
724
737
 
725
738
  Reference-style:
@@ -727,10 +740,10 @@ Reference-style:
727
740
  ```markdown
728
741
  ![][{reference}]
729
742
 
730
- [{reference}]: {video-link}
743
+ [{reference}]: {media-link}
731
744
  ```
732
745
 
733
- For configuring video attributes (e.g, width, height), just adding query string to
746
+ For configuring media attributes (e.g, width, height), just adding query string to
734
747
  the link as below:
735
748
 
736
749
  ```markdown
@@ -763,6 +776,22 @@ the link as below:
763
776
  ![](https://dai.ly/x7tgcev?width=100%&height=400)
764
777
  ```
765
778
 
779
+ #### Spotify Usage
780
+
781
+ ```markdown
782
+ ![](http://open.spotify.com/track/4Dg5moVCTqxAb7Wr8Dq2T5)
783
+ ```
784
+
785
+ <image width="600" src="https://user-images.githubusercontent.com/9413601/89762618-5d11b000-db23-11ea-81db-35cc3682b234.png">
786
+
787
+ #### SoundCloud Usage
788
+
789
+ ```markdown
790
+ ![](https://soundcloud.com/aviciiofficial/preview-avicii-vs-lenny)
791
+ ```
792
+
793
+ <image width="600" src="https://user-images.githubusercontent.com/9413601/89762969-1c666680-db24-11ea-97e3-4340f7fac7ac.png">
794
+
766
795
  #### General Video Usage
767
796
 
768
797
  ```markdown
@@ -773,6 +802,15 @@ the link as below:
773
802
  ![](//techslides.com/demos/sample-videos/small.mp4?width=400)
774
803
  ```
775
804
 
805
+ #### General Audio Usage
806
+
807
+ ```markdown
808
+ ![](//www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3)
809
+
810
+ ![](//www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3?autoplay=1&loop=1)
811
+ ```
812
+
813
+ <image width="300" src="https://user-images.githubusercontent.com/9413601/89762143-68181080-db22-11ea-8467-e8b2a8a96ae5.png">
776
814
 
777
815
  ### 6. Hybrid HTML with Markdown
778
816
 
@@ -928,7 +966,7 @@ Automatically adds a `target="_blank" rel="noopener noreferrer"` attribute to al
928
966
  jekyll-spaceship:
929
967
  element-processor:
930
968
  css:
931
- - a: # Replce all `a` tags
969
+ - a: # Replace all `a` tags
932
970
  props:
933
971
  class: ['(^.*$)', '\0 ext-link'] # Add `ext-link` to class by regex pattern
934
972
  target: _blank # Replace `target` value to `_blank`
@@ -944,9 +982,9 @@ Automatically adds `loading="lazy"` to `img` and `iframe` tags to natively load
944
982
  jekyll-spaceship:
945
983
  element-processor:
946
984
  css:
947
- - a: # Replce all `a` tags
985
+ - a: # Replace all `a` tags
948
986
  props: #
949
- loading: lazy # Replace `lading` value to `lazy`
987
+ loading: lazy # Replace `loading` value to `lazy`
950
988
  ```
951
989
 
952
990
  In case you want to prevent loading some images/iframes lazily, add
@@ -959,7 +997,7 @@ See the following examples to prevent lazy loading.
959
997
  jekyll-spaceship:
960
998
  element-processor:
961
999
  css:
962
- - a: # Replce all `a` tags
1000
+ - a: # Replace all `a` tags
963
1001
  props: #
964
1002
  loading: eager # Replace `loading` value to `eager`
965
1003
  ```
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.version = Jekyll::Spaceship::VERSION
10
10
  spec.authors = ["jeffreytse"]
11
11
  spec.email = ["jeffreytse.mail@gmail.com"]
12
- spec.summary = "A Jekyll plugin to provide powerful supports for table, mathjax, plantuml, mermaid, emoji, video, youtube, vimeo, dailymotion, etc."
12
+ spec.summary = "A Jekyll plugin to provide powerful supports for table, mathjax, plantuml, mermaid, emoji, video, audio, youtube, vimeo, dailymotion, spotify, soundcloud, etc."
13
13
  spec.homepage = "https://github.com/jeffreytse/jekyll-spaceship"
14
14
  spec.license = "MIT"
15
15
 
@@ -10,7 +10,7 @@ module Jekyll::Spaceship
10
10
  'plantuml-processor',
11
11
  'mermaid-processor',
12
12
  'polyfill-processor',
13
- 'video-processor',
13
+ 'media-processor',
14
14
  'emoji-processor',
15
15
  'element-processor'
16
16
  ]
@@ -116,7 +116,7 @@ module Jekyll::Spaceship
116
116
  if self.respond_to? method
117
117
  @page.content = self.pre_exclude @page.content
118
118
  @page.content = self.send method, @page.content
119
- @page.content = self.after_exclude @page.content
119
+ @page.content = self.post_exclude @page.content
120
120
  end
121
121
  else
122
122
  if Type.html? output_ext
@@ -151,8 +151,8 @@ module Jekyll::Spaceship
151
151
  logger.log file
152
152
  end
153
153
 
154
- def pre_exclude(content)
155
- @exclusion_store = []
154
+ def exclusion_regexs()
155
+ regexs = []
156
156
  @exclusions.each do |type|
157
157
  regex = nil
158
158
  if type == :code
@@ -160,9 +160,16 @@ module Jekyll::Spaceship
160
160
  elsif type == :math
161
161
  regex = /(((?<!\\)\${1,2})[^\n]*?\1)/
162
162
  elsif type == :liquid_filter
163
- regex = /((?<!\\)\{\{[^\n]*?\}\})/
163
+ regex = /((?<!\\)((\{\{[^\n]*?\}\})|(\{%[^\n]*?%\})))/
164
164
  end
165
- next if regex.nil?
165
+ regexs.push regex unless regex.nil?
166
+ end
167
+ regexs
168
+ end
169
+
170
+ def pre_exclude(content, regexs = self.exclusion_regexs())
171
+ @exclusion_store = []
172
+ regexs.each do |regex|
166
173
  content.scan(regex) do |match_data|
167
174
  match = match_data[0]
168
175
  id = @exclusion_store.size
@@ -173,7 +180,7 @@ module Jekyll::Spaceship
173
180
  content
174
181
  end
175
182
 
176
- def after_exclude(content)
183
+ def post_exclude(content)
177
184
  while @exclusion_store.size > 0
178
185
  match = @exclusion_store.pop
179
186
  id = @exclusion_store.size
@@ -192,5 +199,38 @@ module Jekyll::Spaceship
192
199
  end
193
200
  content
194
201
  end
202
+
203
+ def self.fetch_img_data(url)
204
+ begin
205
+ res = Net::HTTP.get_response URI(url)
206
+ raise res.body unless res.is_a?(Net::HTTPSuccess)
207
+ content_type = res.header['Content-Type']
208
+ raise 'Unknown content type!' if content_type.nil?
209
+ content_body = res.body.force_encoding('UTF-8')
210
+ return {
211
+ 'type' => content_type,
212
+ 'body' => content_body
213
+ }
214
+ rescue StandardError => msg
215
+ logger.log msg
216
+ end
217
+ end
218
+
219
+ def self.make_img_tag(data)
220
+ css_class = data['class']
221
+ type = data['type']
222
+ body = data['body']
223
+ if type == 'url'
224
+ "<img class=\"#{css_class}\" src=\"#{body}\">"
225
+ elsif type.include?('svg')
226
+ body.gsub(/\<\?xml.*?\?>/, '')
227
+ .gsub(/<!--[^\0]*?-->/, '')
228
+ .sub(/<svg /, "<svg class=\"#{css_class}\" ")
229
+ else
230
+ body = Base64.encode64(body)
231
+ body = "data:#{type};base64, #{body}"
232
+ "<img class=\"#{css_class}\" src=\"#{body}\">"
233
+ end
234
+ end
195
235
  end
196
236
  end
@@ -6,9 +6,13 @@ module Jekyll::Spaceship
6
6
  class MathjaxProcessor < Processor
7
7
  def self.config
8
8
  {
9
- 'src' => '//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML',
9
+ 'src' => [
10
+ 'https://polyfill.io/v3/polyfill.min.js?features=es6',
11
+ 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js',
12
+ ],
10
13
  'config' => {
11
- 'tex2jax' => { 'inlineMath' => [['$','$'], ['\\(','\\)']] }
14
+ 'tex' => { 'inlineMath' => [['$','$'], ['\\(','\\)']] },
15
+ 'svg': { 'fontCache': 'global' }
12
16
  }
13
17
  }
14
18
  end
@@ -27,8 +31,15 @@ module Jekyll::Spaceship
27
31
 
28
32
  self.handled = true
29
33
 
30
- cfg = "MathJax.Hub.Config(#{config['config'].to_json});"
31
- head.add_child("<script src=\"#{config['src']}\">#{cfg}</script>")
34
+ # add mathjax config
35
+ cfg = config['config'].to_json
36
+ head.add_child("<script>MathJax=#{cfg}</script>")
37
+
38
+ # add mathjax dependencies
39
+ config['src'] = [config['src']] if config['src'].is_a? String
40
+ config['src'].each do |src|
41
+ head.add_child("<script src=\"#{src}\"></script>")
42
+ end
32
43
 
33
44
  doc.to_html
34
45
  end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require "nokogiri"
5
+
6
+ module Jekyll::Spaceship
7
+ class MediaProcessor < Processor
8
+ def self.config
9
+ {
10
+ 'default' => {
11
+ 'id' => 'media-{id}',
12
+ 'class' => 'media',
13
+ 'width' => '100%',
14
+ 'height' => 350,
15
+ 'frameborder' => 0,
16
+ 'style' => 'max-width: 600px;outline: none',
17
+ 'allow' => 'encrypted-media; picture-in-picture'
18
+ }
19
+ }
20
+ end
21
+
22
+ def on_handle_html(content)
23
+ # use nokogiri to parse html content
24
+ doc = Nokogiri::HTML(content)
25
+ # handle each img tag
26
+ doc.css('img').each do |element|
27
+ handle_normal_audio(element)
28
+ handle_normal_video(element)
29
+ handle_youtube(element)
30
+ handle_vimeo(element)
31
+ handle_dailymotion(element)
32
+ handle_spotify(element)
33
+ handle_soundcloud(element)
34
+ end
35
+ doc.to_html
36
+ end
37
+
38
+ # Examples:
39
+ # ![audio](//www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3)
40
+ # ![audio](//www.expample.com/examples/t-rex-roar.mp3?autoplay=true&loop=true)
41
+ def handle_normal_audio(element)
42
+ handle_media(element, {
43
+ media_type: 'audio',
44
+ host: '(https?:\\/\\/)?.*\\/',
45
+ id: '(.+?\\.(mp3|wav|ogg|mid|midi|aac|wma))',
46
+ })
47
+ end
48
+
49
+
50
+ # Examples:
51
+ # ![video](//www.html5rocks.com/en/tutorials/video/basics/devstories.webm)
52
+ # ![video](//techslides.com/demos/sample-videos/small.ogv?allow=autoplay)
53
+ # ![video](//techslides.com/demos/sample-videos/small.mp4?width=400)
54
+ def handle_normal_video(element)
55
+ handle_media(element, {
56
+ media_type: 'iframe',
57
+ host: '(https?:\\/\\/)?.*\\/',
58
+ id: '(.+?\\.(avi|mp4|webm|ogg|ogv|flv|mkv|mov|wmv|3gp|rmvb|asf))'
59
+ })
60
+ end
61
+
62
+ # Examples:
63
+ # ![youtube](https://www.youtube.com/watch?v=XA2WjJbmmoM "title")
64
+ # ![youtube](http://www.youtube.com/embed/w-m_yZCLF5Q)
65
+ # ![youtube](//youtu.be/mEP3YXaSww8?height=100%&width=400)
66
+ def handle_youtube(element)
67
+ handle_media(element, {
68
+ media_type: 'iframe',
69
+ host: '(https?:)?\\/\\/.*youtu.*',
70
+ id: '(?<=\\?v\\=|embed\\/|\\.be\\/)([a-zA-Z0-9\\_\\-]+)',
71
+ base_url: "https://www.youtube.com/embed/"
72
+ })
73
+ end
74
+
75
+ # Examples:
76
+ # ![vimeo](https://vimeo.com/263856289)
77
+ # ![vimeo](https://vimeo.com/263856289?height=100%&width=400)
78
+ def handle_vimeo(element)
79
+ handle_media(element, {
80
+ media_type: 'iframe',
81
+ host: '(https?:)?\\/\\/vimeo\\.com\\/',
82
+ id: '([0-9]+)',
83
+ base_url: "https://player.vimeo.com/video/"
84
+ })
85
+ end
86
+
87
+ # Examples:
88
+ # ![dailymotion](https://www.dailymotion.com/video/x7tgcev)
89
+ # ![dailymotion](https://dai.ly/x7tgcev?height=100%&width=400)
90
+ def handle_dailymotion(element)
91
+ handle_media(element, {
92
+ media_type: 'iframe',
93
+ host: '(https?:)?\\/\\/.*dai.?ly.*',
94
+ id: '(?<=video\\/|\\/)([a-zA-Z0-9\\_\\-]+)',
95
+ base_url: "https://www.dailymotion.com/embed/video/"
96
+ })
97
+ end
98
+
99
+ # Examples:
100
+ # ![spotify](//open.spotify.com/track/4Dg5moVCTqxAb7Wr8Dq2T5)
101
+ # ![spotify](//open.spotify.com/track/37mEkAaqCE7FXMvnlVA8pp?width=400)
102
+ def handle_spotify(element)
103
+ handle_media(element, {
104
+ media_type: 'iframe',
105
+ host: '(https?:)?\\/\\/open\\.spotify\\.com\\/track\\/',
106
+ id: '(?<=track\\/)([a-zA-Z0-9\\_\\-]+)',
107
+ base_url: "https://open.spotify.com/embed/track/",
108
+ height: 80
109
+ })
110
+ end
111
+
112
+ # Examples:
113
+ # ![soundcloud](//soundcloud.com/aviciiofficial/preview-avicii-vs-lenny)
114
+ def handle_soundcloud(element)
115
+ handle_media(element, {
116
+ media_type: 'iframe',
117
+ id_from: 'html',
118
+ host: '(https?:)?\\/\\/soundcloud\\.com\\/.+\\/[^\\?]+',
119
+ id: '(?<=soundcloud:\\/\\/sounds:)([0-9]+)',
120
+ base_url: "https://w.soundcloud.com/player/?url="\
121
+ "https%3A//api.soundcloud.com/tracks/",
122
+ height: 125,
123
+ })
124
+ end
125
+
126
+ def handle_media(element, data)
127
+ host = data[:host]
128
+ src = element.get_attribute('src')
129
+ title = element.get_attribute('title')
130
+ id = data[:id_from] === 'html' ? '()' : data[:id]
131
+ match_data = src.match(/#{host}#{id}\S*/)
132
+ return if match_data.nil?
133
+
134
+ media_type = data[:media_type]
135
+ base_url = data[:base_url]
136
+ id = data[:id_from] === 'html' \
137
+ ? get_id_from_html(src, data[:id]) \
138
+ : match_data[2]
139
+ qs = src.match(/(?<=\?)(\S*?)$/)
140
+ qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
141
+ next true if v == id or v == ''
142
+ end
143
+
144
+ cfg = self.config['default'].clone
145
+ cfg['id'] = qs['id'] || cfg['id']
146
+ cfg['class'] = qs['class'] || cfg['class']
147
+ cfg['style'] = qs['style'] || cfg['style']
148
+ cfg['id'] = cfg['id'].gsub('{id}', id)
149
+ cfg['class'] = cfg['class'].gsub('{id}', id)
150
+
151
+ cfg['src'] = URI(base_url ? "#{base_url}#{id}" : src).tap do |v|
152
+ v.query = URI.encode_www_form(qs) if qs.size > 0
153
+ end
154
+
155
+ case media_type
156
+ when 'audio'
157
+ cfg['autoplay'] = qs['autoplay'] || data[:autoplay] || cfg['autoplay']
158
+ cfg['loop'] = qs['loop'] || data[:loop] || cfg['loop']
159
+ cfg['style'] += ';display: none;' if qs['hidden']
160
+ handle_audio(element, { cfg: cfg })
161
+ when 'iframe'
162
+ cfg['title'] = title
163
+ cfg['width'] = qs['width'] || data[:width] || cfg['width']
164
+ cfg['height'] = qs['height'] || data[:height] || cfg['height']
165
+ cfg['frameborder'] = qs['frameborder'] || cfg['frameborder']
166
+ cfg['allow'] ||= cfg['allow']
167
+ handle_iframe(element, { cfg: cfg })
168
+ end
169
+ self.handled = true
170
+ end
171
+
172
+ def handle_audio(element, data)
173
+ cfg = data[:cfg]
174
+ html = "<audio"\
175
+ " id=\"#{cfg['id']}\""\
176
+ " class=\"#{cfg['class']}\""\
177
+ " #{cfg['autoplay'] ? 'autoplay' : ''}"\
178
+ " #{cfg['loop'] ? 'loop' : ''}"\
179
+ " src=\"#{cfg['src']}\""\
180
+ " style=\"#{cfg['style']}\""\
181
+ " controls>" \
182
+ "<p> Your browser doesn't support HTML5 audio."\
183
+ " Here is a <a href=\"#{cfg['src']}\">link to download the audio</a>"\
184
+ "instead. </p>"\
185
+ "</audio>"
186
+ doc = Nokogiri::XML(html)
187
+ element.replace(doc.children.first)
188
+ end
189
+
190
+ def handle_iframe(element, data)
191
+ cfg = data[:cfg]
192
+ html = "<iframe"\
193
+ " id=\"#{cfg['id']}\""\
194
+ " class=\"#{cfg['class']}\""\
195
+ " src=\"#{cfg['src']}\""\
196
+ " title=\"#{cfg['title']}\""\
197
+ " width=\"#{cfg['width']}\""\
198
+ " height=\"#{cfg['height']}\""\
199
+ " style=\"#{cfg['style']}\""\
200
+ " allow=\"#{cfg['allow']}\""\
201
+ " frameborder=\"#{cfg['frameborder']}\""\
202
+ " allowfullscreen>"\
203
+ "</iframe>"
204
+ doc = Nokogiri::XML(html)
205
+ element.replace(doc.children.first)
206
+ end
207
+
208
+ def get_id_from_html(url, pattern)
209
+ id = ''
210
+ begin
211
+ url = 'https:' + url if url.start_with? '//'
212
+ res = Net::HTTP.get_response URI(url)
213
+ raise res.body unless res.is_a?(Net::HTTPSuccess)
214
+ res.body.match pattern do |match_data|
215
+ id = match_data[0]
216
+ break
217
+ end
218
+ rescue StandardError => msg
219
+ data = url
220
+ logger.log msg
221
+ end
222
+ id
223
+ end
224
+ end
225
+ end
@@ -62,18 +62,20 @@ module Jekyll::Spaceship
62
62
  def handle_mermaid(code)
63
63
  # encode to UTF-8
64
64
  code = code.encode('UTF-8')
65
-
66
65
  url = get_url(code)
67
66
 
68
67
  # render mode
69
68
  case self.config['mode']
70
69
  when 'pre-fetch'
71
- url = self.get_mermaid_img_data(url)
70
+ data = self.class.fetch_img_data(url)
71
+ end
72
+ if data.nil?
73
+ data = { 'type' => 'url', 'body' => url }
72
74
  end
73
75
 
74
76
  # return img tag
75
- css_class = self.config['css']['class']
76
- "<img class=\"#{css_class}\" src=\"#{url}\">"
77
+ data['class'] = self.config['css']['class']
78
+ self.class.make_img_tag(data)
77
79
  end
78
80
 
79
81
  def get_url(code)
@@ -96,21 +98,5 @@ module Jekyll::Spaceship
96
98
  raise "No supported src ! #{src}"
97
99
  end
98
100
  end
99
-
100
- def get_mermaid_img_data(url)
101
- data = ''
102
- begin
103
- res = Net::HTTP.get_response URI(url)
104
- raise res.body unless res.is_a?(Net::HTTPSuccess)
105
- data = Base64.encode64(res.body)
106
- content_type = res.header['Content-Type']
107
- raise 'Unknown content type!' if content_type.nil?
108
- data = "data:#{content_type};base64, #{data}"
109
- rescue StandardError => msg
110
- data = url
111
- logger.log msg
112
- end
113
- data
114
- end
115
101
  end
116
102
  end
@@ -17,7 +17,7 @@ module Jekyll::Spaceship
17
17
  'css' => {
18
18
  'class' => 'plantuml'
19
19
  },
20
- 'src' => 'http://www.plantuml.com/plantuml/png/'
20
+ 'src' => 'http://www.plantuml.com/plantuml/svg/'
21
21
  }
22
22
  end
23
23
 
@@ -59,18 +59,20 @@ module Jekyll::Spaceship
59
59
  def handle_plantuml(code)
60
60
  # wrap plantuml code
61
61
  code = "@startuml#{code}@enduml".encode('UTF-8')
62
-
63
- url = get_url(code)
62
+ url = self.get_url(code)
64
63
 
65
64
  # render mode
66
65
  case self.config['mode']
67
66
  when 'pre-fetch'
68
- url = self.get_plantuml_img_data(url)
67
+ data = self.class.fetch_img_data(url)
68
+ end
69
+ if data.nil?
70
+ data = { 'type' => 'url', 'body' => url }
69
71
  end
70
72
 
71
73
  # return img tag
72
- css_class = self.config['css']['class']
73
- "<img class=\"#{css_class}\" src=\"#{url}\">"
74
+ data['class'] = self.config['css']['class']
75
+ self.class.make_img_tag(data)
74
76
  end
75
77
 
76
78
  def get_url(code)
@@ -87,21 +89,5 @@ module Jekyll::Spaceship
87
89
  raise "No supported src ! #{src}"
88
90
  end
89
91
  end
90
-
91
- def get_plantuml_img_data(url)
92
- data = ''
93
- begin
94
- res = Net::HTTP.get_response URI(url)
95
- raise res.body unless res.is_a?(Net::HTTPSuccess)
96
- data = Base64.encode64(res.body)
97
- content_type = res.header['Content-Type']
98
- raise 'Unknown content type!' if content_type.nil?
99
- data = "data:#{content_type};base64, #{data}"
100
- rescue StandardError => msg
101
- data = url
102
- logger.log msg
103
- end
104
- data
105
- end
106
92
  end
107
93
  end
@@ -305,10 +305,12 @@ module Jekyll::Spaceship
305
305
  cvter = self.converter('markdown')
306
306
  return if cvter.nil?
307
307
  content = cell.inner_html
308
+ content = self.pre_exclude(content, [/(\<code.*\>.*\<\/code\>)/])
308
309
  .gsub(/(?<!\\)\|/, '\\|')
309
310
  .gsub(/^\s+|\s+$/, '')
310
311
  .gsub(/&lt;/, '<')
311
312
  .gsub(/&gt;/, '>')
313
+ content = self.post_exclude(content)
312
314
  content = cvter.convert(content)
313
315
  content = Nokogiri::HTML.fragment(content)
314
316
  if content.children.first&.name == 'p'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Spaceship
5
- VERSION = "0.8.7"
5
+ VERSION = "0.9.4"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-spaceship
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.7
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - jeffreytse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-30 00:00:00.000000000 Z
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -124,6 +124,7 @@ files:
124
124
  - ".codeclimate.yml"
125
125
  - ".github/FUNDING.yml"
126
126
  - ".gitignore"
127
+ - ".rspec"
127
128
  - ".travis.yml"
128
129
  - Gemfile
129
130
  - LICENSE.txt
@@ -140,11 +141,11 @@ files:
140
141
  - lib/jekyll-spaceship/processors/element-processor.rb
141
142
  - lib/jekyll-spaceship/processors/emoji-processor.rb
142
143
  - lib/jekyll-spaceship/processors/mathjax-processor.rb
144
+ - lib/jekyll-spaceship/processors/media-processor.rb
143
145
  - lib/jekyll-spaceship/processors/mermaid-processor.rb
144
146
  - lib/jekyll-spaceship/processors/plantuml-processor.rb
145
147
  - lib/jekyll-spaceship/processors/polyfill-processor.rb
146
148
  - lib/jekyll-spaceship/processors/table-processor.rb
147
- - lib/jekyll-spaceship/processors/video-processor.rb
148
149
  - lib/jekyll-spaceship/utils/.keep
149
150
  - lib/jekyll-spaceship/version.rb
150
151
  - logos/jekyll-spaceship-logo.png
@@ -173,5 +174,6 @@ rubygems_version: 3.0.8
173
174
  signing_key:
174
175
  specification_version: 4
175
176
  summary: A Jekyll plugin to provide powerful supports for table, mathjax, plantuml,
176
- mermaid, emoji, video, youtube, vimeo, dailymotion, etc.
177
+ mermaid, emoji, video, audio, youtube, vimeo, dailymotion, spotify, soundcloud,
178
+ etc.
177
179
  test_files: []
@@ -1,139 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'uri'
4
-
5
- module Jekyll::Spaceship
6
- class VideoProcessor < Processor
7
- def self.config
8
- {
9
- 'default' => {
10
- 'id' => 'video-{id}',
11
- 'class' => 'video',
12
- 'width' => '100%',
13
- 'height' => 350,
14
- 'border' => 0,
15
- 'style' => 'max-width: 600px',
16
- 'allow' => 'encrypted-media; picture-in-picture',
17
- }
18
- }
19
- end
20
-
21
- def on_handle_markdown(content)
22
- content = handle_normal_video(content)
23
- content = handle_youtube(content)
24
- content = handle_vimeo(content)
25
- content = handle_dailymotion(content)
26
- end
27
-
28
- # Examples:
29
- # ![video](//www.html5rocks.com/en/tutorials/video/basics/devstories.webm)
30
- # ![video](//techslides.com/demos/sample-videos/small.ogv?allow=autoplay)
31
- # ![video](//techslides.com/demos/sample-videos/small.mp4?width=400)
32
- def handle_normal_video(content)
33
- handle_video(content, {
34
- host: '(https?:)?\\/\\/.*\\/',
35
- id: '(.+?\\.(avi|mp4|webm|ogg|ogv|flv|mkv|mov|wmv|3gp|rmvb|asf))',
36
- })
37
- end
38
-
39
- # Examples:
40
- # ![youtube](https://www.youtube.com/watch?v=XA2WjJbmmoM "title")
41
- # ![youtube](http://www.youtube.com/embed/w-m_yZCLF5Q)
42
- # ![youtube](//youtu.be/mEP3YXaSww8?height=100%&width=400)
43
- def handle_youtube(content)
44
- handle_video(content, {
45
- host: '(https?:)?\\/\\/.*youtu.*',
46
- id: '(?<=\\?v\\=|embed\\/|\\.be\\/)([a-zA-Z0-9\\_\\-]+)',
47
- iframe_url: "https://www.youtube.com/embed/"
48
- })
49
- end
50
-
51
- # Examples:
52
- # ![vimeo](https://vimeo.com/263856289)
53
- # ![vimeo](https://vimeo.com/263856289?height=100%&width=400)
54
- def handle_vimeo(content)
55
- handle_video(content, {
56
- host: '(https?:)?\\/\\/vimeo\\.com\\/',
57
- id: '([0-9]+)',
58
- iframe_url: "https://player.vimeo.com/video/"
59
- })
60
- end
61
-
62
- # Examples:
63
- # ![dailymotion](https://www.dailymotion.com/video/x7tgcev)
64
- # ![dailymotion](https://dai.ly/x7tgcev?height=100%&width=400)
65
- def handle_dailymotion(content)
66
- handle_video(content, {
67
- host: '(https?:)?\\/\\/.*dai.?ly.*',
68
- id: '(?<=video\\/|\\/)([a-zA-Z0-9\\_\\-]+)',
69
- iframe_url: "https://www.dailymotion.com/embed/video/"
70
- })
71
- end
72
-
73
- def handle_video(content, data)
74
- host = data[:host]
75
- return content if content.sub(/#{host}/, '').nil?
76
-
77
- iframe_url = data[:iframe_url]
78
- id = data[:id]
79
- url = "(#{host}#{id}\\S*)"
80
- title = '("(.*)".*){0,1}'
81
-
82
- # pre-handle reference-style links
83
- regex = /(\[(.*)\]:\s*(#{url}\s*#{title}))/
84
- content.scan regex do |match_data|
85
- match = match_data[0]
86
- ref_name = match_data[1]
87
- ref_value = match_data[2]
88
- content = content.gsub(match, '')
89
- .gsub(/\!\[(.*)\]\s*\[#{ref_name}\]/,
90
- "![\1](#{ref_value})")
91
- end
92
-
93
- # handle inline-style links
94
- regex = /(\!\[(.*)\]\(.*#{url}\s*#{title}\))/
95
- content.scan regex do |match_data|
96
- url = match_data[2]
97
- id = match_data[4]
98
- title = match_data[6]
99
- qs = url.match(/(?<=\?)(\S*?)$/)
100
- qs = Hash[URI.decode_www_form(qs.to_s)].reject do |k, v|
101
- next true if v == id or v == ''
102
- end
103
-
104
- default = self.config['default']
105
- css_id = qs['id'] || default['id']
106
- css_class = qs['class'] || default['class']
107
- width = qs['width'] || data[:width] || default['width']
108
- height = qs['height'] || data[:height] || default['height']
109
- frameborder = qs['frameborder'] || default['border']
110
- style = qs['style'] || default['style']
111
- allow = qs['allow'] || default['allow']
112
-
113
- css_id = css_id.gsub('{id}', id)
114
- css_class = css_class.gsub('{id}', id)
115
-
116
- url = URI(iframe_url ? "#{iframe_url}#{id}" : url).tap do |v|
117
- v.query = URI.encode_www_form(qs) if qs.size > 0
118
- end
119
-
120
- html = "<iframe"\
121
- " id=\"#{css_id}\""\
122
- " class=\"#{css_class}\""\
123
- " src=\"#{url}\""\
124
- " title=\"#{title}\""\
125
- " width=\"#{width}\""\
126
- " height=\"#{height}\""\
127
- " style=\"#{style}\""\
128
- " allow=\"#{allow}\""\
129
- " frameborder=\"#{frameborder}\""\
130
- " allowfullscreen>" \
131
- "</iframe>"
132
-
133
- content = content.gsub(match_data[0], html)
134
- self.handled = true
135
- end
136
- content
137
- end
138
- end
139
- end