jekyll-dry 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e999472a8eab6ae46d936e0455d0d1b036cc9b9dc0cd93d61dbfe3db9ca4a465
4
+ data.tar.gz: 2a6370165c59fbbf18049f19d3f5a51f6f0816a296d57ac9871f80696f6d7cec
5
+ SHA512:
6
+ metadata.gz: '058246a2c85ef4efb7f483f46fb0f0b47071e9256f7256ede62bce018007c1d4279c64b51a82700d0b8c6dde8afa194659b8394a8e85d8b048a38e70a1632ed4'
7
+ data.tar.gz: 2a1a41e461641c5fd3ff5a10ad0fa7a293c0645d0768169d5c5f30e7296dca13633870b3ac995b03841e74ffb0e9d4d5d940ff4c6eda3f4bcca249854d50c87f
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /vendor/
10
+ /_playground/
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.5
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ cache: bundler
4
+
5
+ branches:
6
+ only:
7
+ - master
8
+
9
+ script:
10
+ - bundle exec rake build
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at vagiz.d@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in jekyll-dry.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jekyll-dry (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (10.5.0)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ bundler (~> 2.0)
16
+ jekyll-dry!
17
+ rake (~> 10.0)
18
+
19
+ BUNDLED WITH
20
+ 2.0.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Vagiz Duseev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 vduseev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # jekyll-dry
2
+
3
+ [![Build Status](https://travis-ci.org/vduseev/jekyll-dry.svg?branch=master)](https://travis-ci.org/vduseev/jekyll-dry)
4
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/f261f89a633e47e3964ecc37bb826d4f)](https://www.codacy.com/manual/vduseev/jekyll-dry?utm_source=github.com&utm_medium=referral&utm_content=vduseev/jekyll-dry&utm_campaign=Badge_Grade)
5
+
6
+ Jekyll plugin that helps you to implement the DRY (Don't Repeat Yourself) principle while writing documentation using Jekyll.
7
+ The plugin allows you to reuse any fragments of markdown multiple times across a single Jekyll website. The fragments can include Liquid syntax and tags.
8
+
9
+ ## Table of contents
10
+
11
+ * User Guide:
12
+ * [Usage](#usage)
13
+ * [Installation](#installation)
14
+ * [Incompatibility with GitHub Pages](#incompatibility-with-github-pages)
15
+ * Implementation:
16
+ * [Plugin's architecture](architecture.md)
17
+ * [Detailed Design](detailed_design.md)
18
+
19
+ ## Usage
20
+
21
+ ### Fragment's beginning tag: `{% frag ... %}`
22
+
23
+ `frag` tag marks the beginning of a reusable fragment and assigns a unique id to it. Everything between `frag` and `endfrag` tags with unique id is considered a unique reusable fragment that can be included to any page.
24
+
25
+ <a name="example-of-frag-usage">Example of usage</a>:
26
+ ```
27
+ It was decided that the amount of dependencies of the executable will
28
+ be kept at minimum. For that reason {% frag dependencies %}the only
29
+ dependency is Python's `argparse` library{% endfrag dependencies %}.
30
+ ```
31
+
32
+ As a result of the above markup the `dependencies` file will be generated and will contain following text:
33
+ ```
34
+ the only dependency is Python's `argparse` library
35
+ ```
36
+
37
+ The generated file is now available for inclusion at any page, including the page where it was initially declared. During generation process `frag` tag is replaced in page with an empty string.
38
+
39
+ ### Fragment's end tag: `{% endfrag ... %}`
40
+
41
+ `endfrag` tag only marks the end of the fragment declared by `frag` tag and is only used by it. After Jekyll processes the page `endfrag` disappears.
42
+
43
+ If no matching `endfrag` is found for a given `frag`, then that `frag` will not be counted as a valid fragment and will not produce an include file.
44
+
45
+ <a name="example-of-endfrag-usage">Example of usage</a>: [see above](#example-of-frag-usage).
46
+
47
+ During generation process `endfrag` tag is replaced in page with an empty string.
48
+
49
+ ### Fragment embedding tag: `{% > ... %}`
50
+
51
+ `>` inclusion tag that searches for an include file with a given unique id generated by `frag` tag. Works in exactly same way as traditional `include` tag, but does not use parameters.
52
+
53
+ <a name="example-of-inclusion-usage">Example of usage:</a>
54
+ ```
55
+ Testing will require a test suite that covers a set of test cases
56
+ derived from initial use cases. However, since {% > dependencies %},
57
+ the testing will be entirely implemented using just the `py.test`
58
+ library.
59
+ ```
60
+
61
+ Which will produce the following result:
62
+
63
+ Testing will require a test suite that covers a set of test cases derived from initial use cases. However, since the only
64
+ dependency is Python's `argparse` library, the testing will be entirely implemented using just the `py.test` library.
65
+
66
+ ## Installation
67
+
68
+ Drop the `jekyll-dry.rb` file into the `_plugins` directory of the website as described in the first option of enabling a plugin in [Jekyll documentation](https://jekyllrb.com/docs/plugins/#installing-a-plugin):
69
+ ```
70
+ In your site source root, make a _plugins directory. Place your plugins
71
+ here. Any file ending in *.rb inside this directory will be loaded
72
+ before Jekyll generates your site.
73
+ ```
74
+
75
+ ## Incompatibility with GitHub Pages
76
+
77
+ Since this is a custom plugin which is not included in the code set of GitHub pages plugins it will not work with GitHub's automatic website generation.
78
+
79
+ You will have to generate the website locally and then push the contents of the `_site` folder to GitHub in order to publish your website.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/clean'
3
+
4
+ task :default => [:clean]
5
+ #task :default => :spec
data/architecture.md ADDED
@@ -0,0 +1,65 @@
1
+ # Architecture of jekyll-dry plugin
2
+
3
+ The plugin consists of three new Liquid tags: `frag`, `endfrag`, and `>`.
4
+
5
+ ## Fragment's beginning tag: `frag`
6
+
7
+ `frag` tag is inherited from `Liquid::Block` and automatically detects `endfrag` tag with the same id that was used for `frag` tag itself. That means that the tag's class method must perform a text search on the page using regex expression with the starting position of the search equal to the position of the first character after the current `frag` tag.
8
+
9
+ If a corresponding `endfrag` tag is not found, then the `render()` method of the tag does not return anything.
10
+
11
+ However, if matching `endfrag` tag is found, then the whole text between the pair of `frag` and `endfrag` tags is captured and saved to a variable.
12
+
13
+ Any other `frag` and `endfrag` tags trapped in the captured text are removed.
14
+
15
+ After that, the text is saved to the file in the output directory. The saving path must be `output_directory_path/_fragments/`. And the name of the file must be equal to the unique id (*or variable as it is called in the source code of `include` tag*) provided with the tag.
16
+
17
+ If the file with the same name already exists in the `_fragments` directory, then an exception must be thrown from the plugin, saying:
18
+ ```
19
+ The fragment with such name already exists: <fragment's name here>
20
+ ```
21
+
22
+ ## Fragment's end tag: `endfrag`
23
+
24
+ `endfrag` tag is only required for the correct work of the `frag` tag. It is replaced with empty string, or simply, not rendered at all when processed.
25
+
26
+ ## Fragment's embedding tag: `>`
27
+
28
+ `>` embedding tag must have a lower priority than `frag` tag. This is required because all fragment files must be generated before `>` tag gets parsed and processed by Jekyll.
29
+
30
+ Embedding tag looks for the file specified in the variable to the tag in the `output_directory_path/_fragments/` directory.
31
+
32
+ If file is not found then nothing is rendered.
33
+
34
+ If, however, the file is found, the embedding tag reads it and resolves all internal inclusions completely (see a [note on recursive fragment embedding](#recursion)), regenerating the initial requested fragment while doing so.
35
+
36
+ If no regeneration is required and the fragment already has a final form, then the `>` tag embeds the contents of the file in place of itself on the page.
37
+
38
+ ## <a name="recursion">Note on recursive fragment embedding and loops</a>
39
+
40
+ A fragment might contain an inclusion of another fragment inside itself. For example:
41
+ ```
42
+ {% frag example_of_loop %}
43
+ This text illustrates that the fragment can contain another fragment
44
+ inside itself. {% > totally_different_fragment %} Such inclusion is
45
+ correctly resolved during generation process.
46
+ {% endfrag example_of_loop %}
47
+ ```
48
+
49
+ In order to resolve this the `frag` tag first generates all fragment files, including `>` tag inside them left intact.
50
+
51
+ The example above will result in a following fragment generated.
52
+
53
+ `output_directory_path/_fragments/example_of_loop`:
54
+ ```
55
+ This text illustrates that the fragment can contain another fragment
56
+ inside itself. {% > totally_different_fragment %} Such inclusion is
57
+ correctly resolved during generation process.
58
+ ```
59
+
60
+ Later, when `>` tag is being processed, the first time it encounters the usage of the `example_of_loop` fragment in a page, it detects an internal inclusion of another fragment, in this case a fragment called `totally_different_fragment`. So, it goes and pulls up that fragment's file and replaces the `{% > totally_different_fragment %}` string in `example_of_loop` file with the actual content of `totally_different_fragment` file. Hence, it regenerates the `example_of_loop` file leaving it ready-to-use for all other cases, where this fragment will be included whether it's the same page or a different one. This action must be performed in a recursive fashion, or using a stack, until the fragment embedded in another fragment is static and has a determined content. In other words, when embedded fragment has no inclusions in it. As soon as this condition is satisfied the loop, or recursion, has to be stopped.
61
+
62
+ A special validity check must be included into the logic to make sure that under no circumstances a fragment contains an inclusion of itself. Or, in other words, that there is no loop in fragment embedding. Whenever this is detected, an exception must be thrown, saying:
63
+ ```
64
+ A loop in fragment inclusion is detected: <looped fragment's name here>
65
+ ```
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jekyll/dry"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,48 @@
1
+ # Detailed design of jekyll-dry plugin
2
+
3
+ ## Fragment's beginning tag: `frag`
4
+
5
+ ### Hierarchy note
6
+
7
+ Must be in module `Jekyll`. Must be in module `Tags`.
8
+
9
+ ### Class `FragTag`
10
+
11
+ Class `FragTag` must be inherited from `Liquid::Tag`.
12
+
13
+ #### Methods of `FragTag`
14
+
15
+ ##### `initialize` method
16
+
17
+ ###### Arguments:
18
+
19
+ * tag_name
20
+ * markup
21
+ * tokens
22
+
23
+ ###### Logic:
24
+ 1. The `initialize method` should first make a call to the `super` method.
25
+ 1. Then it should verify that markup string matches the predefined markup pattern similar to the one in the source code of the `include` tag. The regex below matches following example of markup:
26
+ ```
27
+ file_path.ext param1="value1" param2='value2'
28
+ ```
29
+ The regex that matches that string is:
30
+ ```
31
+ # Capture group "fragment_id":
32
+ # - Starts with any amount of any symbols other than "{"
33
+ # - One or more untitled capture group:
34
+ # - Starts with "{{"
35
+ # - Followed by any number of whitespace characters
36
+ # - One or more: word, "-", or "."
37
+ # - Followed by any number of whitespace characters
38
+ # - Maybe one "|" followed by any amount of any symbols
39
+ # - Ends with "}}"
40
+ # - And any amount of symbols other than "\s", "{", or "}"
41
+ #
42
+ # Capture group "params":
43
+ # - Everything not captured by "fragment_id" group
44
+
45
+ (?<fragment_id>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)
46
+ (?<params>.*)
47
+ ```
48
+ 1. If markup matched this regex, then a capture group named `fragment_id` must be extracted
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "jekyll-dry"
7
+ spec.version = Jekyll::JekyllDry::VERSION
8
+ spec.authors = ["vduseev"]
9
+ spec.email = ["vagiz.d@gmail.com"]
10
+
11
+ spec.summary = %q{Don't Repeat Yourself. Reuse text fragments.}
12
+ spec.description = %q{Jekyll plugin that helps you to implement the DRY (Don't Repeat Yourself) principle while writing documentation using Jekyll.}
13
+ spec.homepage = "https://github.com/vduseev/jekyll-dry"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/vduseev/jekyll-dry"
18
+ spec.metadata["changelog_uri"] = "https://raw.githubusercontent.com/vduseev/jekyll-dry/master/CHANGELOG.md"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 2.0"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ end
data/lib/jekyll-dry.rb ADDED
@@ -0,0 +1,116 @@
1
+ # (The MIT License)
2
+ #
3
+ # Copyright (c) 2018 Vagiz Duseev
4
+
5
+ module ContextExt
6
+ def find_variable(key)
7
+ variable = super(key)
8
+ unless variable
9
+ variable = registers[:site].fragments[key]
10
+ end
11
+ variable
12
+ end
13
+ end
14
+
15
+ Jekyll::Hooks.register :site, :pre_render do |container, payload|
16
+ Liquid::Context.prepend(ContextExt)
17
+ end
18
+
19
+ module Jekyll
20
+ class FragmentGenerator < Generator
21
+ TagStart = /#{Liquid::TagStart}#{Liquid::WhitespaceControl}?\s*/o
22
+ TagEnd = /\s*#{Liquid::WhitespaceControl}?#{Liquid::TagEnd}/o
23
+ FragmentSubPattern = /#{TagStart}(?i:(end)?frag)\s*(.*?)#{TagEnd}\s*/om
24
+ FullFragmentPattern = %r/
25
+ #{TagStart}(?i:frag)\s*(?<id>.*?)#{TagEnd}
26
+ (?<body>.*)
27
+ #{TagStart}(?i:endfrag)\s*\k<id>#{TagEnd}
28
+ /xom
29
+
30
+ def generate(site)
31
+ # Initialize hash map that will store the fragments for rendering
32
+ class << site
33
+ attr_accessor :fragments
34
+ end
35
+ site.fragments = Hash.new
36
+
37
+ # Parse fragments on pages
38
+ site.pages.each do |page|
39
+ fragments = parse_page(page.content)
40
+
41
+ site.fragments.merge!(fragments) do |key, old_val, new_val|
42
+ # This section is invoked every time there is a duplicate key
43
+ # in site.fragments and parsed fragments
44
+ raise Liquid::SyntaxError.new(
45
+ "Duplicate fragment #{key} on page #{page.url}",
46
+ original_fragment: old_val,
47
+ duplicate_fragment: new_val
48
+ )
49
+ end
50
+ end
51
+ end
52
+
53
+ def parse_page(content)
54
+ fragments = Hash.new
55
+
56
+ pos = 0
57
+ while m = FullFragmentPattern.match(content, pos)
58
+ body = clean_fragment(m[:body])
59
+ fragments.store(m[:id], body)
60
+ puts("fragment #{m[:id]}:", body)
61
+ pos = m.begin(:id)
62
+ end
63
+ fragments
64
+ end
65
+
66
+ def clean_fragment(body)
67
+ pattern = /\s*#{FragmentSubPattern}\s*/om
68
+ clean_body = body.gsub(FragmentSubPattern, "")
69
+ clean_body.lstrip!
70
+ clean_body.rstrip!
71
+ end
72
+ end
73
+
74
+ class FragmentBlockBody < Liquid::BlockBody
75
+ def initialize
76
+ super
77
+ end
78
+
79
+ def whitespace_handler(token, parse_context)
80
+ return unless token =~ Jekyll::FragmentGenerator::FragmentSubPattern
81
+ previous_token = @nodelist.last
82
+ if previous_token.is_a? String
83
+ # previous_token.rstrip!
84
+ end
85
+ parse_context.trim_whitespace = true
86
+ end
87
+ end
88
+
89
+ class FragmentBlock < Liquid::Block
90
+ def initialize(tag_name, markup, options)
91
+ super
92
+ end
93
+
94
+ def parse(tokens)
95
+ @body = FragmentBlockBody.new
96
+ while parse_body(@body, tokens)
97
+ end
98
+ end
99
+ end
100
+
101
+ class Fragment < FragmentBlock
102
+ def initialize(tag_name, markup, options)
103
+ super
104
+ @fragment_id, _ = markup.strip.split(%r!\s+!, 2)
105
+ end
106
+
107
+ def render(context)
108
+ output = super
109
+ #context[@fragment_id] = output
110
+ #context.resource_limits.assign_score += output.length
111
+ output
112
+ end
113
+ end
114
+ end
115
+
116
+ Liquid::Template.register_tag('frag', Jekyll::Fragment)
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Jekyll
2
+ module JekyllDry
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-dry
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - vduseev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-11-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Jekyll plugin that helps you to implement the DRY (Don't Repeat Yourself)
42
+ principle while writing documentation using Jekyll.
43
+ email:
44
+ - vagiz.d@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".ruby-version"
51
+ - ".travis.yml"
52
+ - CODE_OF_CONDUCT.md
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - _playground/about.md
60
+ - architecture.md
61
+ - bin/console
62
+ - bin/setup
63
+ - detailed_design.md
64
+ - jekyll-dry.gemspec
65
+ - lib/jekyll-dry.rb
66
+ - lib/version.rb
67
+ homepage: https://github.com/vduseev/jekyll-dry
68
+ licenses:
69
+ - MIT
70
+ metadata:
71
+ homepage_uri: https://github.com/vduseev/jekyll-dry
72
+ source_code_uri: https://github.com/vduseev/jekyll-dry
73
+ changelog_uri: https://raw.githubusercontent.com/vduseev/jekyll-dry/master/CHANGELOG.md
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubygems_version: 3.0.3
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Don't Repeat Yourself. Reuse text fragments.
93
+ test_files: []