pulsar-jekyll-code-example 1.0.0
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 +7 -0
- data/CHANGELOG.md +32 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +84 -0
- data/LICENSE.md +27 -0
- data/README.md +191 -0
- data/lib/js/jekyll-code-example-buttons.js.rb +23 -0
- data/lib/pulsar-jekyll-code-example.rb +154 -0
- data/pulsar-jekyll-code-example.gemspec +20 -0
- data/spec/all_page_code_examples_spec.rb +31 -0
- data/spec/code_example_spec.rb +88 -0
- data/spec/spec_helper.rb +14 -0
- metadata +85 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14b5ec05fca3bbd9b529a075723f373eaacdb8f2
|
4
|
+
data.tar.gz: 2db41a424d7eb98c30fb8bb0423892f1bc0e762b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a4ddb25b35614c2454dc8a6609734ab5d0c8b17407ae6d2b741e6600c01548b3b455a51781ed42860a0c27cc4d4231b711f75282f57666c044d041dcf4b6f9c2
|
7
|
+
data.tar.gz: 24d35d1df76b090219340df5758ee96a8118fcfe1e4bc18517d8bbb076f7f1b964e7eec9a077e83a0ccc51d4b772644e991308ee19726e5db826281e37823201
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
==========
|
3
|
+
|
4
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
5
|
+
|
6
|
+
[How to use a CHANGELOG](http://keepachangelog.com/)
|
7
|
+
|
8
|
+
## 1.0.0 - 2017-01-30
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
|
12
|
+
- Started versioning based on semantic versioning.
|
13
|
+
|
14
|
+
### Added
|
15
|
+
|
16
|
+
- CSS class applied to <li> and <ul> tags in language menus can be set via the
|
17
|
+
`code_example_list_class` in _config.yml.
|
18
|
+
|
19
|
+
## 0.0.7 - 2015-03-18
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
|
23
|
+
- HTML escaping code examples, so the brower renders HTML/XMl as HTML/XML
|
24
|
+
characters
|
25
|
+
|
26
|
+
## 0.0.6 - 2015-03-16
|
27
|
+
|
28
|
+
### Added
|
29
|
+
|
30
|
+
- CSS classes applied to buttons and button container elements can now be
|
31
|
+
configured via _config.yml. Supporting JavaScript also uses classes set in
|
32
|
+
_config.yml.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pulsar-jekyll-code-example (1.0.0)
|
5
|
+
htmlentities
|
6
|
+
jekyll
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
addressable (2.5.0)
|
12
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
13
|
+
coderay (1.1.1)
|
14
|
+
colorator (1.1.0)
|
15
|
+
diff-lcs (1.3)
|
16
|
+
fakefs (0.10.2)
|
17
|
+
ffi (1.9.17)
|
18
|
+
forwardable-extended (2.6.0)
|
19
|
+
htmlentities (4.3.4)
|
20
|
+
jekyll (3.4.0)
|
21
|
+
addressable (~> 2.4)
|
22
|
+
colorator (~> 1.0)
|
23
|
+
jekyll-sass-converter (~> 1.0)
|
24
|
+
jekyll-watch (~> 1.1)
|
25
|
+
kramdown (~> 1.3)
|
26
|
+
liquid (~> 3.0)
|
27
|
+
mercenary (~> 0.3.3)
|
28
|
+
pathutil (~> 0.9)
|
29
|
+
rouge (~> 1.7)
|
30
|
+
safe_yaml (~> 1.0)
|
31
|
+
jekyll-sass-converter (1.5.0)
|
32
|
+
sass (~> 3.4)
|
33
|
+
jekyll-watch (1.5.0)
|
34
|
+
listen (~> 3.0, < 3.1)
|
35
|
+
kramdown (1.13.2)
|
36
|
+
liquid (3.0.6)
|
37
|
+
listen (3.0.8)
|
38
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
39
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
40
|
+
mercenary (0.3.6)
|
41
|
+
method_source (0.8.2)
|
42
|
+
mini_portile2 (2.1.0)
|
43
|
+
nokogiri (1.7.0.1)
|
44
|
+
mini_portile2 (~> 2.1.0)
|
45
|
+
pathutil (0.14.0)
|
46
|
+
forwardable-extended (~> 2.6)
|
47
|
+
pry (0.10.4)
|
48
|
+
coderay (~> 1.1.0)
|
49
|
+
method_source (~> 0.8.1)
|
50
|
+
slop (~> 3.4)
|
51
|
+
public_suffix (2.0.5)
|
52
|
+
rb-fsevent (0.9.8)
|
53
|
+
rb-inotify (0.9.8)
|
54
|
+
ffi (>= 0.5.0)
|
55
|
+
rouge (1.11.1)
|
56
|
+
rspec (3.5.0)
|
57
|
+
rspec-core (~> 3.5.0)
|
58
|
+
rspec-expectations (~> 3.5.0)
|
59
|
+
rspec-mocks (~> 3.5.0)
|
60
|
+
rspec-core (3.5.4)
|
61
|
+
rspec-support (~> 3.5.0)
|
62
|
+
rspec-expectations (3.5.0)
|
63
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
64
|
+
rspec-support (~> 3.5.0)
|
65
|
+
rspec-mocks (3.5.0)
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
+
rspec-support (~> 3.5.0)
|
68
|
+
rspec-support (3.5.0)
|
69
|
+
safe_yaml (1.0.4)
|
70
|
+
sass (3.4.23)
|
71
|
+
slop (3.6.0)
|
72
|
+
|
73
|
+
PLATFORMS
|
74
|
+
ruby
|
75
|
+
|
76
|
+
DEPENDENCIES
|
77
|
+
fakefs
|
78
|
+
nokogiri
|
79
|
+
pry
|
80
|
+
pulsar-jekyll-code-example!
|
81
|
+
rspec
|
82
|
+
|
83
|
+
BUNDLED WITH
|
84
|
+
1.14.4
|
data/LICENSE.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2015, GovDelivery, Inc.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
3. Neither the name of GovDelivery nor the names of its contributors may be
|
15
|
+
used to endorse or promote products derived from this software without
|
16
|
+
specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
19
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
[](https://travis-ci.org/govdelivery/jekyll-code-example-tag)
|
2
|
+
[](http://badge.fury.io/rb/jekyll-code-example-tag)
|
3
|
+
|
4
|
+
jekyll-code-example-tag
|
5
|
+
=======================
|
6
|
+
|
7
|
+
Provides a tag that allows you to include in your posts and pages code examples
|
8
|
+
for multiple languages that are kept in separate files. Another tag allows you
|
9
|
+
to combine all code examples that are on a page.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add the following to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'jekyll-code-example-tag'
|
16
|
+
|
17
|
+
and then execute:
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
Or install it manually:
|
22
|
+
|
23
|
+
gem install jekyll-code-example-tag
|
24
|
+
|
25
|
+
Then, include a script tag in your page or layout to fetch the required
|
26
|
+
javascript:
|
27
|
+
|
28
|
+
<script type="text/javascript" src="/js/jekyll-code-example-buttons.js"></script>
|
29
|
+
|
30
|
+
You may also overwrite the provided javascript by writing a `jekyll-code-example-buttons.js`
|
31
|
+
file in the `/js/` directory of your Jekyll project.
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Configure CSS Classes
|
36
|
+
|
37
|
+
Via your site's _config.yml, you can define what CSS class or classes the
|
38
|
+
example buttons and button containers will have. For example:
|
39
|
+
|
40
|
+
code_example_buttons_class: 'the_buttons'
|
41
|
+
code_example_button_class: 'a_button'
|
42
|
+
|
43
|
+
will cause each button to have the class `a_button`, and buttons will be inside
|
44
|
+
a div with the class `the_buttons`.
|
45
|
+
|
46
|
+
`code_example_buttons_class` defaults to 'buttons', and
|
47
|
+
`code_example_button_class` defaults to 'button'.
|
48
|
+
|
49
|
+
Same is true for ```code_example_list_class``` which controls the class used for the ```<li>``` and ```<ul>``` tags.
|
50
|
+
The default class is 'code-tab' which can be changed by setting:
|
51
|
+
```
|
52
|
+
code_example_list_class: my-list-class
|
53
|
+
```
|
54
|
+
in _config.yml.
|
55
|
+
|
56
|
+
### code_example
|
57
|
+
|
58
|
+
First, select a folder to place your code examples in. By default, the top
|
59
|
+
level folder `code_examples` will be used. If you would like to store your
|
60
|
+
examples in a different folder, than create and set a `code_example_dir`
|
61
|
+
setting in your _config.yaml:
|
62
|
+
|
63
|
+
code_example_dir: assets/code/examples
|
64
|
+
|
65
|
+
Now, add some code examples. Create folders for each language you would like to
|
66
|
+
provide a code example for. Then, add files to each language folder that
|
67
|
+
contain language appropriate code examples.
|
68
|
+
|
69
|
+
For example, say we would like to include some Hello World examples in Ruby and
|
70
|
+
Python. First, assuming we are using the default code examples directory, we
|
71
|
+
would add the following to your project:
|
72
|
+
|
73
|
+
.
|
74
|
+
|-code_examples
|
75
|
+
|-ruby
|
76
|
+
|-hello_world
|
77
|
+
|-python
|
78
|
+
|-hello_world
|
79
|
+
|
80
|
+
`ruby/hello_world` could contain
|
81
|
+
|
82
|
+
puts "Hello World"
|
83
|
+
|
84
|
+
while `python/hello_world` could contain
|
85
|
+
|
86
|
+
print "Hello World"
|
87
|
+
|
88
|
+
Now, create a post that includes these code examples. Include a code example in
|
89
|
+
a page or posting with the *code_example* tag:
|
90
|
+
|
91
|
+
---
|
92
|
+
title: Starting to Program
|
93
|
+
---
|
94
|
+
|
95
|
+
Here is everybody's favorite first program, in Ruby and Python.
|
96
|
+
|
97
|
+
{% code_example hello_world %}
|
98
|
+
|
99
|
+
Build your site, and you will find a page that contains the following markup:
|
100
|
+
|
101
|
+
<p>Here is everybody's favorite first program, in Ruby and Python.</p>
|
102
|
+
|
103
|
+
<div class="code-examples">
|
104
|
+
<div class="buttons examples">
|
105
|
+
<ul>
|
106
|
+
<li><a href="#" class="button active" target="Python">Python</a></li>
|
107
|
+
<li><a href="#" class="button" target="ruby">Ruby</a></li>
|
108
|
+
</ul>
|
109
|
+
</div>
|
110
|
+
<div class="highlight example python" style="display: block;">
|
111
|
+
<pre><code class="language-python" data-lang="python">print "Hello World"</code></pre>
|
112
|
+
</div>
|
113
|
+
<div class="highlight example ruby" style="display: none;">
|
114
|
+
<pre><code class="language-ruby" data-lang="ruby">puts "Hello World"</code></pre>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
|
118
|
+
The *code_example* tag will search the folders in your code examples directory
|
119
|
+
for files that match whatever string is given to it, and will include only
|
120
|
+
languages/files that match it. Thus, if you add a `goodbye_world` example in
|
121
|
+
just Ruby:
|
122
|
+
|
123
|
+
.
|
124
|
+
|-code_examples
|
125
|
+
|-ruby
|
126
|
+
|-goodbye_world
|
127
|
+
|-hello_world
|
128
|
+
|-python
|
129
|
+
|-hello_world
|
130
|
+
|
131
|
+
and include it in a post:
|
132
|
+
|
133
|
+
{% code_example goodbye_world %}
|
134
|
+
|
135
|
+
the resulting markup will include just the Ruby example:
|
136
|
+
|
137
|
+
<div class="code-examples">
|
138
|
+
<div class="buttons examples">
|
139
|
+
<ul>
|
140
|
+
<li><a href="#" class="button" target="ruby">Ruby</a></li>
|
141
|
+
</ul>
|
142
|
+
</div>
|
143
|
+
<div class="highlight example ruby" style="display: none;">
|
144
|
+
<pre><code class="language-ruby" data-lang="ruby">puts "Goodbye World"</code></pre>
|
145
|
+
</div>
|
146
|
+
</div>
|
147
|
+
|
148
|
+
The *code_example* tag can also support examples organized in sub directories.
|
149
|
+
For example, say you would like to organize some of your code examples by
|
150
|
+
product and API version:
|
151
|
+
|
152
|
+
.
|
153
|
+
|-code_examples
|
154
|
+
|-productA
|
155
|
+
|-api_v1
|
156
|
+
|-ruby
|
157
|
+
|-widget_maker
|
158
|
+
|-python
|
159
|
+
|-widget_maker
|
160
|
+
|-api_v2
|
161
|
+
|-ruby
|
162
|
+
|-widget_maker
|
163
|
+
|-python
|
164
|
+
|-widget_maker
|
165
|
+
|-productB
|
166
|
+
|-api_v1
|
167
|
+
|-ruby
|
168
|
+
|-authenticating
|
169
|
+
|-python
|
170
|
+
|-authenticating
|
171
|
+
|-ruby
|
172
|
+
|-hello_world
|
173
|
+
|-python
|
174
|
+
|-hello_world
|
175
|
+
|
176
|
+
With the above directory structure, including any of the following calls to
|
177
|
+
code_example will result in including only the relevant code examples from
|
178
|
+
the referred to directory:
|
179
|
+
|
180
|
+
{% code_example productA/api_v1/widget_maker %}
|
181
|
+
{% code_example productA/api_v2/widget_maker %}
|
182
|
+
{% code_example productB/api_v1/authenticating %}
|
183
|
+
{% code_example hello_world %}
|
184
|
+
|
185
|
+
### all_page_code_examples
|
186
|
+
|
187
|
+
If you have included a few code examples on a page via the *code_example* tag,
|
188
|
+
you can provide your readers with an easy to copy version of all of your
|
189
|
+
examples by using the *all_page_code_examples* tag:
|
190
|
+
|
191
|
+
{% all_page_code_examples %}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def code_example_buttons_js(site)
|
2
|
+
buttons_class = site.config['code_example_buttons_class'] ? site.config['code_example_buttons_class'] : 'buttons'
|
3
|
+
button_class = site.config['code_example_button_class'] ? site.config['code_example_button_class'] : 'button'
|
4
|
+
|
5
|
+
<<EOF
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
jQuery(function(){
|
9
|
+
jQuery('.#{buttons_class}.examples .#{button_class}').click(function(e){
|
10
|
+
e.preventDefault();
|
11
|
+
var parent = jQuery(this).closest('.code-examples');
|
12
|
+
var target = jQuery(this).attr('target');
|
13
|
+
|
14
|
+
parent.find('.example').hide();
|
15
|
+
parent.find('.example.'+target).show();
|
16
|
+
parent.find('.#{buttons_class}.examples .#{button_class}.active').removeClass('active');
|
17
|
+
parent.find('.#{buttons_class}.examples .#{button_class}[target="'+target+'"]').addClass('active');
|
18
|
+
});
|
19
|
+
|
20
|
+
jQuery('.#{buttons_class}.examples li:first-child .#{button_class}').click();
|
21
|
+
});
|
22
|
+
EOF
|
23
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require_relative 'js/jekyll-code-example-buttons.js.rb'
|
2
|
+
require 'htmlentities'
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
module CodeExampleTags
|
6
|
+
|
7
|
+
def self.code_example_dir(site)
|
8
|
+
site.fetch('code_example_dir', 'code_examples')
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns a hash of available code examples (per language) for the provided example name
|
12
|
+
def self.code_examples(context_path, example_name, site)
|
13
|
+
# Collect all relevant files
|
14
|
+
examples_root = File.join(code_example_dir(site), context_path)
|
15
|
+
|
16
|
+
code_folders = Dir.entries(examples_root).select do |entry|
|
17
|
+
File.directory? File.join(examples_root, entry) and !(entry =='.' || entry == '..')
|
18
|
+
end
|
19
|
+
|
20
|
+
examples = {}
|
21
|
+
code_folders.each do |lang|
|
22
|
+
code_folder = File.join(examples_root, lang)
|
23
|
+
example_file = Dir.entries(code_folder).find do |entry|
|
24
|
+
File.file? File.join(code_folder, entry) and entry == example_name
|
25
|
+
end
|
26
|
+
if example_file
|
27
|
+
examples[lang] = File.join(code_folder, example_file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
examples
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.buttons_markup(examples, context)
|
35
|
+
site = context['site']
|
36
|
+
buttons_class = site['code_example_buttons_class'] ? site['code_example_buttons_class'] : 'buttons'
|
37
|
+
button_class = site['code_example_button_class'] ? site['code_example_button_class'] : 'button'
|
38
|
+
list_class = site['code_example_list_class'] ? site['code_example_list_class'] : 'code-tab'
|
39
|
+
menu_items = ""
|
40
|
+
|
41
|
+
examples_reverse = Hash[examples.to_a.reverse]
|
42
|
+
|
43
|
+
examples_reverse.each_key do |lang|
|
44
|
+
|
45
|
+
menu_items << "<li class='#{list_class}'><a href='#' class='#{button_class}' target='#{lang}'>#{lang.capitalize}</a></li>"
|
46
|
+
end
|
47
|
+
<<EOF
|
48
|
+
<div class="#{buttons_class} examples">
|
49
|
+
<ul class="#{list_class}">
|
50
|
+
#{menu_items}
|
51
|
+
</ul>
|
52
|
+
</div>
|
53
|
+
EOF
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.example_markup(language, content)
|
57
|
+
he = HTMLEntities.new
|
58
|
+
<<EOF
|
59
|
+
<div class="example language-#{language} #{language}">
|
60
|
+
<pre class="prettyprint lang-#{language}"><code data-lang="#{language}">#{he.encode(content)}</code></pre>
|
61
|
+
</div>
|
62
|
+
EOF
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.wrap_examples_div(content)
|
67
|
+
"<div class='code-examples'>#{content}</div>"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.get_example_name_and_context(example_string)
|
71
|
+
example_string.strip!
|
72
|
+
if example_string.include?('/')
|
73
|
+
example_arr = example_string.split('/')
|
74
|
+
example_name = example_arr.delete_at(-1)
|
75
|
+
context_path = example_arr.join(File::SEPARATOR) + File::SEPARATOR
|
76
|
+
else
|
77
|
+
context_path = ''
|
78
|
+
example_name = example_string
|
79
|
+
end
|
80
|
+
|
81
|
+
return context_path, example_name
|
82
|
+
end
|
83
|
+
|
84
|
+
class CodeExampleTag < Liquid::Tag
|
85
|
+
def initialize(tag_name, example_string, tokens)
|
86
|
+
@context_path, @example_name = Jekyll::CodeExampleTags::get_example_name_and_context(example_string)
|
87
|
+
super
|
88
|
+
end
|
89
|
+
|
90
|
+
def render(context)
|
91
|
+
|
92
|
+
examples = Jekyll::CodeExampleTags::code_examples(@context_path, @example_name, context['site'])
|
93
|
+
|
94
|
+
# Build the code example elements
|
95
|
+
output = Jekyll::CodeExampleTags::buttons_markup(examples, context)
|
96
|
+
examples.each do |lang, path|
|
97
|
+
example_content = File.read(path)
|
98
|
+
output << Jekyll::CodeExampleTags::example_markup(lang, example_content)
|
99
|
+
end
|
100
|
+
|
101
|
+
output = Jekyll::CodeExampleTags::wrap_examples_div(output)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class AllPageCodeExamplesTag < Liquid::Tag
|
106
|
+
def render(context)
|
107
|
+
examples = {}
|
108
|
+
context['page']['content'].scan(/\{%\s*code_example (\S+)\s*%\}/) do |name|
|
109
|
+
context_path, example_name = Jekyll::CodeExampleTags::get_example_name_and_context(name[0])
|
110
|
+
more_examples = Jekyll::CodeExampleTags::code_examples(context_path, example_name, context['site'])
|
111
|
+
examples.merge!(more_examples){|key, pre_example, new_example| "#{pre_example}\n#{new_example}"}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Build the code example elements
|
115
|
+
output = Jekyll::CodeExampleTags::buttons_markup(examples, context)
|
116
|
+
examples.each do |lang, paths|
|
117
|
+
example_content = ""
|
118
|
+
for path in paths.split("\n")
|
119
|
+
example_content << File.read(path)
|
120
|
+
end
|
121
|
+
output << Jekyll::CodeExampleTags::example_markup(lang, example_content)
|
122
|
+
end
|
123
|
+
|
124
|
+
output = Jekyll::CodeExampleTags::wrap_examples_div(output)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class CodeExamplesJsFile < Jekyll::StaticFile
|
129
|
+
def write(dest)
|
130
|
+
|
131
|
+
dest_path = File.join(dest, @dir, @name)
|
132
|
+
|
133
|
+
FileUtils.mkdir_p(File.dirname(dest_path))
|
134
|
+
content = code_example_buttons_js(@site)
|
135
|
+
File.open(dest_path, 'w') do |f|
|
136
|
+
f.write(content)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class CodeExamplesJsGenerator < Jekyll::Generator
|
142
|
+
safe true
|
143
|
+
|
144
|
+
def generate(site)
|
145
|
+
name = 'jekyll-code-example-buttons.js'
|
146
|
+
destination = '/js/'
|
147
|
+
site.static_files << CodeExamplesJsFile.new(site, site.source, destination, name)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
Liquid::Template.register_tag('code_example', Jekyll::CodeExampleTags::CodeExampleTag)
|
154
|
+
Liquid::Template.register_tag('all_page_code_examples', Jekyll::CodeExampleTags::AllPageCodeExamplesTag)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'pulsar-jekyll-code-example'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2015-02-03'
|
5
|
+
s.authors = ['Paul Stanton']
|
6
|
+
s.email = 'paul.stanton@jadu.net'
|
7
|
+
s.homepage = 'https://github.com/Stanton/pulsar-jekyll-code-example'
|
8
|
+
s.license = 'BSD-3-Clause'
|
9
|
+
s.summary = 'Tags for including code examples in posts and pages.'
|
10
|
+
s.description = %q{Provides a tag that allows you to include in your posts
|
11
|
+
and pages code examples for multiple langagues that are
|
12
|
+
kept in seperate files. Another tag allows you to combine
|
13
|
+
all code examples that are on a page.}
|
14
|
+
|
15
|
+
s.add_runtime_dependency 'jekyll'
|
16
|
+
s.add_runtime_dependency 'htmlentities'
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split($\)
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative './spec_helper.rb'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
describe 'all_page_code_examples', fakefs: true do
|
5
|
+
|
6
|
+
let(:page) do
|
7
|
+
page = <<EOF
|
8
|
+
{% code_example hello_world %}
|
9
|
+
{% code_example goodbye_world %}
|
10
|
+
{% all_page_code_examples %}
|
11
|
+
EOF
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:all) do
|
15
|
+
FakeFS.activate!
|
16
|
+
FileUtils.mkdir_p('code_examples/python')
|
17
|
+
File.open('code_examples/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
18
|
+
File.open('code_examples/python/goodbye_world', 'w') { |f| f << 'print "Goodbye World"'}
|
19
|
+
end
|
20
|
+
|
21
|
+
after(:all) do
|
22
|
+
FakeFS.deactivate!
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can be used' do
|
26
|
+
t = Liquid::Template.parse(page)
|
27
|
+
o = t.render!({'site' => {}, 'page' => {'content' => page}})
|
28
|
+
o_html = Nokogiri::HTML.parse(o)
|
29
|
+
expect(o_html.search("[text()*='print \"Hello World\"print \"Goodbye World\"']")).not_to be_empty
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require_relative './spec_helper.rb'
|
2
|
+
|
3
|
+
def check_code_example_conditions(o_obj, buttons_class: 'buttons', button_class: 'button')
|
4
|
+
expect(o_obj.xpath('/div[@class="code-examples"]/div[@class="'+buttons_class+' examples"]/ul/li/a[@class="'+button_class+'"][@target="ruby"][.="Ruby"]')).not_to be_empty
|
5
|
+
expect(o_obj.xpath('/div[@class="code-examples"]/div[@class="'+buttons_class+' examples"]/ul/li/a[@class="'+button_class+'"][@target="python"][.="Python"]')).not_to be_empty
|
6
|
+
ruby_example = o_obj.xpath('/div[@class="code-examples"]/div[@class="highlight example ruby"]/pre/code[@class="language ruby"][@data-lang="ruby"]')
|
7
|
+
expect(ruby_example).not_to be_empty
|
8
|
+
expect(ruby_example.first.content).to eq 'puts "Hello World"'
|
9
|
+
python_example = o_obj.xpath('/div[@class="code-examples"]/div[@class="highlight example python"]/pre/code[@class="language python"][@data-lang="python"]')
|
10
|
+
expect(python_example).not_to be_empty
|
11
|
+
expect(python_example.first.content).to eq 'print "Hello World"'
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'code_example', fakefs: true do
|
15
|
+
|
16
|
+
let(:page) { "{% code_example hello_world %}" }
|
17
|
+
|
18
|
+
before(:all) do
|
19
|
+
FakeFS.activate!
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:all) do
|
23
|
+
FakeFS.deactivate!
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'can be used' do
|
27
|
+
FileUtils.mkdir_p('code_examples/ruby')
|
28
|
+
FileUtils.mkdir_p('code_examples/python')
|
29
|
+
File.open('code_examples/ruby/hello_world', 'w') { |f| f << 'puts "Hello World"'}
|
30
|
+
File.open('code_examples/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
31
|
+
|
32
|
+
t = Liquid::Template.parse(page)
|
33
|
+
o = t.render!({'site' => {}})
|
34
|
+
o_obj = Nokogiri::XML.parse(o)
|
35
|
+
check_code_example_conditions(o_obj)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'can be configured via "code_example_dir"' do
|
39
|
+
FileUtils.mkdir_p('examples/ruby')
|
40
|
+
FileUtils.mkdir_p('examples/python')
|
41
|
+
File.open('examples/ruby/hello_world', 'w') { |f| f << 'puts "Hello World"'}
|
42
|
+
File.open('examples/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
43
|
+
|
44
|
+
t = Liquid::Template.parse(page)
|
45
|
+
o = t.render!({'site' => {'code_example_dir' => 'examples'}})
|
46
|
+
o_obj = Nokogiri::XML.parse(o)
|
47
|
+
check_code_example_conditions(o_obj)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can be configured via "code_example_button_class"' do
|
51
|
+
FileUtils.mkdir_p('code_examples/ruby')
|
52
|
+
FileUtils.mkdir_p('code_examples/python')
|
53
|
+
File.open('code_examples/ruby/hello_world', 'w') { |f| f << 'puts "Hello World"'}
|
54
|
+
File.open('code_examples/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
55
|
+
|
56
|
+
t = Liquid::Template.parse(page)
|
57
|
+
o = t.render!({'site' => {'code_example_button_class' => 'button'}})
|
58
|
+
o_obj = Nokogiri::XML.parse(o)
|
59
|
+
check_code_example_conditions(o_obj, button_class: 'button')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'can be configured via "code_example_buttons_class"' do
|
63
|
+
FileUtils.mkdir_p('code_examples/ruby')
|
64
|
+
FileUtils.mkdir_p('code_examples/python')
|
65
|
+
File.open('code_examples/ruby/hello_world', 'w') { |f| f << 'puts "Hello World"'}
|
66
|
+
File.open('code_examples/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
67
|
+
|
68
|
+
t = Liquid::Template.parse(page)
|
69
|
+
o = t.render!({'site' => {'code_example_buttons_class' => 'button-group'}})
|
70
|
+
o_obj = Nokogiri::XML.parse(o)
|
71
|
+
check_code_example_conditions(o_obj, buttons_class: 'button-group')
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
it 'allows for dividing examples via context' do
|
76
|
+
FileUtils.mkdir_p('code_examples/v1/ruby')
|
77
|
+
FileUtils.mkdir_p('code_examples/v1/python')
|
78
|
+
File.open('code_examples/v1/ruby/hello_world', 'w') { |f| f << 'puts "Hello World"'}
|
79
|
+
File.open('code_examples/v1/python/hello_world', 'w') { |f| f << 'print "Hello World"'}
|
80
|
+
|
81
|
+
page = "{% code_example v1/hello_world %}"
|
82
|
+
|
83
|
+
t = Liquid::Template.parse(page)
|
84
|
+
o = t.render!({'site' => {}})
|
85
|
+
o_obj = Nokogiri::XML.parse(o)
|
86
|
+
check_code_example_conditions(o_obj)
|
87
|
+
end
|
88
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'fakefs/spec_helpers'
|
2
|
+
require 'jekyll'
|
3
|
+
require 'liquid'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'pry'
|
6
|
+
require 'rspec'
|
7
|
+
require_relative '../lib/pulsar-jekyll-code-example.rb'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.include FakeFS::SpecHelpers, fakefs: true
|
11
|
+
end
|
12
|
+
|
13
|
+
Pry.config.history.should_save = false;
|
14
|
+
Pry.config.history.should_load = false;
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pulsar-jekyll-code-example
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paul Stanton
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jekyll
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: htmlentities
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: "Provides a tag that allows you to include in your posts \n and
|
42
|
+
pages code examples for multiple langagues that are \n kept
|
43
|
+
in seperate files. Another tag allows you to combine\n all code
|
44
|
+
examples that are on a page."
|
45
|
+
email: paul.stanton@jadu.net
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- CHANGELOG.md
|
51
|
+
- Gemfile
|
52
|
+
- Gemfile.lock
|
53
|
+
- LICENSE.md
|
54
|
+
- README.md
|
55
|
+
- lib/js/jekyll-code-example-buttons.js.rb
|
56
|
+
- lib/pulsar-jekyll-code-example.rb
|
57
|
+
- pulsar-jekyll-code-example.gemspec
|
58
|
+
- spec/all_page_code_examples_spec.rb
|
59
|
+
- spec/code_example_spec.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
homepage: https://github.com/Stanton/pulsar-jekyll-code-example
|
62
|
+
licenses:
|
63
|
+
- BSD-3-Clause
|
64
|
+
metadata: {}
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
requirements: []
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 2.5.1
|
82
|
+
signing_key:
|
83
|
+
specification_version: 4
|
84
|
+
summary: Tags for including code examples in posts and pages.
|
85
|
+
test_files: []
|