hyde-fonts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ef7f7a15334f4df1f96be84e4c34b6e5b63500170c559ec590e36379c03695f3
4
+ data.tar.gz: f3cfdf6988e1de02511abce55f29c39a940c4090140c323971fda3aa8ca2005d
5
+ SHA512:
6
+ metadata.gz: 07d8d6fdd0a29e3d458d40ec1ccff14d4952b94891b3c5aee73405d626943e894e38b8a3b9182241e6b4e7e12d25dda210f5407e3b28fa196d9ada950f29c14f
7
+ data.tar.gz: 65ccfe4b9510c92d7a05b700f4dbb84ac1fe456fa2893f58637c9d2c87a72c30c1b52b8ef66909f78613be732705041f9c533c2d2d2b885dcb4ac0e19e8e05cc
@@ -0,0 +1,24 @@
1
+ module Hyde
2
+ class FontData
3
+ attr_reader :faces
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ @faces = []
8
+ @sizes = []
9
+
10
+ return unless @data
11
+
12
+ parse_faces
13
+ end
14
+
15
+ def parse_faces
16
+
17
+ for face in @data['faces'] do
18
+ faces.push(Hyde::FontFace.new(face))
19
+ end
20
+
21
+ return faces
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ module Hyde
2
+ class FontFace
3
+ attr_reader :provider
4
+ attr_accessor :css
5
+
6
+ def initialize(face)
7
+ @name = face['name']
8
+ @provider = face['provider']
9
+ @weights = face['weights']
10
+ @variants = parse_variants
11
+ @css = []
12
+ end
13
+
14
+ def sort_variants
15
+ @variants.sort do |a, b|
16
+ (a.italic == b.italic) ? a.weight <=> b.weight : a.italic <=> b.italic
17
+ end
18
+ end
19
+
20
+ def to_s
21
+ variants = sort_variants.map { |variant| variant.to_s }
22
+
23
+ @name + ':ital,wght@' + variants.join(';')
24
+ end
25
+
26
+ private
27
+
28
+ def parse_variants
29
+ variants = []
30
+
31
+ for variant in @weights
32
+ variants.push(Hyde::FontVariant.new(weight: variant['value'], italic: variant['italic']))
33
+ end
34
+
35
+ return variants
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module Hyde
2
+ class FontRuleset
3
+ attr_reader :filename, :char_set, :family, :style, :weight, :uri, :format, :ruleset, :local_rule_set
4
+
5
+ def initialize(raw_css_ruleset)
6
+ @ruleset = raw_css_ruleset
7
+
8
+ /\/\* (?'character_set'.*) \*\// =~ raw_css_ruleset
9
+ /^\s*font-family:\s'(?'family'[\w]*)';$/ =~ raw_css_ruleset
10
+ /^\s*font-style:\s(?'style'[\w]*);$/ =~ raw_css_ruleset
11
+ /^\s*font-weight:\s(?'weight'[\w]*);$/ =~ raw_css_ruleset
12
+ /\s\ssrc:\surl\((?'uri'.*)\)\s.*\('(?'format'.*)'\);$$/ =~ raw_css_ruleset
13
+
14
+ @char_set = character_set
15
+ @family = family
16
+ @style = style
17
+ @weight = weight
18
+ @uri = URI(uri)
19
+ @format = format
20
+
21
+ @filename = [@family, @style, @weight, @char_set + '.' + @format].join('_')
22
+ end
23
+
24
+ def local_ruleset(path)
25
+ @ruleset.gsub(/(?<=url\().*(?=\)\s)/, '/' + File.join(path, @filename))
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module Hyde
2
+ class FontVariant
3
+ attr_reader :italic, :weight
4
+
5
+ def initialize(weight:, italic:)
6
+ @weight = weight
7
+ @italic = 0
8
+
9
+ if italic == true
10
+ @italic = 1
11
+ end
12
+ end
13
+
14
+ def to_s
15
+ @italic.to_s + ',' + @weight.to_s
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module Hyde
2
+ # Alternative class for jekyll's static files
3
+ # this allows the creation of files without a source file
4
+
5
+ class GeneratedCssFile < Jekyll::StaticFile
6
+ attr_accessor :file_contents
7
+ attr_reader :generator, :x
8
+
9
+ def initialize(site, dir, name)
10
+ @site = site
11
+ @dir = dir
12
+ @name = name
13
+ @relative_path = File.join(*[@dir, @name].compact)
14
+ @extname = File.extname(@name)
15
+ @type = @collection&.label&.to_sym
16
+ @generator = 'hyde_fonts'
17
+ end
18
+
19
+ def write(dest)
20
+ dest_path = destination(dest)
21
+ return false if File.exist?(dest_path)
22
+
23
+ FileUtils.mkdir_p(File.dirname(dest_path))
24
+ FileUtils.rm(dest_path) if File.exist?(dest_path)
25
+
26
+ File.open(dest_path, 'w') do |output_file|
27
+ output_file << file_contents
28
+ end
29
+
30
+ true
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ module Hyde
2
+ # Alternative class for jekyll's static files
3
+ # this allows the creation of files without a source file
4
+
5
+ class GeneratedFontFile < Jekyll::StaticFile
6
+ attr_accessor :file_contents
7
+ attr_reader :generator, :dest_path
8
+
9
+ def initialize(site, dir, name)
10
+ @site = site
11
+ @dir = dir
12
+ @name = name
13
+ @relative_path = File.join(*[@dir, @name].compact)
14
+ @extname = File.extname(@name)
15
+ @type = @collection&.label&.to_sym
16
+ @generator = 'hyde_fonts'
17
+ @dest_path = ''
18
+ end
19
+
20
+ def write(dest)
21
+ return false if File.exist?(dest_path)
22
+
23
+ @dest_path = destination(dest)
24
+ FileUtils.mkdir_p(File.dirname(dest_path))
25
+ FileUtils.rm(dest_path) if File.exist?(dest_path)
26
+
27
+ File.open(dest_path, 'w') do |output_file|
28
+ output_file << file_contents
29
+ end
30
+
31
+ true
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,111 @@
1
+ require 'jekyll'
2
+ require_relative 'font_data.rb'
3
+ require_relative 'font_face.rb'
4
+ require_relative 'font_ruleset.rb'
5
+ require_relative 'font_variant.rb'
6
+ require_relative 'generated_css_file.rb'
7
+ require_relative 'generated_font_file.rb'
8
+ require_relative 'provider_google.rb'
9
+
10
+ module Jekyll
11
+ class HydeFontsTag < Liquid::Tag
12
+ def initialize(tag_name, text, tokens)
13
+ super
14
+
15
+ @tag_name = tag_name
16
+ @text = text.strip
17
+ @tokens = tokens
18
+ end
19
+
20
+ def render(context)
21
+ config = context.registers[:site].config['hyde_fonts']
22
+ return unless config['enable'] == true
23
+
24
+ file = context.registers[:site].static_files.find { |file|
25
+ file.is_a?(Hyde::GeneratedCssFile)
26
+ }
27
+
28
+ if @text == 'inline'
29
+ file.file_contents
30
+ else
31
+ "<link href='" + file.relative_path + "' rel='stylesheet'>"
32
+ end
33
+ end
34
+ end
35
+
36
+ Liquid::Template.register_tag('hyde_fonts', Jekyll::HydeFontsTag)
37
+
38
+ class HydeFontsGenerator < Generator
39
+ def generate(site)
40
+ Hyde::Fonts.new(site).generate()
41
+ end
42
+ end
43
+ end
44
+
45
+ module Hyde
46
+ class Fonts
47
+ @@config = {
48
+ "data_path" => 'fonts',
49
+ "file_output_path" => 'assets/fonts',
50
+ "css_output_name" => 'fonts.css',
51
+ "css_minify" => true,
52
+ "enable" => true,
53
+ "fetch_fonts" => true,
54
+ "keep_files" => false
55
+ }
56
+
57
+ def initialize(site)
58
+ @site = site
59
+ @config = site.config.dig('hyde_fonts') || @@config
60
+
61
+ if config('keep_files') == true
62
+ @site.config['keep_files'].push(config('file_output_path'))
63
+ end
64
+
65
+ if site.config.dig('hyde_fonts').nil?
66
+ @site.config['hyde_fonts'] = @config
67
+ end
68
+ end
69
+
70
+ def generate
71
+ # get faces from jekyll data file
72
+ font_data = Hyde::FontData.new(data)
73
+
74
+ # handle font providers
75
+ for face in font_data.faces
76
+ case face.provider
77
+ when 'google'
78
+ Hyde::FontProviderGoogle.new(@site, @config).fetch(face)
79
+ when 'local'
80
+ # TODO handle local fonts
81
+ # Hyde::FontProviderLocal.new(@site, @config).fetch(face)
82
+ end
83
+ end
84
+
85
+ css = font_data.faces.map { |face| face.css }
86
+ # generate static file containing face css rulesets
87
+ css_file = Hyde::GeneratedCssFile.new(@site, config('file_output_path'), config('css_output_name'))
88
+ css_file.file_contents = minify(css.join("\n"))
89
+
90
+ @site.static_files << css_file
91
+ end
92
+
93
+ private
94
+
95
+ def config(*keys)
96
+ @config.dig(*keys)
97
+ end
98
+
99
+ def data
100
+ @site.data.dig(config('data_path'), 'fonts')
101
+ end
102
+
103
+ def minify(css)
104
+ return css if config('css_minify') == false
105
+
106
+ converter_config = { 'sass' => { 'style' => 'compressed' } }
107
+
108
+ Jekyll::Converters::Scss.new(converter_config).convert(css)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,71 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+
4
+ module Hyde
5
+ class FontProviderGoogle
6
+ def initialize(site, config)
7
+ @site = site
8
+ @config = config
9
+ end
10
+
11
+ def fetch(face)
12
+ @face = face
13
+
14
+ begin
15
+ uri_payload = Net::HTTP.get(face_uri, {
16
+ "User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0'
17
+ })
18
+ rescue
19
+ Jekyll.logger.warn('Fonts Warning:', 'Unable to reach Google Fonts service.')
20
+ return
21
+ end
22
+
23
+ rulesets = parse_css_payload(uri_payload)
24
+
25
+ # TODO if @config['fetch_fonts'] is false, don't download the files
26
+
27
+ for ruleset in rulesets
28
+ fetch_font_from_ruleset(ruleset)
29
+ face.css.push(rewrite_ruleset_to_local(ruleset))
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def face_uri
36
+ google_uri_base = 'https://fonts.googleapis.com/css2'
37
+ params = [['display', 'swap']]
38
+ params.push(['family', @face.to_s])
39
+
40
+ uri = google_uri_base + '?' + params.map { |param| param.join('=') }.join('&')
41
+
42
+ URI(uri)
43
+ end
44
+
45
+ def parse_css_payload(css)
46
+ css.scan(/\/\*[^}]*}/).map do |raw_ruleset|
47
+ Hyde::FontRuleset.new(raw_ruleset)
48
+ end
49
+ end
50
+
51
+ def fetch_font_from_ruleset(ruleset)
52
+ filename = ruleset.filename
53
+ file = Hyde::GeneratedFontFile.new(@site, @config['file_output_path'], filename)
54
+
55
+ destination_fname = file.destination('./')
56
+
57
+ if @config['keep_files'] == true
58
+ return if File.exist?(destination_fname)
59
+ end
60
+
61
+ font_uri_payload = Net::HTTP.get(ruleset.uri)
62
+ file.file_contents = font_uri_payload
63
+
64
+ @site.static_files << file
65
+ end
66
+
67
+ def rewrite_ruleset_to_local(ruleset)
68
+ ruleset.local_ruleset(@config['file_output_path'])
69
+ end
70
+ end
71
+ end
data/lib/hyde_fonts.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Hyde
2
+ class Fonts
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
6
+
7
+ require_relative './hyde_fonts/hyde_fonts.rb'
8
+
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hyde-fonts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gregory Daynes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ description: Hyde Fonts is a plugin for Jekyll to make adding Google fonts based on
34
+ configuration.
35
+ email: email@gregdaynes.com
36
+ executables: []
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - lib/hyde_fonts.rb
41
+ - lib/hyde_fonts/font_data.rb
42
+ - lib/hyde_fonts/font_face.rb
43
+ - lib/hyde_fonts/font_ruleset.rb
44
+ - lib/hyde_fonts/font_variant.rb
45
+ - lib/hyde_fonts/generated_css_file.rb
46
+ - lib/hyde_fonts/generated_font_file.rb
47
+ - lib/hyde_fonts/hyde_fonts.rb
48
+ - lib/hyde_fonts/provider_google.rb
49
+ homepage: https://gregdaynes.com
50
+ licenses:
51
+ - MIT
52
+ metadata: {}
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubygems_version: 3.4.6
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Plugin for jekyll to manage google fonts
72
+ test_files: []