jekyll-sidenotes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a6bc13af6e112fda4515fd79f024754baa61ecac10f16bbde1731f2e60090d9d
4
+ data.tar.gz: f751232e94a896e772989ca95f07a30e28e7dfbf50b0e0aa704d17337d30fe13
5
+ SHA512:
6
+ metadata.gz: e9381c9280b2f78ef71e8fb24256988cdebc7a2b0774f6b9c13199804db1df5e27c36baa073f5e31e4b36ce3ac8d31f15a5e6bfbfc8ceb2fafe7745a2a12b127
7
+ data.tar.gz: aaa4fe85ff92f8e9dd24ca7c7b763e21c925556674fe12f57cbb12bf3dd7f7a6a3d995f0cacf2467ad1a59c5714cccf4c198310d0ce2dec93c67d9c2050e2d87
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ *.gem
2
+ Gemfile.lock
3
+
4
+ /.bundle/
5
+ /.yardoc
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+
13
+ spec/fixtures/_site
14
+ spec/fixtures/**/.jekyll-cache
15
+ # rspec failure tracking
16
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 3.0.0
6
+ before_install: gem install bundler -v 2.2.17
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## [0.0.1] - 2022-12-07
2
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in jekyll-sidenotes.gemspec
6
+ gemspec
7
+
8
+ gem "jekyll"
9
+ gem "nanoid"
10
+
11
+ gem "rake", "~> 13.0"
12
+
13
+ gem "rspec", "~> 3.0"
14
+
15
+ gem "rubocop", "~> 1.7"
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Jekyll::SideNotes
2
+
3
+ `jekyll-sidenotes` is similar to markdown footnotes, but adds notes that render to either the left or right of the main content. The style is inspired by [tufte-css](https://edwardtufte.github.io/tufte-css/).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'jekyll-sidenotes'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install jekyll-sidenotes
20
+
21
+ ## Syntax
22
+
23
+ ```markdown
24
+ This is what a left-sidenote[<left] and a right-sidenote[>right] look like.
25
+
26
+ [<left]: the syntax looks similar to...
27
+ [>right]: ...regular markdown footnotes.
28
+ ```
29
+
30
+ On medium to small sized screens, you can click on sidenote superscripts to show or hide their content.
31
+
32
+ Note:
33
+
34
+ - Sidenotes increment together, but separately from footnotes2. So, for example, it’s possible for there to be a ‘1’ for both a standard markdown footnote and a sidenote.
35
+ - Sidenotes require an “\n” after each definition to parse properly. A warning will display if there are missing newlines (regardless of sidenotes).
36
+
37
+ ## Influences
38
+
39
+ For clean’n’simple sidenote css implementation:
40
+ [tufte css](https://github.com/edwardtufte/tufte-css)
41
+
42
+ How to implement tufte css in jekyll.
43
+ [simply jekyll](https://github.com/raghudotcc/simply-jekyll)
44
+
45
+ For sidenote implementation comparisons.
46
+ [gwern.net](https://github.com/gwern/gwern.net)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "jekyll/sidenotes"
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__)
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,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/jekyll-sidenotes/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "jekyll-sidenotes"
7
+ spec.version = Jekyll::SideNotes::VERSION
8
+ spec.authors = ["manunamz"]
9
+ spec.email = ["manunamz@pm.me"]
10
+
11
+ spec.summary = "Extended markdown syntax for sidenotes."
12
+ spec.description = "Create sidenotes, like footnotes, in your jekyll blog by using [<left] and [>right] syntax."
13
+ spec.homepage = "https://github.com/manunamz/jekyll-sidenotes"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
+ spec.licenses = ["GPL3"]
16
+
17
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = "https://github.com/manunamz/jekyll-sidenotes"
21
+ spec.metadata["changelog_uri"] = "https://github.com/manunamz/jekyll-sidenotes/blob/main/CHANGELOG.md"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ spec.add_runtime_dependency "nanoid"
34
+
35
+ # For more information and examples about making a new gem, checkout our
36
+ # guide at: https://bundler.io/guides/creating_gem.html
37
+ end
@@ -0,0 +1,137 @@
1
+ // Sidenotes
2
+ $content-sidenote-width: .375 * $content-width;
3
+
4
+ @mixin sidenote-container {
5
+ padding-right: $gutter-spacing-sm;
6
+ padding-left: $gutter-spacing-sm;
7
+
8
+ // @include mq(md) {
9
+ // // padding-right: $gutter-spacing;
10
+ // // margin-right: $content-width / 3;
11
+ // margin-right: -$content-width / 2;
12
+ // width: $content-width / 4;
13
+ // }
14
+ @include mq(lg) {
15
+ padding-left: $gutter-spacing;
16
+ padding-right: $gutter-spacing;
17
+ }
18
+ }
19
+
20
+ // more on sidenote implementation: https://www.gwern.net/Sidenotes
21
+ .main-content {
22
+ counter-reset: sidenote-counter;
23
+
24
+ // right-sidenote
25
+ .rsn {
26
+ @include sidenote-container;
27
+ display: none;
28
+ word-wrap: break-word;
29
+
30
+ @include mq(lg) {
31
+ display: block;
32
+ float: right;
33
+ clear: right;
34
+
35
+ margin-right: -$content-sidenote-width;
36
+ width: $content-sidenote-width;
37
+ margin-top: $sp-1;
38
+ margin-bottom: 0;
39
+ font-size: $font-size-2;
40
+ // line-height: 1.3;
41
+ vertical-align: baseline;
42
+ position: relative;
43
+ }
44
+ }
45
+
46
+ // left-sidenote
47
+ .lsn {
48
+ @include sidenote-container;
49
+ display: none;
50
+ word-wrap: break-word;
51
+
52
+ @include mq(lg) {
53
+ display: block;
54
+ float: left;
55
+ clear: left;
56
+
57
+ margin-left: -$content-sidenote-width;
58
+ width: $content-sidenote-width;
59
+ margin-top: $sp-1;
60
+ margin-bottom: 0;
61
+ font-size: $font-size-2;
62
+ // line-height: 1.3;
63
+ vertical-align: baseline;
64
+ position: relative;
65
+ }
66
+ }
67
+
68
+ // all sidenotes
69
+ .sidenote-toggle:checked + .rsn,
70
+ .sidenote-toggle:checked + .lsn {
71
+ display: block;
72
+ float: left;
73
+ left: 1rem;
74
+ clear: both;
75
+ width: 95%;
76
+ margin: 1rem 2.5%;
77
+ vertical-align: baseline;
78
+ position: relative;
79
+ }
80
+
81
+ label.sidenote-toggle:not(.sidenote-number) {
82
+ display: inline;
83
+ }
84
+
85
+ .sidenote-number {
86
+ counter-increment: sidenote-counter;
87
+ }
88
+
89
+ input.sidenote-toggle {
90
+ display: none;
91
+ }
92
+
93
+ label.sidenote-number {
94
+ display: inline;
95
+ }
96
+
97
+ label.sidenote-toggle:not(.sidenote-number) {
98
+ display: none;
99
+ }
100
+
101
+ .sidenote-number:after,
102
+ .rsn:before,
103
+ .lsn:before {
104
+ position: relative;
105
+ vertical-align: baseline;
106
+ }
107
+
108
+ .sidenote-number:after {
109
+ content: counter(sidenote-counter);
110
+ color: var(--wiki-link-color);
111
+ cursor: pointer;
112
+ font-size: $font-size-2;
113
+ top: -$sp-1-75;
114
+ left: $sp-0-75;
115
+ padding-right: $sp-0-75;
116
+ }
117
+
118
+ .rsn:before,
119
+ .lsn:before {
120
+ content: counter(sidenote-counter) " ";
121
+ font-size: $font-size-2;
122
+ top: -$sp-2;
123
+ }
124
+
125
+ // blockquote .rsn,
126
+ // blockquote .lsn {
127
+ // margin-right: -82%;
128
+ // min-width: 59%;
129
+ // text-align: left;
130
+ // }
131
+
132
+ .rsn > code,
133
+ .lsn > code {
134
+ font-size: $font-size-2;
135
+ }
136
+ }
137
+ }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module SideNotes
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+ require 'jekyll'
3
+ require 'nanoid'
4
+ require 'time'
5
+
6
+ require_relative "jekyll-sidenotes/version"
7
+
8
+
9
+ module Jekyll
10
+ module SideNotes
11
+
12
+ # verify all entries end with a "\n" so sidenotes works
13
+ # (sidenotes don't detect the last definition if there is no ending "\n").
14
+ class SideNoteGenerator < Jekyll::Generator
15
+ safe true
16
+ attr_accessor :md_docs
17
+
18
+ ##
19
+ # parser constants
20
+ ##
21
+ # constants are taken from kramdown and baseparser.
22
+ # (for easier kramdown integration)
23
+
24
+ # from baseparser: https://github.com/ruby/rexml/blob/master/lib/rexml/parsers/baseparser.rb#L36
25
+ LETTER = '[:alpha:]'
26
+ COMBININGCHAR = '' # TODO
27
+ EXTENDER = '' # TODO
28
+ NCNAME_STR= "[#{LETTER}_][-[:alnum:]._#{COMBININGCHAR}#{EXTENDER}]*"
29
+ UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
30
+
31
+ # from kramdown: https://github.com/gettalong/kramdown
32
+ # from blank_line.rb
33
+ BLANK_LINE = /(?>^\s*\n)+/
34
+ # from eob.rb
35
+ EOB_MARKER = /^\^\s*?\n/
36
+ # from kramdown.rb
37
+ OPT_SPACE = / {0,3}/
38
+ # Regexp for matching indentation (one tab or four spaces)
39
+ INDENT = /^(?:\t| {4})/
40
+ # from extensions.rb
41
+ ALD_ID_CHARS = /[\w-]/
42
+ ALD_ANY_CHARS = /\\\}|[^\}]/
43
+ ALD_ID_NAME = /\w#{ALD_ID_CHARS}*/
44
+ IAL_BLOCK = /\{:(?!:|\/)(#{ALD_ANY_CHARS}+)\}\s*?\n/
45
+ IAL_BLOCK_START = /^#{OPT_SPACE}#{IAL_BLOCK}/
46
+ # from html.rb
47
+ # Some HTML elements like script belong to both categories (i.e. are valid in block and
48
+ # span HTML) and don't appear therefore!
49
+ # script, textarea
50
+ HTML_SPAN_ELEMENTS = %w[a abbr acronym b big bdo br button cite code del dfn em i img input
51
+ ins kbd label mark option q rb rbc rp rt rtc ruby samp select small
52
+ span strong sub sup tt u var]
53
+ # from paragraph.rb
54
+ LAZY_END_HTML_SPAN_ELEMENTS = HTML_SPAN_ELEMENTS + %w[script]
55
+ LAZY_END_HTML_START = /<(?>(?!(?:#{LAZY_END_HTML_SPAN_ELEMENTS.join('|')})\b)#{REXML::Parsers::BaseParser::UNAME_STR})/
56
+ LAZY_END_HTML_STOP = /<\/(?!(?:#{LAZY_END_HTML_SPAN_ELEMENTS.join('|')})\b)#{REXML::Parsers::BaseParser::UNAME_STR}\s*>/m
57
+ # from markdown.rb
58
+ # CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:#{INDENT}[ \t]*\S.*\n)+)*/
59
+ # because `.gsub(INDENT, '')` in footnote.rb
60
+ # CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:s[ \t]*\S.*\n)+)*/
61
+ # from codeblock.rb
62
+ CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:#{INDENT}[ \t]*\S.*\n)+(?:(?!#{IAL_BLOCK_START}|#{EOB_MARKER}|^#{OPT_SPACE}#{LAZY_END_HTML_STOP}|^#{OPT_SPACE}#{LAZY_END_HTML_START})^[ \t]*\S.*\n)*)*/
63
+
64
+ # footnotes (for reference)
65
+ # FOOTNOTE_DEFINITION_START = /^#{OPT_SPACE}\[\^(#{ALD_ID_NAME})\]:\s*?(.*?\n#{CODEBLOCK_MATCH})/
66
+ # FOOTNOTE_MARKER_START = /\[\^(#{ALD_ID_NAME})\]/
67
+ ##
68
+ # constants for local use
69
+ ##
70
+ # right
71
+ RIGHT_SIDENOTE_DEFINITION_START = /^#{OPT_SPACE}\[\>(#{ALD_ID_NAME})\]:\s*?(.*?\n#{CODEBLOCK_MATCH})/
72
+ RIGHT_SIDENOTE_MARKER_START = /\[\>(#{ALD_ID_NAME})\]/
73
+ # left
74
+ LEFT_SIDENOTE_DEFINITION_START = /^#{OPT_SPACE}\[\<(#{ALD_ID_NAME})\]:\s*?(.*?\n#{CODEBLOCK_MATCH})/
75
+ LEFT_SIDENOTE_MARKER_START = /\[\<(#{ALD_ID_NAME})\]/
76
+
77
+ def generate(site)
78
+
79
+ # setup markdown docs
80
+ docs = site.pages + site.docs_to_write
81
+ @md_docs = docs.filter {|doc| site.find_converter_instance(Jekyll::Converters::Markdown).matches(doc.extname) }
82
+
83
+ link_extension = !!site.config["use_html_extension"] ? '.html' : ''
84
+
85
+ @md_docs.each do |cur_doc|
86
+ # check for newlines @ eof.
87
+ # (kramdown can handle footnotes with no newline, but the regex i'm getting requires a newline after the last footnote to find it.)
88
+ if cur_doc.content[-1] != "\n"
89
+ Jekyll.logger.debug "Missing newline at end of file -- this could break sidenotes: ", cur_doc.data['title']
90
+ end
91
+ parse_sidenote(cur_doc, "left")
92
+ parse_sidenote(cur_doc, "right")
93
+ end
94
+ end
95
+
96
+ # just get tufte-style sidenotes working for now...
97
+ # if there's time, emulate gwern's method: https://github.com/gwern/gwern.net/blob/9e6893033ec63248b1f0b29df119c40d39a7dcef/css/default.css#L1223
98
+
99
+ # mark -> [<left-sidenote], [>right-sidenote]
100
+ # def -> [<left-sidenote]:, [>right-sidenote]:
101
+ # `side` should be 'right' or 'left'
102
+ def parse_sidenote(doc, side)
103
+ # left v right setup
104
+ if side == "right"
105
+ sidenote_def_regex = RIGHT_SIDENOTE_DEFINITION_START
106
+ # sidenote_mark_regex = RIGHT_SIDENOTE_MARKER_START
107
+ css_class = "rsn"
108
+ sn_regex = /\>/
109
+ elsif side == "left"
110
+ sidenote_def_regex = LEFT_SIDENOTE_DEFINITION_START
111
+ # sidenote_mark_regex = LEFT_SIDENOTE_MARKER_START
112
+ css_class = "lsn"
113
+ sn_regex = /\</
114
+ else
115
+ Jekyll.logger.warn "Can't process sidenote that is not either 'right' or 'left'."
116
+ return
117
+ end
118
+ # process sidenotes
119
+ sidenotes = doc.content.scan(sidenote_def_regex)
120
+ doc.content.gsub!(sidenote_def_regex, '') # rm sidenote defs from original note.
121
+ i = 0
122
+ sidenotes.each do |sidenote|
123
+ i += 1
124
+ mark = sidenote[0]
125
+ definition = sidenote[1]
126
+ doc.content = doc.content.gsub(
127
+ /\[#{sn_regex}(#{mark})\]/i,
128
+ "<label for=\"#{css_class}-#{i}\" class=\"sidenote-toggle sidenote-number\"></label><input type=\"checkbox\" id=\"#{css_class}-#{i}\" class=\"sidenote-toggle\"><span class=\"#{css_class}\">#{definition}</span>"
129
+ )
130
+ end
131
+ end
132
+ end
133
+
134
+ end
135
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-sidenotes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - manunamz
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-12-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nanoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Create sidenotes, like footnotes, in your jekyll blog by using [<left]
28
+ and [>right] syntax.
29
+ email:
30
+ - manunamz@pm.me
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - ".rspec"
37
+ - ".rubocop.yml"
38
+ - ".travis.yml"
39
+ - CHANGELOG.md
40
+ - Gemfile
41
+ - README.md
42
+ - Rakefile
43
+ - bin/console
44
+ - bin/setup
45
+ - jekyll-sidenotes.gemspec
46
+ - lib/jekyll-sidenotes.rb
47
+ - lib/jekyll-sidenotes/_sidenotes.scss
48
+ - lib/jekyll-sidenotes/version.rb
49
+ homepage: https://github.com/manunamz/jekyll-sidenotes
50
+ licenses:
51
+ - GPL3
52
+ metadata:
53
+ homepage_uri: https://github.com/manunamz/jekyll-sidenotes
54
+ source_code_uri: https://github.com/manunamz/jekyll-sidenotes
55
+ changelog_uri: https://github.com/manunamz/jekyll-sidenotes/blob/main/CHANGELOG.md
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 2.4.0
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.3.11
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Extended markdown syntax for sidenotes.
75
+ test_files: []