├── .ruby-version
├── OSSMETADATA
├── .qlty
├── configs
│ └── .shellcheckrc
├── .gitignore
└── qlty.toml
├── .rspec
├── scripts
├── build
├── test
├── lint
├── devcontainer_postCreateCommand.sh
├── setup
└── console
├── .ackrc
├── spec
├── fixtures
│ ├── missing_definition
│ │ ├── _data
│ │ │ └── glossary.yml
│ │ ├── page.md
│ │ ├── _config.yml
│ │ ├── _layouts
│ │ │ └── default.html
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ ├── missing_term
│ │ ├── _data
│ │ │ └── glossary.yml
│ │ ├── page.md
│ │ ├── _config.yml
│ │ ├── _layouts
│ │ │ └── default.html
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ ├── empty_definition
│ │ ├── _data
│ │ │ └── glossary.yml
│ │ ├── page.md
│ │ ├── _config.yml
│ │ ├── _layouts
│ │ │ └── default.html
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ ├── normal
│ │ ├── page8.md
│ │ ├── page1.md
│ │ ├── page4.md
│ │ ├── _config.yml
│ │ ├── page2.md
│ │ ├── page6.md
│ │ ├── page3.md
│ │ ├── page7.md
│ │ ├── page5.md
│ │ ├── _layouts
│ │ │ └── default.html
│ │ ├── _data
│ │ │ └── glossary.yml
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ ├── duplicate_term
│ │ ├── _data
│ │ │ └── glossary.yml
│ │ ├── page.md
│ │ ├── _config.yml
│ │ ├── _layouts
│ │ │ └── default.html
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ ├── missing_glossary
│ │ ├── page.md
│ │ ├── _config.yml
│ │ ├── _layouts
│ │ │ └── default.html
│ │ └── assets
│ │ │ └── css
│ │ │ └── style.css
│ └── missing_tag_arg
│ │ ├── _config.yml
│ │ ├── page.md
│ │ ├── _layouts
│ │ └── default.html
│ │ ├── _data
│ │ └── glossary.yml
│ │ └── assets
│ │ └── css
│ │ └── style.css
├── jekyll-glossary_tooltip.rb
├── jekyll-glossary_tooltip
│ ├── options_parser_spec.rb
│ └── tag_spec.rb
└── spec_helper.rb
├── .devcontainer
└── devcontainer.json
├── img
├── tooltip_screenshot.png
└── tooltip_screenshot.xcf
├── lib
├── jekyll-glossary_tooltip
│ ├── version.rb
│ ├── errors.rb
│ ├── options_parser.rb
│ ├── jekyll-glossary_tooltip.css
│ └── tag.rb
└── jekyll-glossary_tooltip.rb
├── gemfiles
├── README.md
├── jekyll_4.x.x.gemfile
└── jekyll_3.7.x.gemfile
├── CONTRIBUTING.md
├── .simplecov
├── Appraisals
├── SECURITY.md
├── .editorconfig
├── .github
├── dependabot.yml
└── workflows
│ ├── cd.yml
│ ├── codeql-analysis.yml
│ └── ci.yml
├── .codeclimate.yml
├── .gitignore
├── Rakefile
├── Gemfile
├── LICENSE.txt
├── jekyll-glossary_tooltip.gemspec
├── CHANGELOG.md
├── .rubocop.yml
└── README.md
/.ruby-version:
--------------------------------------------------------------------------------
1 | 3.1.0
2 |
--------------------------------------------------------------------------------
/OSSMETADATA:
--------------------------------------------------------------------------------
1 | osslifecycle=active
2 |
--------------------------------------------------------------------------------
/.qlty/configs/.shellcheckrc:
--------------------------------------------------------------------------------
1 | source-path=SCRIPTDIR
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --format documentation
2 | --color
3 | --require spec_helper
4 |
--------------------------------------------------------------------------------
/scripts/build:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -eux
3 | bundle exec rake $*
4 |
--------------------------------------------------------------------------------
/scripts/test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -eux
3 | bundle exec rake spec $*
4 |
--------------------------------------------------------------------------------
/scripts/lint:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -eux
3 | bundle exec rake rubocop $*
4 |
--------------------------------------------------------------------------------
/.ackrc:
--------------------------------------------------------------------------------
1 | --ignore-dir=coverage/
2 | --ignore-dir=spec/dest
3 | --ignore-dir=.jekyll-cache
4 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_definition/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_no_def
2 | url: term_no_def url
3 |
--------------------------------------------------------------------------------
/.qlty/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !configs
3 | !configs/**
4 | !hooks
5 | !hooks/**
6 | !qlty.toml
7 | !.gitignore
8 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_term/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_defined
2 | definition: here
3 | url: !
4 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "postCreateCommand": "bash scripts/devcontainer_postCreateCommand.sh"
3 | }
4 |
--------------------------------------------------------------------------------
/img/tooltip_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikw/jekyll-glossary_tooltip/HEAD/img/tooltip_screenshot.png
--------------------------------------------------------------------------------
/img/tooltip_screenshot.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/erikw/jekyll-glossary_tooltip/HEAD/img/tooltip_screenshot.xcf
--------------------------------------------------------------------------------
/spec/fixtures/empty_definition/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_no_def
2 | definition:
3 | url: term_no_def url
4 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page8.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 8"
3 | layout: default
4 | ---
5 |
6 | {% glossary term_with_url, display: José Álvarez %}
7 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Jekyll
4 | module GlossaryTooltip
5 | VERSION = "2.1.0"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/fixtures/duplicate_term/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_popular
2 | definition: first definition
3 | - term: term_popular
4 | definition: second definition
5 |
--------------------------------------------------------------------------------
/spec/fixtures/duplicate_term/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_popular %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_glossary/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary any_term %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page1.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 1"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_with_url %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page4.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 4"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term with spaces %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/empty_definition/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_no_def %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_definition/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_no_def %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_term/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_not_defined %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/duplicate_term/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_term/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/gemfiles/README.md:
--------------------------------------------------------------------------------
1 | These Gemfiles are used from the CI pipeline in the build matrix to test specific versions of dependencies. They are generated by [Appraisal](https://github.com/thoughtbot/appraisal).
2 |
--------------------------------------------------------------------------------
/spec/fixtures/empty_definition/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_definition/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_glossary/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_tag_arg/_config.yml:
--------------------------------------------------------------------------------
1 | # This file must exist, as Jekyll will print a warning during build otherwise.
2 | # Config can also be done in the #make_site helper.
3 | title: Fixture Site
4 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page2.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 2"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_without_url %} the glossary.
9 |
10 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page6.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 6"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary term_with_url_embedded_liquid %} the glossary.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page3.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 3"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page to {% glossary TerM_Case_Insensitive %} the glossary.
9 |
10 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page7.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 6"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | When a term is followed by a comma {% glossary term_without_url %}, no space before comma..
9 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 | Please use GitHub tooling (issues, PRs) to disucssion and code contributions!
3 |
4 | When you open an PR, GitHub Actions will build your code, run tests, liters and so on.
5 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_tag_arg/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A simple fixture page with a tag that forgot the argument {% glossary %} that is needed.
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/page5.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fixture page 5"
3 | layout: default
4 | ---
5 |
6 | # Fixture
7 |
8 | A term can have custom display name: {% glossary term_with_url, display: term alt display name %}.
9 |
--------------------------------------------------------------------------------
/spec/jekyll-glossary_tooltip.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | RSpec.describe Jekyll::GlossaryTooltip do
4 | it "has a version number" do
5 | expect(Jekyll::GlossaryTooltip::VERSION).not_to be_nil
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/scripts/devcontainer_postCreateCommand.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Devcontainer postCreateCommand.
3 | # Install dependencies for running this project in GitHub Codespaces.
4 |
5 | set -eux
6 |
7 | # For project.
8 | bundle install
9 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/duplicate_term/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/empty_definition/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_glossary/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_tag_arg/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_term/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_definition/_layouts/default.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ page.title }}
5 |
6 |
7 |
8 | {{ content }}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.simplecov:
--------------------------------------------------------------------------------
1 | # vi: ft=ruby
2 |
3 | SimpleCov.start do
4 | enable_coverage :branch # Add branch coverage statistics.
5 | minimum_coverage 90 # Minimum coverage percentage.
6 | command_name "test:bdd" # Must be set for codeclimat reporter
7 | end
8 |
--------------------------------------------------------------------------------
/Appraisals:
--------------------------------------------------------------------------------
1 | # Override jekyll version from .gemspec
2 |
3 | appraise "jekyll-3.7.x" do
4 | gem "jekyll", "~> 3.7"
5 | gem "kramdown", "2.3.1"
6 | gem "kramdown-parser-gfm", "~> 1.0"
7 | end
8 |
9 | appraise "jekyll-4.x.x" do
10 | gem "jekyll", "~> 4.0"
11 | end
12 |
--------------------------------------------------------------------------------
/scripts/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 | IFS=$'\n\t'
4 | set -vx
5 |
6 | rvm install ruby-$(cat .ruby-version)
7 | gem install bundler -v 2.2.18
8 | bundle install
9 |
10 |
11 | # Qlty CLI tool. Ref: https://docs.qlty.sh/cli/quickstart
12 | curl https://qlty.sh | sh
13 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | | Version | Supported |
6 | | ------- | ------------------ |
7 | | 1.x.x | :white_check_mark: |
8 | | < 1.0 | :x: |
9 |
10 |
11 | ## Reporting a Vulnerability
12 | Please open a GitHub Issue in this repository for any potential issues!
13 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative "jekyll-glossary_tooltip/options_parser"
4 | require_relative "jekyll-glossary_tooltip/tag"
5 | require_relative "jekyll-glossary_tooltip/version"
6 |
7 | module Jekyll
8 | # Module for the plugin.
9 | module GlossaryTooltip
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Modified version of https://github.com/ruby/ruby/blob/master/.editorconfig
2 |
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | indent_size = 4
8 | indent_style = space
9 | insert_final_newline = true
10 | tab_width = 4
11 | trim_trailing_whitespace = true
12 |
13 | [*.rb]
14 | indent_size = 2
15 |
16 | [*.gemspec]
17 | indent_size = 2
18 |
19 | [*.yml]
20 | indent_size = 2
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Reference: https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2 | # Validation: https://dependabot.com/docs/config-file/validator/
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: "bundler"
7 | directory: "/"
8 | schedule:
9 | interval: "monthly"
10 | #ignore:
11 | #- dependency-name: "rubocop"
12 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_tag_arg/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_with_url
2 | definition: term_with_url definition
3 | url: term_with_url url
4 | - term: term_without_url
5 | definition: term_without_url definition
6 | - term: TERM_CASE_INSENSITIVE
7 | definition: TERM_CASE_INSENSITIVE definition
8 | url: TERM_CASE_INSENSITIVE url
9 | - term: term with spaces
10 | definition: term with spaces definition
11 |
--------------------------------------------------------------------------------
/scripts/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | require "bundler/setup"
5 | require "jekyll-glossary_tooltip"
6 |
7 | # You can add fixtures and/or initialization code here to make experimenting
8 | # with your gem easier. You can also use a different console, if you like.
9 |
10 | # (If you use this, don't forget to add pry to your Gemfile!)
11 | # require "pry"
12 | # Pry.start
13 |
14 | require "irb"
15 | IRB.start(__FILE__)
16 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/_data/glossary.yml:
--------------------------------------------------------------------------------
1 | - term: term_with_url
2 | definition: term_with_url definition
3 | url: term_with_url url
4 | - term: term_without_url
5 | definition: term_without_url definition
6 | - term: TERM_CASE_INSENSITIVE
7 | definition: TERM_CASE_INSENSITIVE definition
8 | url: TERM_CASE_INSENSITIVE url
9 | - term: term with spaces
10 | definition: term with spaces definition
11 | - term: term_with_url_embedded_liquid
12 | definition: term_with_url_embedded_liquid definition
13 | url: >
14 | {% link page2.md %}
15 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | # Reference: https://docs.codeclimate.com/docs/advanced-configuration#section-checks
2 | # Reference of plugins: https://docs.codeclimate.com/docs/list-of-engines
3 |
4 | version: "2"
5 | plugins:
6 | rubocop:
7 | enabled: true
8 | channel: rubocop-1-18-3
9 | fixme:
10 | enabled: true
11 | eslint:
12 | enabled: true
13 | duplication:
14 | enabled: true
15 | config:
16 | languages:
17 | - ruby
18 | - javascript
19 | ratings:
20 | paths:
21 | - "**.rb"
22 | - "**.js"
23 | exclude_paths:
24 | - scripts/
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Contrary to ruby apps, ruby gems should not check in Gemfile.lock.
2 | # Reference: https://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
3 | Gemfile.lock
4 | # Same for Appraisals generated Gemfiles
5 | gemfiles/*gemfile.lock
6 | gemfiles/Gemfile*.lock
7 |
8 | # Bundle local config
9 | .bundle/
10 |
11 | # Package gem from $(rake install)
12 | pkg/
13 |
14 | # simplecov
15 | coverage/
16 |
17 | # rspec
18 | .jekyll-cache/
19 | .rspec_status
20 | spec/dest/
21 | spec/reports/
22 |
23 | # Jekyll - when switching from gh-pages-source branch
24 | _site/
25 |
--------------------------------------------------------------------------------
/gemfiles/jekyll_4.x.x.gemfile:
--------------------------------------------------------------------------------
1 | # This file was generated by Appraisal
2 |
3 | source "https://rubygems.org"
4 |
5 | gem "jekyll", "~> 4.0"
6 |
7 | group :development, :test do
8 | gem "appraisal", "~> 2.4", require: false
9 | gem "gem-release", "~> 2.0", require: false
10 | gem "rake", "~> 13.0", require: false
11 | gem "solargraph", require: false
12 | end
13 |
14 | group :test do
15 | gem "rspec", "~> 3.0"
16 | gem "rubocop", "~> 1.18", require: false
17 | gem "rubocop-rake", "~> 0.6", require: false
18 | gem "rubocop-rspec", "~> 3.5", require: false
19 | gem "simplecov", "~> 0.22"
20 | gem "json_pure", "~> 2.8", require: false
21 | end
22 |
23 | gemspec path: "../"
24 |
--------------------------------------------------------------------------------
/gemfiles/jekyll_3.7.x.gemfile:
--------------------------------------------------------------------------------
1 | # This file was generated by Appraisal
2 |
3 | source "https://rubygems.org"
4 |
5 | gem "jekyll", "~> 3.7"
6 | gem "kramdown", "2.3.1"
7 | gem "kramdown-parser-gfm", "~> 1.0"
8 |
9 | group :development, :test do
10 | gem "appraisal", "~> 2.4", require: false
11 | gem "gem-release", "~> 2.0", require: false
12 | gem "rake", "~> 13.0", require: false
13 | gem "solargraph", require: false
14 | end
15 |
16 | group :test do
17 | gem "rspec", "~> 3.0"
18 | gem "rubocop", "~> 1.18", require: false
19 | gem "rubocop-rake", "~> 0.6", require: false
20 | gem "rubocop-rspec", "~> 3.5", require: false
21 | gem "simplecov", "~> 0.22"
22 | gem "json_pure", "~> 2.8", require: false
23 | end
24 |
25 | gemspec path: "../"
26 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Deployment # Well, semi-continuous
2 |
3 | on:
4 | push:
5 | tags: v[0-9]+.[0-9]+.[0-9]+
6 | env:
7 | RUBY_VER: 3.0.1
8 | jobs:
9 | test:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Set up Ruby
14 | uses: ruby/setup-ruby@v1
15 | with:
16 | ruby-version: ${{ env.RUBY_VER }}
17 | bundler-cache: true
18 | - name: Run CI Build with Rake
19 | run: bundle exec rake
20 | release-github:
21 | needs: [test]
22 | runs-on: ubuntu-latest
23 | steps:
24 | - uses: actions/checkout@v2
25 | - name: Build and publish gem to GitHub Packages
26 | if: contains(github.ref, 'refs/tags/v')
27 | uses: jstastny/publish-gem-to-github@master
28 | with:
29 | token: ${{ github.token }}
30 | owner: ${{ github.repository_owner }}
31 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | # The branches below must be a subset of the branches above
8 | branches: [ main ]
9 | schedule:
10 | - cron: '41 19 1 * *'
11 |
12 | jobs:
13 | analyze:
14 | name: Analyze
15 | runs-on: ubuntu-latest
16 | permissions:
17 | actions: read
18 | contents: read
19 | security-events: write
20 |
21 | strategy:
22 | fail-fast: false
23 | matrix:
24 | language: [ 'ruby' ]
25 |
26 | steps:
27 | - name: Checkout repository
28 | uses: actions/checkout@v2
29 |
30 | # Initializes the CodeQL tools for scanning.
31 | - name: Initialize CodeQL
32 | uses: github/codeql-action/init@v1
33 | with:
34 | languages: ${{ matrix.language }}
35 |
36 | - name: Perform CodeQL Analysis
37 | uses: github/codeql-action/analyze@v1
38 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Run $(rake -T) to list all tasks.
4 |
5 | # Include default tasks like build, release, install etc. See https://github.com/rubygems/rubygems/blob/master/bundler/lib/bundler/gem_helper.rb#L46
6 | require "bundler/gem_tasks"
7 |
8 | # rspec: Testing framework. Adds 'spec' rake task.
9 | require "rspec/core/rake_task"
10 | RSpec::Core::RakeTask.new(:spec)
11 |
12 | # rubocop: Linting. Adds 'rubocop' rake task.
13 | require "rubocop/rake_task"
14 | RuboCop::RakeTask.new(:rubocop) do |t|
15 | # See https://docs.rubocop.org/rubocop/usage/basic_usage.html
16 | t.options = ["--display-cop-names", "--parallel"]
17 | end
18 |
19 | desc "Run Qlty code analysis"
20 | task :qlty do
21 | sh "qlty smells --all"
22 | sh "qlty metrics --all --max-depth=2 --sort complexity --limit 10"
23 | # sh "qlty lint" # Just runs rubocop, not necessary as we have a task for this already
24 | end
25 |
26 | # default task: Add spec and rubocop to default tasks.
27 | task default: %i[spec rubocop]
28 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Put require=false on gem's that we don't need to import in code (cli exec only)
4 |
5 | source "https://rubygems.org"
6 |
7 | # Include dependencies from the .gemspec
8 | gemspec
9 |
10 | # Development dependencies
11 | # Should rather be here than in the .gemspec
12 | # Reference: https://github.com/rubygems/bundler/pull/7222
13 | # However there's an argument for using gemspec too: https://bundler.io/guides/creating_gem.html#testing-our-gem
14 | group :development, :test do
15 | gem "appraisal", "~> 2.4", require: false
16 | gem "gem-release", "~> 2.0", require: false
17 | gem "rake", "~> 13.0", require: false
18 | gem "solargraph", require: false
19 | end
20 |
21 | group :test do
22 | gem "json_pure", "~> 2.8", require: false # Solargraph pulls in v2.6.3 which fails build with " uninitialized constant JSON::Fragment"
23 | gem "rspec", "~> 3.0"
24 | gem "rubocop", "~> 1.18", require: false
25 | gem "rubocop-rake", "~> 0.6", require: false
26 | gem "rubocop-rspec", "~> 3.5", require: false
27 | gem "simplecov", "~> 0.22"
28 | end
29 |
--------------------------------------------------------------------------------
/spec/fixtures/normal/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_term/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/duplicate_term/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/empty_definition/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_glossary/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_tag_arg/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/spec/fixtures/missing_definition/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 3px dotted blue;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 Erik Westrup
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.
22 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: main
7 | pull_request:
8 | branches: main
9 |
10 | # OIDC permissions for qlty
11 | permissions:
12 | contents: read
13 | id-token: write
14 |
15 | jobs:
16 | test:
17 | runs-on: ubuntu-latest
18 |
19 | strategy:
20 | matrix:
21 | ruby: [2.7.0, 3.0.1]
22 | gemfile:
23 | - gemfiles/jekyll_3.7.x.gemfile
24 | - gemfiles/jekyll_4.x.x.gemfile
25 |
26 | env:
27 | BUNDLE_GEMFILE: ${{ matrix.gemfile }}
28 |
29 | steps:
30 | - name: Checkout code
31 | uses: actions/checkout@v4
32 |
33 | - name: Set up Ruby
34 | uses: ruby/setup-ruby@v1
35 | with:
36 | ruby-version: ${{ matrix.ruby }}
37 | bundler-cache: true
38 | bundler: 2.2.18
39 |
40 | - name: Run tests
41 | run: bundle exec rake spec
42 |
43 | - name: Run linting
44 | run: bundle exec rake rubocop
45 |
46 | - name: Publish code coverage to qlty
47 | uses: qltysh/qlty-action/coverage@v2
48 | with:
49 | oidc: true
50 | format: simplecov
51 | files: coverage/.resultset.json
52 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip/errors.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Jekyll
4 | module GlossaryTooltip
5 | module Errors
6 | class MissingTermDefinition < StandardError
7 | def initialize(term_name); super("Glossary entry for '#{term_name}' does not contain a definition!") end
8 | end
9 | class MissingTermEntry < StandardError
10 | def initialize(term_name); super("The term '#{term_name}' was not defined in the glossary") end
11 | end
12 | class MultipleTermEntries < StandardError
13 | def initialize(term_name); super("The term '#{term_name}' was defined multiple times in the glossary") end
14 | end
15 | class NoGlossaryFile < StandardError; def initialize; super("No data.glossary found") end end
16 | class OptionsNoTermNameInTag < StandardError
17 | def initialize; super("No term name argument for the glossary tag supplied") end
18 | end
19 | class OptionsBadTagArgumentFormat < StandardError
20 | def initialize(term_name); super("The glossary tag for term '#{term_name}' has a bad argument format") end
21 | end
22 | class OptionsUnknownTagArgument < StandardError
23 | def initialize(arg); super("An unknown tag argument #{arg} was encountered") end
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip/options_parser.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "jekyll-glossary_tooltip/errors"
4 |
5 | module Jekyll
6 | module GlossaryTooltip
7 | # Stripped down & modified version of
8 | # https://github.com/ayastreb/jekyll-maps/blob/master/lib/jekyll-maps/options_parser.rb
9 | class OptionsParser
10 | ARGS_PATTERN = %r{\s*([\p{L}_][-\p{L}_]*):\s*([\p{L}_][^,\n\r]*)}
11 | ARGS_ALLOWED = %w[
12 | display
13 | ].freeze
14 |
15 | class << self
16 | def parse(raw_options)
17 | options = {
18 | term_query: nil,
19 | display: nil
20 | }
21 | opt_segments = raw_options.strip.split(",")
22 | raise Errors::OptionsNoTermNameInTag unless opt_segments.length.positive?
23 |
24 | options[:term_query] = opt_segments[0]
25 | opt_segments.shift
26 | parse_segments(options, opt_segments)
27 | options
28 | end
29 |
30 | def parse_segments(options, opt_segments)
31 | opt_segments.each do |opt_segment|
32 | raise Errors::OptionsBadTagArgumentFormat, options[:term_name] unless opt_segment =~ ARGS_PATTERN
33 |
34 | arg_name = Regexp.last_match(1)
35 | arg_value = Regexp.last_match(2)
36 | raise Errors::OptionsUnknownTagArgument, arg_name unless ARGS_ALLOWED.include?(arg_name)
37 |
38 | options[arg_name.to_sym] = arg_value
39 | end
40 | end
41 | end
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/spec/jekyll-glossary_tooltip/options_parser_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "jekyll-glossary_tooltip/options_parser"
4 | require "jekyll-glossary_tooltip/errors"
5 |
6 | P = Jekyll::GlossaryTooltip::OptionsParser
7 | E = Jekyll::GlossaryTooltip::Errors
8 |
9 | RSpec.describe Jekyll::GlossaryTooltip::OptionsParser do
10 | context "when providing valid term name" do
11 | let(:actual) { P.parse("a_term") }
12 | let(:expected) do
13 | { term_query: "a_term",
14 | display: nil }
15 | end
16 |
17 | it "parsing works" do
18 | expect(actual).to eq(expected)
19 | end
20 | end
21 |
22 | context "when providing valid term name and valid arg" do
23 | let(:actual) { P.parse("a_term, display: FancyName ") }
24 | let(:expected) do
25 | { term_query: "a_term",
26 | display: "FancyName" }
27 | end
28 |
29 | it "parsing works" do
30 | expect(actual).to eq(expected)
31 | end
32 | end
33 |
34 | context "when providing no term name query" do
35 | it "parsing raises error" do
36 | expect { P.parse(" ") }.to raise_error(E::OptionsNoTermNameInTag)
37 | end
38 | end
39 |
40 | context "when providing valid term name and invalid arg" do
41 | it "parsing raises error" do
42 | expect { P.parse("a_term, unknownArg: what") }.to raise_error(E::OptionsUnknownTagArgument)
43 | end
44 | end
45 |
46 | context "when providing invalid format" do
47 | it "parsing raises error" do
48 | expect { P.parse("a_term, display = FancyName") }.to raise_error(E::OptionsBadTagArgumentFormat)
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/jekyll-glossary_tooltip.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative "lib/jekyll-glossary_tooltip/version"
4 |
5 | Gem::Specification.new do |spec|
6 | spec.name = "jekyll-glossary_tooltip"
7 | spec.version = Jekyll::GlossaryTooltip::VERSION
8 | spec.authors = ["Erik Westrup"]
9 | spec.email = ["erik.westrup@icloud.com"]
10 |
11 | spec.summary = "Jekyll plugin providing a glossary liquid tag that will show a tooltip of a term definition in your site."
12 | spec.description = "This plugin simplifies for your readers and you by making it easy to define terms or abbreviations that needs an explanation. Define a common dictionary of terms and their definition in a YAML file. Then inside markdown files you can use the provided glossary liquid tag to insert a tooltip for a defined word from the dictionary. The tooltip will show the term definition on mouse hover."
13 | spec.homepage = "https://github.com/erikw/jekyll-glossary_tooltip/"
14 | spec.license = "MIT"
15 | spec.required_ruby_version = [">= 2.7", "< 4"]
16 |
17 | spec.metadata["homepage_uri"] = spec.homepage
18 | spec.metadata["source_code_uri"] = "https://github.com/erikw/jekyll-glossary_tooltip/"
19 | spec.metadata["changelog_uri"] = "https://github.com/erikw/jekyll-glossary_tooltip/blob/main/CHANGELOG.md"
20 |
21 | # Specify which files should be added to the gem when it is released.
22 | # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23 | spec.files = Dir.chdir(File.expand_path(__dir__)) do
24 | `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
25 | end
26 | spec.bindir = "exe"
27 | spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28 | spec.require_paths = ["lib"]
29 |
30 | spec.add_dependency "jekyll", [">= 3.7", "< 5.0"]
31 | end
32 |
--------------------------------------------------------------------------------
/.qlty/qlty.toml:
--------------------------------------------------------------------------------
1 | # This file was automatically generated by `qlty init`.
2 | # You can modify it to suit your needs.
3 | # We recommend you to commit this file to your repository.
4 | #
5 | # This configuration is used by both Qlty CLI and Qlty Cloud.
6 | #
7 | # Qlty CLI -- Code quality toolkit for developers
8 | # Qlty Cloud -- Fully automated Code Health Platform
9 | #
10 | # Try Qlty Cloud: https://qlty.sh
11 | #
12 | # For a guide to configuration, visit https://qlty.sh/d/config
13 | # Or for a full reference, visit https://qlty.sh/d/qlty-toml
14 | config_version = "0"
15 |
16 | exclude_patterns = [
17 | "*_min.*",
18 | "*-min.*",
19 | "*.min.*",
20 | "**/.yarn/**",
21 | "**/*.d.ts",
22 | "**/assets/**",
23 | "**/bower_components/**",
24 | "**/build/**",
25 | "**/cache/**",
26 | "**/config/**",
27 | "**/db/**",
28 | "**/deps/**",
29 | "**/dist/**",
30 | "**/extern/**",
31 | "**/external/**",
32 | "**/generated/**",
33 | "**/Godeps/**",
34 | "**/gradlew/**",
35 | "**/mvnw/**",
36 | "**/node_modules/**",
37 | "**/protos/**",
38 | "**/seed/**",
39 | "**/target/**",
40 | "**/templates/**",
41 | "**/testdata/**",
42 | "**/vendor/**",
43 | ]
44 |
45 | test_patterns = [
46 | "**/test/**",
47 | "**/spec/**",
48 | "**/*.test.*",
49 | "**/*.spec.*",
50 | "**/*_test.*",
51 | "**/*_spec.*",
52 | "**/test_*.*",
53 | "**/spec_*.*",
54 | ]
55 |
56 | [smells]
57 | mode = "comment"
58 |
59 | [smells.boolean_logic]
60 | threshold = 4
61 |
62 | [smells.file_complexity]
63 | threshold = 55
64 |
65 | [smells.return_statements]
66 | threshold = 4
67 |
68 | [smells.nested_control_flow]
69 | threshold = 4
70 |
71 | [smells.function_parameters]
72 | threshold = 4
73 |
74 | [smells.function_complexity]
75 | threshold = 5
76 |
77 | [[source]]
78 | name = "default"
79 | default = true
80 |
81 | [[plugin]]
82 | name = "rubocop"
83 | version = "1.80.2"
84 | package_file = "Gemfile"
85 | package_filters = ["rubocop"]
86 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip/jekyll-glossary_tooltip.css:
--------------------------------------------------------------------------------
1 | /* Tooltip from https://www.w3schools.com/css/css_tooltip.asp */
2 | .jekyll-glossary {
3 | position: relative;
4 | display: inline-block;
5 | border-bottom: 2px dotted #0074bd;
6 | cursor: help;
7 | }
8 |
9 | .jekyll-glossary .jekyll-glossary-tooltip {
10 | visibility: hidden;
11 | width: 120px;
12 | background-color: black;
13 | color: #fff;
14 | text-align: center;
15 | font-size: 0.5em;
16 | padding: 5px;
17 | border-radius: 6px;
18 |
19 | /* Position the tooltip text - see examples below! */
20 | position: absolute;
21 | z-index: 1;
22 |
23 | width: 160px;
24 | bottom: 100%;
25 | left: 50%;
26 | margin-left: -80px; /* Use half of the width to center the tooltip */
27 |
28 | }
29 |
30 | /* Show the tooltip text when you mouse over the tooltip container */
31 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
32 | visibility: visible;
33 | }
34 |
35 | /* Style the source link (if there is one provided in the glossary entry). */
36 | .jekyll-glossary-source-link:before {
37 | content: "[source]"; // "(reference)", "" or whatever you want.
38 | }
39 |
40 | /* Arrow created with borders. */
41 | .jekyll-glossary .jekyll-glossary-tooltip::after {
42 | content: " ";
43 | position: absolute;
44 | top: 100%;
45 | left: 50%;
46 | margin-left: -5px;
47 | border-width: 5px;
48 | border-style: solid;
49 | border-color: black transparent transparent transparent;
50 | }
51 |
52 | /* Animation from invisible to visible on hover. */
53 | .jekyll-glossary .jekyll-glossary-tooltip {
54 | opacity: 0;
55 | transition: opacity 1s;
56 | }
57 | .jekyll-glossary:hover .jekyll-glossary-tooltip {
58 | opacity: 1;
59 | }
60 |
61 | /* HACK: hide surrounding parenthesis on definition. When Jekyll renders
62 | * post.excerpt, all HTML and CSS is stripped. The effect is that the extra
63 | * parenthesis that are added are hidden in the normal blog post with hoover, but
64 | * hidden in the post.except when html and css is stripped. Ref:
65 | * https://github.com/erikw/jekyll-glossary_tooltip/issues/7#issuecomment-2711471867 */
66 | .jekyll-glossary-tooltip-hidden {
67 | display: none;
68 | }
69 |
--------------------------------------------------------------------------------
/lib/jekyll-glossary_tooltip/tag.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "jekyll"
4 | require "jekyll-glossary_tooltip/errors"
5 |
6 | module Jekyll
7 | module GlossaryTooltip
8 | # Custom liquid tag implementation.
9 | class Tag < Liquid::Tag
10 | def initialize(tag_name, args, tokens)
11 | super
12 | @opts = OptionsParser.parse(args)
13 | end
14 |
15 | def render(context)
16 | entry = lookup_entry(context.registers[:site], @opts[:term_query])
17 | @opts[:display] ||= @opts[:term_query]
18 | html = <<~HTML
19 |
20 | #{@opts[:display]}
21 | (#{entry["definition"]}#{render_tooltip_url(entry, context)})
22 |
23 | HTML
24 | html.gsub("\n", "")
25 | end
26 |
27 | private
28 |
29 | LOG_TAG = "Glossary Tag:"
30 |
31 | def render_tooltip_url(entry, context)
32 | # The content of the anchor is set from the CSS class jekyll-glossary-source-link,
33 | # so that the plugin user can customize the text without touching ruby source.
34 | return "" if entry["url"].nil?
35 |
36 | url = Liquid::Template.parse(entry["url"]).render(context).strip
37 | " "
38 | end
39 |
40 | def lookup_entry(site, term_name)
41 | entry = read_term_entry_from_config(site, term_name)
42 | raise Errors::MissingTermDefinition, term_name unless entry["definition"]
43 |
44 | entry["url"] = nil unless entry.key?("url")
45 | entry
46 | end
47 |
48 | # Retrieve a term from the glossary via the site.
49 | def read_term_entry_from_config(site, term_name)
50 | raise Errors::NoGlossaryFile unless site.data["glossary"]
51 |
52 | entries = site.data["glossary"].select do |entry|
53 | entry.key?("term") and term_name.casecmp(entry["term"]).zero?
54 | end
55 |
56 | case entries.length
57 | when 0
58 | raise Errors::MissingTermEntry, term_name
59 | when 1
60 | entries[0]
61 | else
62 | raise Errors::MultipleTermEntries, term_name
63 | end
64 | end
65 | end
66 | end
67 | end
68 |
69 | Liquid::Template.register_tag("glossary", Jekyll::GlossaryTooltip::Tag)
70 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [Unreleased]
8 |
9 | ## [2.1.0] - 2025-10-30
10 | ### Added
11 | - Unicode support [#20](https://github.com/erikw/jekyll-glossary_tooltip/pull/20)
12 | ### Changed
13 | - Migrated CI from Travis to GitHub Actions.
14 |
15 | ## [2.0.0] - 2025-03-31
16 | ### Added
17 | - [BREAKING] Hidden with CSS parenthesis around term definition. These parenthesis will be revealed when jekyll produces a post.except as typically HTML and CSS stripped => the plain text rendering of the glossary tag will be " (term-description> )". [#7](https://github.com/erikw/jekyll-glossary_tooltip/issues/7)
18 | - To **upgrade** to new version, you need to update the CSS by re-copy the full contexts of [jekyll-glossary_tooltip.css](lib/jekyll-glossary_tooltip/jekyll-glossary_tooltip.css) to your side. The new CSS class `.jekyll-glossary-tooltip-hidden` is added and needed to hide parenthesis in the tooltip.
19 |
20 | ## [1.5.1] - 2025-03-10
21 | ### Fixed
22 | - Strip newlines from generated HTML to prevent unnecessary spaces to be added. [#9](https://github.com/erikw/jekyll-glossary_tooltip/issues/9)
23 |
24 | ## [1.5.0] - 2022-09-08
25 | ### Added
26 | - Support for embedded liquid tags in the url field. ([#3](https://github.com/erikw/jekyll-glossary_tooltip/issues/3])
27 |
28 | ## [1.4.0] - 2021-08-18
29 | ### Changed
30 | * Bump local ruby to 3.1.0
31 |
32 | ## [1.3.1] - 2021-08-18
33 | ### Added
34 | - GitHub workflow to publish to GitHub Packages.
35 |
36 | ## [1.3.1] - 2021-08-18
37 | ### Fixed
38 | - gemspec dependency range stynax.
39 |
40 | ## [1.3.0] - 2021-08-07
41 | ### Changed
42 | - Open the souce link from a tooltip in a new tab.
43 |
44 | ## [1.2.0] - 2021-08-06
45 | ### Added
46 | - Bottom arrow to the tooltip.
47 | - Tooltip hover animation from invisible to visible.
48 |
49 | ### Changed
50 | - Restyle the glossary term bottom border style and color.
51 |
52 | ## [1.1.0] - 2021-08-06
53 | ### Added
54 | - Optional `display:` argument to set a different term display name, rather than using the term name as defined in the glossary file. Usage: `{% glossary term_name, display: Different Name To Display %}`.
55 |
56 | ## [1.0.0] - 2021-08-05
57 | - No changes from `v0.1.0` but just bumping to final first major release version!
58 |
59 | ## [0.1.0] - 2021-08-05
60 | - First release version. The plugin is fully working but I suspect that there might be a few point releases just to nail the release process. Once this is working, there will soon be an 1.0.0 release!
61 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "simplecov" # Must be before any application code. See conf at .simplecov
4 |
5 | require "jekyll"
6 |
7 | Jekyll.logger.log_level = :warn
8 |
9 | # Base directory for fixtures.
10 | SOURCE_DIR = File.expand_path("fixtures", __dir__)
11 | # Base directory for generated files from tests.
12 | DEST_DIR = File.expand_path("dest", __dir__)
13 |
14 | # Tag matching regex parts.
15 | R1 = %r{\s*}
16 | R2 = %r{\s*\s*}
17 | R_PAR_OPEN = %r{\s*\(\s*}
18 | R_PAR_CLOSE = %r{\s*\)\s*}
19 | R3 = %r{\s* \s*}
21 | R5 = %r{\s*}
22 |
23 | # Reference for RSpec config: https://www.rubydoc.info/github/rspec/rspec-core/RSpec/Core/Configuration
24 | # Reference on Jekyll helper functions:
25 | # - https://github.com/jekyll/jekyll-seo-tag/blob/master/spec/spec_helper.rb
26 | # - https://github.com/ayastreb/jekyll-maps/blob/master/spec/spec_helper.rb
27 | RSpec.configure do |config|
28 | config.example_status_persistence_file_path = ".rspec_status"
29 | config.order = :defined
30 | config.disable_monkey_patching!
31 | # Use rspec framework and the 'expect' syntax (instead of 'should')
32 | config.expect_with :rspec do |c|
33 | c.syntax = :expect
34 | end
35 |
36 | # Get absolute path to a file within a fixture in the source dir.
37 | def source_dir(fixture, *filesegments)
38 | File.join(SOURCE_DIR, fixture, *filesegments)
39 | end
40 |
41 | # Get absolute path to file within destination output dir.
42 | def dest_dir(*filesegments)
43 | File.join(DEST_DIR, *filesegments)
44 | end
45 |
46 | def config_defaults
47 | {
48 | "destination" => dest_dir,
49 | "gems" => ["jekyll-glossary_tooltip"] # Called "plugins" in Jekyll >=3.5.0
50 | }.freeze
51 | end
52 |
53 | # Create a Jekyll site from fixtures
54 | def make_site(options = {})
55 | site_config = Jekyll.configuration(config_defaults.merge(options))
56 | Jekyll::Site.new(site_config)
57 | end
58 |
59 | # Ensure that there was no site before each example group (=context).
60 | # Remove dest dir. For using in "after :all" blocks
61 | def remove_dest_dir
62 | FileUtils.rm_rf(dest_dir)
63 | end
64 |
65 | # Expect HTML tag components to match given content.
66 | def expect_tag_match(content, term_name, url: true, term_display: nil, href: nil)
67 | term_display ||= term_name
68 |
69 | regex = %r{#{R1}#{term_display}#{R2}#{R_PAR_OPEN}#{term_name} definition}
70 | if url
71 | href ||= "#{term_name} url"
72 | regex = Regexp.new(regex.source + %r{#{R3}#{href}#{R4}}.source)
73 | end
74 | regex = Regexp.new(regex.source + %r{#{R_PAR_CLOSE}#{R5}}.source)
75 |
76 | expect(content).to match(regex)
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/spec/jekyll-glossary_tooltip/tag_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "fileutils"
4 |
5 | require "jekyll-glossary_tooltip/tag"
6 | require "jekyll-glossary_tooltip/errors"
7 |
8 | E = Jekyll::GlossaryTooltip::Errors # Make namespace referencing easier here.
9 |
10 | RSpec.describe Jekyll::GlossaryTooltip::Tag do
11 | after(:context) { remove_dest_dir }
12 |
13 | context "when a site is correctly configured" do
14 | before(:context) do
15 | site = make_site({ "source" => source_dir("normal") })
16 | site.process
17 | end
18 |
19 | let(:page1) { File.read(dest_dir("page1.html")) }
20 | let(:page2) { File.read(dest_dir("page2.html")) }
21 | let(:page3) { File.read(dest_dir("page3.html")) }
22 | let(:page4) { File.read(dest_dir("page4.html")) }
23 | let(:page5) { File.read(dest_dir("page5.html")) }
24 | let(:page6) { File.read(dest_dir("page6.html")) }
25 | let(:page7) { File.read(dest_dir("page7.html")) }
26 | let(:page8) { File.read(dest_dir("page8.html")) }
27 |
28 | it "renders a glossary tag with a URL" do
29 | expect_tag_match(page1, "term_with_url")
30 | end
31 |
32 | it "renders a glossary tag without a URL" do
33 | expect_tag_match(page2, "term_without_url", url: false)
34 | end
35 |
36 | it "renders a glossary tag from case insensitive lookup" do
37 | expect_tag_match(page3, "TERM_CASE_INSENSITIVE", term_display: "TerM_Case_Insensitive")
38 | end
39 |
40 | it "renders a glossary tag having spaces" do
41 | expect_tag_match(page4, "term with spaces", url: false)
42 | end
43 |
44 | it "renders a glossary tag with alternative display name" do
45 | expect_tag_match(page5, "term_with_url", term_display: "term alt display name")
46 | end
47 |
48 | it "renders a glossary tag with URL rendered from embedded liquid tags" do
49 | expect_tag_match(page6, "term_with_url_embedded_liquid", href: "/page2.html")
50 | end
51 |
52 | it "renders no unnecessary space after tooltip" do
53 | # expect_tag_match(page7, "term_with_url", href: "/page2.html")
54 | term_name = "term_without_url"
55 | regex = %r{#{R1}#{term_name}#{R2}#{R_PAR_OPEN}#{term_name} definition}
56 | regex = Regexp.new(regex.source + %r{#{R_PAR_CLOSE}#{R5}, no space before comma.}.source)
57 |
58 | expect(page7).to match(regex)
59 | end
60 |
61 | it "renders a glossary tag with Unicode characters in display" do
62 | # verify that the parser accepts ‘display’ with accents/Unicode
63 | expect_tag_match(page8, "term_with_url", term_display: "José Álvarez")
64 | end
65 | end
66 |
67 | context "when a site is incorrectly configured (missing term definition)" do
68 | let(:site) { make_site({ "source" => source_dir("missing_definition") }) }
69 |
70 | it "building the site will raise an error" do
71 | expect { site.process }.to raise_error(E::MissingTermDefinition)
72 | end
73 | end
74 |
75 | context "when a site is incorrectly configured (empty term definition)" do
76 | let(:site) { make_site({ "source" => source_dir("empty_definition") }) }
77 |
78 | it "building the site will raise an error" do
79 | expect { site.process }.to raise_error(E::MissingTermDefinition)
80 | end
81 | end
82 |
83 | context "when a site is incorrectly configured (missing glossary file)" do
84 | let(:site) { make_site({ "source" => source_dir("missing_glossary") }) }
85 |
86 | it "building the site will raise an error" do
87 | expect { site.process }.to raise_error(E::NoGlossaryFile)
88 | end
89 | end
90 |
91 | context "when a site is incorrectly configured (missing term in glossary)" do
92 | let(:site) { make_site({ "source" => source_dir("missing_term") }) }
93 |
94 | it "building the site will raise an error" do
95 | expect { site.process }.to raise_error(E::MissingTermEntry)
96 | end
97 | end
98 |
99 | context "when a site is incorrectly configured (duplicate term in glossary)" do
100 | let(:site) { make_site({ "source" => source_dir("duplicate_term") }) }
101 |
102 | it "building the site will raise an error" do
103 | expect { site.process }.to raise_error(E::MultipleTermEntries)
104 | end
105 | end
106 |
107 | context "when a site is incorrectly configured (missing term arg in the tag)" do
108 | let(:site) { make_site({ "source" => source_dir("missing_tag_arg") }) }
109 |
110 | it "building the site will raise an error" do
111 | expect { site.process }.to raise_error(E::OptionsNoTermNameInTag)
112 | end
113 | end
114 | end
115 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | # See pages related at https://docs.rubocop.org/rubocop/1.12/cops_layout.html
2 |
3 | # Rubocop plugins
4 | plugins:
5 | - rubocop-rake
6 | - rubocop-rspec
7 |
8 | inherit_mode:
9 | merge:
10 | - Exclude # Merge my AllCops.Exclude with default excludes from https://github.com/rubocop/rubocop/blob/master/config/default.yml
11 |
12 | AllCops:
13 | TargetRubyVersion: 3.0
14 | Include:
15 | - lib/**/*.rb
16 | - spec/**/*.rb
17 | Exclude:
18 | # Travis: during build there will be a lot of rubocop config files in this path which will cause build failure as the refer to gems which are not installed by this project.
19 | # See https://github.com/rubocop/rubocop/issues/9832
20 | - gemfiles/vendor/bundle/**/*
21 | NewCops: disable
22 |
23 | Gemspec/DeprecatedAttributeAssignment:
24 | Enabled: true
25 | Gemspec/RequireMFA:
26 | Enabled: true
27 |
28 | Layout/LineEndStringConcatenationIndentation:
29 | Enabled: true
30 | Layout/EmptyLineBetweenDefs:
31 | Enabled: true
32 | Exclude:
33 | - lib/jekyll-glossary_tooltip/errors.rb
34 | Layout/SpaceBeforeBrackets:
35 | Enabled: true
36 |
37 | Lint/AmbiguousAssignment:
38 | Enabled: true
39 | Lint/DeprecatedConstants:
40 | Enabled: true
41 | Lint/DuplicateBranch:
42 | Enabled: true
43 | Lint/DuplicateRegexpCharacterClassElement:
44 | Enabled: true
45 | Lint/EmptyBlock:
46 | Enabled: true
47 | Lint/EmptyClass:
48 | Enabled: true
49 | Lint/AmbiguousOperatorPrecedence:
50 | Enabled: true
51 | Lint/AmbiguousRange:
52 | Enabled: true
53 | Lint/IncompatibleIoSelectWithFiberScheduler:
54 | Enabled: true
55 | Lint/RequireRelativeSelfPath:
56 | Enabled: true
57 | Lint/UselessRuby2Keywords:
58 | Enabled: true
59 | Lint/EmptyInPattern:
60 | Enabled: true
61 | Lint/LambdaWithoutLiteralBlock:
62 | Enabled: true
63 | Layout/LineLength:
64 | Max: 120
65 | Lint/NoReturnInBeginEndBlocks:
66 | Enabled: true
67 | Lint/NumberedParameterAssignment:
68 | Enabled: true
69 | Lint/OrAssignmentToConstant:
70 | Enabled: true
71 | Lint/RedundantDirGlobSort:
72 | Enabled: true
73 | Lint/SymbolConversion:
74 | Enabled: true
75 | Lint/ToEnumArguments:
76 | Enabled: true
77 | Lint/TripleQuotes:
78 | Enabled: true
79 | Lint/UnexpectedBlockArity:
80 | Enabled: true
81 | Lint/UnmodifiedReduceAccumulator:
82 | Enabled: true
83 | Lint/UnreachableCode:
84 | Severity: error
85 | Lint/UselessAccessModifier:
86 | Enabled: false
87 |
88 | Metrics/AbcSize:
89 | Enabled: true
90 | Metrics/BlockLength:
91 | Enabled: true
92 | Max: 100
93 | Metrics/MethodLength:
94 | Enabled: true
95 | Max: 25
96 |
97 | Naming/FileName:
98 | Enabled: false
99 | Exclude:
100 | - lib/jekyll-glossary_tooltip.rb
101 | Naming/InclusiveLanguage:
102 | Enabled: true
103 | Naming/BlockForwarding:
104 | Enabled: true
105 |
106 | Security/IoMethods:
107 | Enabled: true
108 |
109 | Style/ArgumentsForwarding:
110 | Enabled: true
111 | Style/CollectionCompact:
112 | Enabled: true
113 | Style/Documentation:
114 | Enabled: true
115 | Exclude:
116 | - lib/jekyll-glossary_tooltip/errors.rb
117 | Style/DocumentDynamicEvalDefinition:
118 | Enabled: true
119 | Style/EndlessMethod:
120 | Enabled: true
121 | Style/HashConversion:
122 | Enabled: true
123 | Style/HashExcept:
124 | Enabled: true
125 | Style/IfWithBooleanLiteralBranches:
126 | Enabled: true
127 | Style/InPatternThen:
128 | Enabled: true
129 | Style/MultilineInPatternThen:
130 | Enabled: true
131 | Style/NegatedIfElseCondition:
132 | Enabled: true
133 | Style/NilLambda:
134 | Enabled: true
135 | Style/QuotedSymbols:
136 | Enabled: true
137 | Style/RedundantArgument:
138 | Enabled: true
139 | Style/RegexpLiteral:
140 | Enabled: false
141 | Style/SingleLineMethods:
142 | Enabled: true
143 | Exclude:
144 | - lib/jekyll-glossary_tooltip/errors.rb
145 | Style/StringChars:
146 | Enabled: true
147 | Style/StringLiterals:
148 | Enabled: true
149 | EnforcedStyle: double_quotes
150 | Style/StringLiteralsInInterpolation:
151 | Enabled: true
152 | EnforcedStyle: double_quotes
153 | Style/SwapValues:
154 | Enabled: true
155 | Style/FileRead:
156 | Enabled: true
157 | Style/FileWrite:
158 | Enabled: true
159 | Style/MapToHash:
160 | Enabled: true
161 | Style/NumberedParameters:
162 | Enabled: true
163 | Style/NumberedParametersLimit:
164 | Enabled: true
165 | Style/OpenStructUse:
166 | Enabled: true
167 | Style/RedundantSelfAssignmentBranch:
168 | Enabled: true
169 | Style/SelectByRegexp:
170 | Enabled: true
171 |
172 |
173 | # Reference: https://github.com/rubocop/rubocop-rake/blob/master/config/default.yml
174 | Rake:
175 | Enabled: true
176 |
177 | # Reference:
178 | # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html
179 | # https://github.com/rubocop/rubocop-rspec/blob/master/config/default.yml
180 | RSpec:
181 | Enabled: true
182 | RSpec/IdenticalEqualityAssertion:
183 | Enabled: true
184 | RSpec/BeforeAfterAll:
185 | Enabled: false
186 | RSpec/ExcessiveDocstringSpacing:
187 | Enabled: true
188 | RSpec/SubjectDeclaration:
189 | Enabled: true
190 | RSpec/MultipleMemoizedHelpers:
191 | Enabled: true
192 | Max: 10
193 | RSpec/SpecFilePathFormat:
194 | # Disable to match structure of lib/. For jekyll plugin inclusion convention features, not having lib/jekyll/sth.rb but lib/jekyll-sth.rb
195 | Enabled: false
196 | RSpec/SpecFilePathSuffix:
197 | # Disable to match structure of lib/. For jekyll plugin inclusion convention features, not having lib/jekyll/sth.rb but lib/jekyll-sth.rb
198 | Enabled: false
199 | RSpec/IndexedLet:
200 | Enabled: false
201 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Jekyll Glossary Tooltip Tag Plugin [](https://x.com/intent/tweet?text=Get%20a%20nifty%20tooltip%20for%20term%20definitions%20in%20your%20Jekyll%20blog%20with%20this%20plugin&url=https://github.com/erikw/jekyll-glossary_tooltip&via=erik_westrup&hashtags=jekyll,plugin)
2 | [](https://badge.fury.io/rb/jekyll-glossary_tooltip)
3 | [](https://rubygems.org/gems/jekyll-glossary_tooltip)
4 | [](https://github.com/erikw/jekyll-glossary_tooltip/actions/workflows/ci.yml)
5 | [](https://github.com/erikw/jekyll-glossary_tooltip/actions/workflows/cd.yml)
6 | [](https://github.com/erikw/jekyll-glossary_tooltip/actions/workflows/codeql-analysis.yml)
7 | [](https://github.com/erikw/jekyll-glossary_tooltip/actions/workflows/pages/pages-build-deployment)
8 | [](https://qlty.sh/gh/erikw/projects/jekyll-glossary_tooltip)
9 | [](https://qlty.sh/gh/erikw/projects/jekyll-glossary_tooltip)
10 | [](#)
11 | [](#)
12 | [](#)
13 | [](LICENSE.txt)
14 | [](https://github.com/Netflix/osstracker)
15 |
16 |
17 |
18 |
19 |
20 |
21 | > [!TIP]
22 | > :point_right: **Live demo**: https://erikw.github.io/jekyll-glossary_tooltip/
23 |
24 |
25 |
26 |
27 | This plugin simplifies things for your website visitors and you by making it easy to define terms or abbreviations that need an explanation. Define a common dictionary of terms and their definition in a YAML file. Then, inside the markdown file, you can use the provided glossary liquid tag to insert a tooltip for a defined word from the dictionary. The tooltip will show the term definition on mouse hover.
28 |
29 | It's also possible to provide an optional URL for, for example, a term definition source reference. To also support mobile devices, this URL link is placed inside the tooltip pop-up itself, rather than making the term itself clickable. This is so that on a mobile device, you will first tap the word to get the hover tooltip, then click the link in the tooltip if desired.
30 |
31 |
32 | # Installation
33 | 1. Add this gem to your Jekyll site's Gemfile in the `:jekyll_plugins` group:
34 | * On CLI (in project root directory):
35 | ```shell
36 | bundle add --group jekyll_plugins jekyll-glossary_tooltip
37 | ```
38 | * Or manually:
39 | ```ruby
40 | group :jekyll_plugins do
41 | [...]
42 | gem 'jekyll-glossary_tooltip'
43 | end
44 | ```
45 | 1. Run `$ bundle install`.
46 | 1. In your site's `_config.yml`, enable the plugin:
47 | ```yml
48 | plugins:
49 | - jekyll-glossary_tooltip
50 | ```
51 | 1. Create a `_data/glossary.yml` file, according to the 'Glossary Term Definition File' section below, with your terms.
52 | 1. Use the liquid tag in a page like `{% glossary term_name %}`
53 | 1. Add CSS styling for the tooltip from [jekyll-glossary_tooltip.css](lib/jekyll-glossary_tooltip/jekyll-glossary_tooltip.css). You need to make sure that the pages where you will use the glossary tag have this styling applied. Typically, this would mean 1) copying this file to your `assets/css/` directory, 2) editing your theme's template for blog posts (or what pages you desire) to include this CSS in the header like ``. However, you could also copy this file's content into your `main.css` or `main.scss` or however you build your site's CSS.
54 | 1. Now just build your site, and you will get nice, nice term definition tooltips on mouse hover (or mobile, tap) for your terms!
55 | ```shell
56 | bundle exec jekyll build
57 | ```
58 |
59 | # Usage
60 | ## Glossary Term Definition File
61 | Create a file `_data/glossary.yml` to host your shared term definition entries. This file should contain a list of term entries in the format of:
62 |
63 | ```markdown
64 | - term: a_term_name # Can contain spaces
65 | definition: A description of the term
66 | url: https://jekyllrb.com/ # Is optional
67 | - term: another term
68 | definition: Some other term definition text
69 | ```
70 |
71 | This could look something like:
72 | ```markdown
73 | - term: Jekyll
74 | definition: A Static Site Generator (SSG) built with Ruby. Widely adopted as of GitHub Pages inclusion.
75 | url: https://jekyllrb.com/
76 | - term: SSG
77 | definition: A Static Site Generator compiles the website before deployment. Then the generated web content is simply retrieved as-is by the client without any code running at retrieval time.
78 | - term: Jamstack
79 | definition: JavaScript + API + Markup - a way of building and hosting websites.
80 | url: https://jamstack.org/
81 | - term: EmbeddedLiquidURL
82 | definition: This definition has a URL with embedded liquid tags to make it dynamic at build time. Note special YAML syntax for being able to use liquid (1.)
83 | url: >
84 | {{ site.baseurl }}{% link page2.md %}
85 | ```
86 |
87 | 1. See [here](https://documentation.platformos.com/use-cases/using-liquid-markup-yaml) for notes on using Liquid in YAML.
88 |
89 |
90 | ## Tag Usage
91 | On any page where you've made sure to include the needed CSS styling, you can use the glossary tag simply like
92 |
93 | ```markdown
94 | Here I'm talking about {% glossary term_name %} in a blog post.
95 |
96 | The term name can contain spaces like {% glossary operating system %}.
97 |
98 | Even if the term is defined in _data/glossary.yml as 'term_name', the matching is case-insensitive
99 | meaning that I can look it up using {% glossary TeRM_NaME %}. Note that the term is displayed as
100 | defined in the tag rather than the definition, here meaning 'TeRM_NaME'.
101 |
102 | The case-styling above works as there's still a case-insensitive match. But what about when you
103 | actually want to display the term differently? Maybe the term is defined as "cat," but you want to
104 | use the plural "cats"? Then you can supply an optional `display` argument. The syntax is:
105 | {% glossary , display: %}
106 |
107 | This could be, e.g.
108 | {% glossary cat, display: cats %}
109 | {% glossary some term, display: some other display text %}
110 | ```
111 |
112 | > [!WARNING]
113 | > A term name can not contain a `,`, as this is the argument separator character.
114 |
115 |
116 | ## CSS Style Override
117 | Simply modify the rules [jekyll-glossary_tooltip.css](lib/jekyll-glossary_tooltip/jekyll-glossary_tooltip.css) that you copied to your project. The tooltip is based on this [tutorial](https://www.w3schools.com/css/css_tooltip.asp). View the generated HTML output to see the HTML tags that are styled, or check the [tag.rb](lib/jekyll-glossary_tooltip/tag.rb) implementation in the method `render()`.
118 |
119 |
120 | ## Page listing all terms
121 | Thanks to this user-submitted [idea](https://github.com/erikw/jekyll-glossary_tooltip/issues/6) we have a way to create a page listing all terms with definitions and URLs.
122 |
123 | :point_right: **Live demo**: https://erikw.github.io/jekyll-glossary_tooltip/glossary.html
124 |
125 | Steps:
126 | 1. Install [jekyll-liquify](https://github.com/gemfarmer/jekyll-liquify) to your site according to its README instructions.
127 | 1. Create a new page in your site similar to [glossary.md](https://github.com/erikw/jekyll-glossary_tooltip/blob/gh-pages-source/glossary.md?plain=1)
128 | 1. Build your site and access your new page listing all terms!
129 |
130 | # Development
131 | The structure of this plugin was inspired by [https://ayastreb.me/writing-a-jekyll-plugin/](https://ayastreb.me/writing-a-jekyll-plugin/), the plugin jekyll-sitemap and the [Bundler Gem tutorial](https://bundler.io/guides/creating_gem.html).
132 |
133 | After checking out the repo;
134 | 1. Install [RVM](https://rvm.io/rvm/install) and install a supported Ruby version (see .gemspec)
135 | 1. run `scripts/setup` to install dependencies
136 | 1. run `scripts/test` to run the tests
137 | * Run a specific test with `bundle exec rspec -e "name of test example"`
138 | 1. You can also run `scripts/console` for an interactive prompt that will allow you to experiment.
139 |
140 | To install this gem onto your local machine, run `bundle exec rake install`.
141 |
142 |
143 | ## Local development
144 | Following the setup at [how-to-specify-local-ruby-gems-in-your-gemfile](https://rossta.net/blog/how-to-specify-local-ruby-gems-in-your-gemfile.html), these are the steps needed to build a jekyll site with a local clone of this plugin for local testing.
145 |
146 | 1. Clone this repo to your machine, say at `~/src/jekyll-glossary_tooltip`
147 | 1. In your Jekyll project's `Gemfile`:
148 | - Remove the `gem 'jekyll-glossary_tooltip'` part
149 | - Add instead `gem 'jekyll-glossary_tooltip', github: 'erikw/jekyll-glossary_tooltip', branch: 'main'`
150 | 1. Configure bundler to use a local path for this gem in this project:
151 | - `$ bundle config --local local.jekyll-glossary_tooltip ~/src/jekyll-glossary_tooltip`
152 | 1. Update the project: `$ bundle install`
153 | 1. Now the project will build with the local clone of this plugin when issuing e.g., `bundle exec jekyll build`
154 | 1. When you're done:
155 | - Remove the local override with: `$ bundle config --delete local.jekyll-glossary_tooltip`
156 | - Optionally restore the original gem included in `Gemfile` or keep building from a branch in the GitHub repo.
157 |
158 | ## Releasing
159 | Instructions for releasing on rubygems.org are below. Optionally make a GitHub [release](https://github.com/erikw/jekyll-glossary_tooltip/releases) after this for the pushed git tag.
160 |
161 | ## Using bundler/gem_tasks rake tasks
162 | Following instructions from [bundler.io](https://bundler.io/guides/creating_gem.html#releasing-the-gem):
163 | ```shell
164 | vi -p lib/jekyll-glossary_tooltip/version.rb CHANGELOG.md
165 | bundle exec rake build
166 | ver=$(ruby -r ./lib/jekyll-glossary_tooltip/version.rb -e 'puts Jekyll::GlossaryTooltip::VERSION')
167 |
168 | # Optional: test locally by including in another project
169 | gem install pkg/jekyll-glossary_tooltip-$ver.gem
170 |
171 | bundle exec rake release
172 | ```
173 |
174 | ## [recommended] Using gem-release gem extension
175 | Using [gem-release](https://github.com/svenfuchs/gem-release):
176 | ```shell
177 | vi CHANGELOG.md && git add CHANGELOG.md && git commit -m "Update CHANGELOG.md" && git push
178 | gem signin
179 | gem bump --version minor --tag --push --release --sign
180 | ```
181 | For `--version`, use `major|minor|patch` as needed.
182 |
183 | ## Multi-versions
184 | * For Ruby, just use RVM to switch between supported Ruby versions specified in `.gemspec`.
185 | * To run with different jekyll versions, [Appraisal](https://github.com/thoughtbot/appraisal) is used with [`Appraisals`](Appraisals) to generate different [`gemfiles/`](gemfiles/)
186 | - To use a specific Gemfile, run like
187 | ```shell
188 | BUNDLE_GEMFILE=gemfiles/jekyll_4.x.x.gemfile bundle exec rake spec
189 | bundle exec appraisal jekyll-4.x.x rake spec
190 | ```
191 | - To run `rake spec` for all gemfiles:
192 | ```shell
193 | bundle exec appraisal rake spec
194 | ```
195 | - To generate new/updated gemfiles from `Appraisals`
196 | ```shell
197 | bundle exec appraisal install
198 | bundle exec appraisal generate
199 | ```
200 |
201 | ## Live Demo GitHub Pages
202 | The live demo source is in the branch [`gh-pages-source`](https://github.com/erikw/jekyll-glossary_tooltip/tree/gh-pages-source). Check its `README.md`!
203 |
204 | # Contributing
205 | Bug reports and pull requests are welcome on GitHub at https://github.com/erikw/jekyll-glossary_tooltip.
206 |
207 | # License
208 | The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
209 |
210 | # Acknowledgement
211 | Thanks to [ayastreb/jekyll-maps](https://github.com/ayastreb/jekyll-maps) for inspiration on project structure and options parsing!
212 |
213 | # More Jekyll
214 | Check out my other Jekyll repositories [here](https://github.com/erikw?tab=repositories&q=jekyll-&type=&language=&sort=).
215 |
--------------------------------------------------------------------------------