jekyll_patternbot 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +12 -0
- data/.gitattributes +13 -0
- data/.gitignore +73 -0
- data/CHANGELOG.md +68 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +1 -0
- data/_config.yml +54 -0
- data/_data/locales/en-ca.yml +5 -0
- data/_includes/patternbot_icons.html +38 -0
- data/_includes/patternbot_pattern_brand_color_swatches.html +48 -0
- data/_includes/patternbot_pattern_brand_typeface.html +32 -0
- data/_includes/patternbot_pattern_brand_typeface_weight.html +15 -0
- data/_includes/patternbot_pattern_copy_script.html +22 -0
- data/_includes/patternbot_patternlib_pattern.html +241 -0
- data/_layouts/patternbot_pattern_internal.html +94 -0
- data/_layouts/patternbot_pattern_lib.html +214 -0
- data/_layouts/patternbot_pattern_user.html +27 -0
- data/_patterns/brand/colors.html +23 -0
- data/_patterns/brand/config.yml +22 -0
- data/_patterns/brand/logos.html +43 -0
- data/_patterns/brand/typefaces.html +18 -0
- data/_patterns/grid/config.yml +14 -0
- data/_patterns/grid/grid-sizes.html +47 -0
- data/_patterns/icons/config.yml +13 -0
- data/_patterns/icons/icons.html +91 -0
- data/_patterns/modules/config.yml +32 -0
- data/_patterns/modules/embed.html +23 -0
- data/_patterns/modules/list-groups.html +21 -0
- data/_patterns/modules/media-objects.html +16 -0
- data/_patterns/typography/config.yml +55 -0
- data/_patterns/typography/emphasis-and-edits.html +80 -0
- data/_patterns/typography/font-sizes.html +90 -0
- data/_patterns/typography/headings.html +31 -0
- data/_patterns/typography/horizontal-spacing.html +46 -0
- data/_patterns/typography/links.html +11 -0
- data/_patterns/typography/lists.html +43 -0
- data/_patterns/typography/quotations.html +17 -0
- data/_patterns/typography/size-adjustments.html +20 -0
- data/_patterns/typography/typesetting.html +32 -0
- data/_patterns/typography/vertical-spacing.html +55 -0
- data/_patterns/utilities/config.yml +11 -0
- data/_patterns/utilities/utilities.html +18 -0
- data/_plugins/jekyll_patternbot/config.rb +19 -0
- data/_plugins/jekyll_patternbot/filters/color.rb +87 -0
- data/_plugins/jekyll_patternbot/filters/number.rb +11 -0
- data/_plugins/jekyll_patternbot/filters/pattern.rb +15 -0
- data/_plugins/jekyll_patternbot/filters/text.rb +33 -0
- data/_plugins/jekyll_patternbot/finders/finder.rb +34 -0
- data/_plugins/jekyll_patternbot/finders/icons.rb +25 -0
- data/_plugins/jekyll_patternbot/finders/logos.rb +26 -0
- data/_plugins/jekyll_patternbot/finders/patterns.rb +69 -0
- data/_plugins/jekyll_patternbot/finders/sample_pages.rb +18 -0
- data/_plugins/jekyll_patternbot/generators/internal_patterns.rb +56 -0
- data/_plugins/jekyll_patternbot/generators/pattern_lib.rb +27 -0
- data/_plugins/jekyll_patternbot/generators/user_patterns.rb +57 -0
- data/_plugins/jekyll_patternbot/helpers/color.rb +26 -0
- data/_plugins/jekyll_patternbot/helpers/file.rb +17 -0
- data/_plugins/jekyll_patternbot/helpers/jekyll.rb +60 -0
- data/_plugins/jekyll_patternbot/helpers/pattern.rb +36 -0
- data/_plugins/jekyll_patternbot/hooks/pattern_lib.rb +57 -0
- data/_plugins/jekyll_patternbot/loggers/patternbot.rb +24 -0
- data/_plugins/jekyll_patternbot/parsers/css_color.rb +54 -0
- data/_plugins/jekyll_patternbot/parsers/css_font.rb +109 -0
- data/_plugins/jekyll_patternbot/parsers/css_utility.rb +27 -0
- data/_plugins/jekyll_patternbot/parsers/gridifier.rb +22 -0
- data/_plugins/jekyll_patternbot/parsers/icons.rb +27 -0
- data/_plugins/jekyll_patternbot/parsers/modulifier.rb +10 -0
- data/_plugins/jekyll_patternbot/parsers/theme.rb +39 -0
- data/_plugins/jekyll_patternbot/parsers/typografier.rb +21 -0
- data/_plugins/jekyll_patternbot/parsers/web_dev_tool.rb +41 -0
- data/_plugins/jekyll_patternbot/processors/brand.rb +22 -0
- data/_plugins/jekyll_patternbot/processors/modules.rb +35 -0
- data/_plugins/jekyll_patternbot/tags/pattern.rb +19 -0
- data/_plugins/jekyll_patternbot/tags/pattern_css.rb +27 -0
- data/_plugins/jekyll_patternbot/tags/pattern_js.rb +27 -0
- data/_plugins/jekyll_patternbot.rb +55 -0
- data/_sass/.gitignore +0 -0
- data/assets/.gitignore +0 -0
- data/assets/_patternbot/common/common.css +223 -0
- data/assets/_patternbot/common/common.min.css +1 -0
- data/assets/_patternbot/common/gridifier.css +1175 -0
- data/assets/_patternbot/common/gridifier.min.css +1 -0
- data/assets/_patternbot/common/modulifier.css +539 -0
- data/assets/_patternbot/common/modulifier.min.css +1 -0
- data/assets/_patternbot/common/typografier.css +1787 -0
- data/assets/_patternbot/common/typografier.min.css +1 -0
- data/assets/_patternbot/images/placeholder-16by9.svg +1 -0
- data/assets/_patternbot/images/placeholder-1by1.svg +1 -0
- data/assets/_patternbot/patterns/brand/brand.css +79 -0
- data/assets/_patternbot/patterns/brand/brand.min.css +1 -0
- data/assets/_patternbot/patterns/grid/grid.css +27 -0
- data/assets/_patternbot/patterns/grid/grid.min.css +1 -0
- data/assets/_patternbot/patterns/icons/icons.css +41 -0
- data/assets/_patternbot/patterns/icons/icons.min.css +1 -0
- data/assets/_patternbot/patterns/modules/modules.css +4 -0
- data/assets/_patternbot/patterns/modules/modules.min.css +1 -0
- data/assets/_patternbot/patterns/typography/typography.css +11 -0
- data/assets/_patternbot/patterns/typography/typography.min.css +1 -0
- data/assets/_patternbot/patterns/utilities/utilities.css +4 -0
- data/assets/_patternbot/patterns/utilities/utilities.min.css +1 -0
- data/assets/_patternbot/ui/gridifier.css +1175 -0
- data/assets/_patternbot/ui/main.css +513 -0
- data/assets/_patternbot/ui/main.js +301 -0
- data/assets/_patternbot/ui/modulifier.css +725 -0
- data/assets/_patternbot/ui/pattern-lib.css +4 -0
- data/assets/_patternbot/ui/pattern-lib.min.css +1 -0
- data/assets/_patternbot/ui/pattern-lib.min.js +1 -0
- data/assets/_patternbot/ui/typografier.css +1787 -0
- data/jekyll_patternbot.gemspec +34 -0
- data/package.json +35 -0
- data/version.rb +3 -0
- data/yarn.lock +2783 -0
- metadata +312 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
|
3
|
+
class UserPatternsGenerator < Jekyll::Generator
|
4
|
+
priority :normal
|
5
|
+
|
6
|
+
def initialize(site)
|
7
|
+
@site = site
|
8
|
+
end
|
9
|
+
|
10
|
+
def generate(site)
|
11
|
+
@site = site
|
12
|
+
@site.pages.concat patterns
|
13
|
+
end
|
14
|
+
|
15
|
+
def patterns
|
16
|
+
pats = []
|
17
|
+
PatternbotData[:patterns][:user].each do |pattern, data|
|
18
|
+
pats.concat pattern_pages(pattern, data)
|
19
|
+
end
|
20
|
+
pats
|
21
|
+
end
|
22
|
+
|
23
|
+
def pattern_pages(pattern, data)
|
24
|
+
pages = []
|
25
|
+
if data[:config].key? 'patterns' and not data[:config]['patterns'].nil?
|
26
|
+
data[:config]['patterns'].each do |subpattern, subdata|
|
27
|
+
pages.push to_page pattern, data, subpattern, subdata
|
28
|
+
end
|
29
|
+
end
|
30
|
+
pages
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_page(pattern, data, subpattern, subdata)
|
34
|
+
source_dir = File.expand_path File.expand_path pattern, Config['patternbot']['source']
|
35
|
+
dir = Config['patternbot']['destination'] + '/patterns/' + pattern
|
36
|
+
html = Jekyll::PageWithoutAFile.new(@site, @site.source, dir, "#{subpattern}.html")
|
37
|
+
html.data['layout'] = 'patternbot_pattern_user'
|
38
|
+
html.data['title'] = PatternHelper.title pattern, subpattern, data, subdata
|
39
|
+
html.data['_PatternbotConfig'] = Config.with_indifferent_access
|
40
|
+
html.data['_PatternbotLocale'] = PatternbotLocale.with_indifferent_access
|
41
|
+
html.data['_PatternbotData'] = PatternbotData.with_indifferent_access
|
42
|
+
html.data['_pattern'] = pattern
|
43
|
+
html.data['_pattern_data'] = data.is_a?(Hash) ? data.with_indifferent_access : {}
|
44
|
+
html.data['_subpattern'] = subpattern
|
45
|
+
html.data['_subpattern_data'] = subdata.is_a?(Hash) ? subdata.with_indifferent_access : {}
|
46
|
+
|
47
|
+
unless File.file? File.expand_path "#{subpattern}.html", source_dir
|
48
|
+
PatternbotLogger.fatal "Patternbot cannot find the associated HTML file for the “#{subpattern}” pattern listed inside the “#{pattern}” config.yml file."
|
49
|
+
end
|
50
|
+
|
51
|
+
html.content = JekyllHelper.pattern_tag_with_data(pattern, subpattern, subdata.is_a?(Hash) ? subdata['fields'] : nil)
|
52
|
+
html
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
class ColorHelper
|
3
|
+
|
4
|
+
def self.color(val)
|
5
|
+
the_color = val
|
6
|
+
if (val.match(/^\-\-/) and
|
7
|
+
PatternbotData.key? :css and
|
8
|
+
PatternbotData[:css].key? :theme and
|
9
|
+
PatternbotData[:css][:theme].key? :colors and
|
10
|
+
PatternbotData[:css][:theme][:colors].key? :raw and
|
11
|
+
PatternbotData[:css][:theme][:colors][:raw].key? val)
|
12
|
+
the_color = PatternbotData[:css][:theme][:colors][:raw][val]
|
13
|
+
end
|
14
|
+
if the_color.match? /^rgb/
|
15
|
+
rgb_bits = the_color.gsub(/[^\d,]/, '').split(/\,/)
|
16
|
+
the_color = [rgb_bits[0].to_i, rgb_bits[1].to_i, rgb_bits[2].to_i]
|
17
|
+
end
|
18
|
+
begin
|
19
|
+
return ColorContrastCalc.color_from the_color
|
20
|
+
rescue
|
21
|
+
return ColorContrastCalc.color_from 'black'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
module FileHelper
|
3
|
+
|
4
|
+
def self.strip(path)
|
5
|
+
path.sub "#{Config['patternbot']['source']}/", ''
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.list_dirs(dir)
|
9
|
+
Dir.entries(dir).select { |entry| File.directory? File.join(dir, entry) and !(entry =='.' || entry == '..') }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.list_files_with_ext(dir, ext)
|
13
|
+
Dir.glob("#{dir}/**/*.#{ext}")
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
module JekyllHelper
|
3
|
+
|
4
|
+
def self._pattern_data_source_var_name(field)
|
5
|
+
"patternbot_temp_var_#{field['name']}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self._pattern_assign_tags(fields)
|
9
|
+
assign_tags = []
|
10
|
+
for field in fields
|
11
|
+
unless field['required'] == false
|
12
|
+
if field.key? 'data'
|
13
|
+
assign_tags.push "{% assign #{self._pattern_data_source_var_name(field)}=#{field['data']['source']} %}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
assign_tags
|
18
|
+
end
|
19
|
+
|
20
|
+
def self._pattern_include_fields(fields, datasource=false)
|
21
|
+
liquid_fields = []
|
22
|
+
for field in fields
|
23
|
+
unless field['required'] == false
|
24
|
+
if field.key? 'data'
|
25
|
+
if datasource
|
26
|
+
liquid_fields.push "#{field['name']}=#{self._pattern_data_source_var_name(field)}"
|
27
|
+
else
|
28
|
+
liquid_fields.push "#{field['name']}=#{field['data']['type']}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
if field.key? 'example'
|
32
|
+
liquid_fields.push "#{field['name']}=\"#{field['example']}\""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
liquid_fields
|
37
|
+
end
|
38
|
+
|
39
|
+
def self._pattern_include(pattern, subpattern, fields)
|
40
|
+
extra_space = ' ' if fields.length > 0
|
41
|
+
"{% pattern #{pattern}/#{subpattern}#{extra_space}#{fields.join(' ')} %}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.pattern_tag(pattern, subpattern, fields)
|
45
|
+
liquid_fields = []
|
46
|
+
liquid_fields = self._pattern_include_fields fields if fields
|
47
|
+
self._pattern_include pattern, subpattern, liquid_fields
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.pattern_tag_with_data(pattern, subpattern, fields)
|
51
|
+
liquid_fields = []
|
52
|
+
liquid_fields = self._pattern_include_fields fields, true if fields
|
53
|
+
assign_tags = []
|
54
|
+
assign_tags = self._pattern_assign_tags fields if fields
|
55
|
+
assign_tags.concat [self._pattern_include(pattern, subpattern, liquid_fields)]
|
56
|
+
assign_tags.join
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
module PatternHelper
|
3
|
+
|
4
|
+
def self.slug_to_words(slug)
|
5
|
+
slug.gsub(/[\-_]/, ' ').gsub(/\s+/, ' ')
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.normalize_filename(filename)
|
9
|
+
return filename unless filename
|
10
|
+
if Config['permalink'].match? /pretty/ or not Config['permalink'].match? /\:output_ext/
|
11
|
+
if filename.match? /^index/
|
12
|
+
if filename.match? /\.html/
|
13
|
+
return filename
|
14
|
+
else
|
15
|
+
return "#{filename}.html"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
return "#{filename.sub(/\.html/, '')}/index.html"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
unless filename.match? /\.html/
|
22
|
+
return "#{filename}.html"
|
23
|
+
end
|
24
|
+
filename
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.title(pattern, subpattern, data, subdata)
|
28
|
+
group_title = self.slug_to_words(pattern).unicode_titlecase
|
29
|
+
pattern_title = self.slug_to_words(subpattern).unicode_titlecase
|
30
|
+
group_title = data['title'] if data.is_a?(Hash) and data.key?('title')
|
31
|
+
pattern_title = subdata['title'] if subdata.is_a?(Hash) and subdata.key?('title')
|
32
|
+
"#{pattern_title} · #{group_title}"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
PatternbotLogger = PatternbotConsoleLogger.new
|
3
|
+
PatternbotCache = {}
|
4
|
+
PatternbotData = {
|
5
|
+
:css => {},
|
6
|
+
:logos => false,
|
7
|
+
:icons => false,
|
8
|
+
:patterns => {},
|
9
|
+
:pages => [],
|
10
|
+
}
|
11
|
+
|
12
|
+
Jekyll::Hooks.register :site, :post_read do |site|
|
13
|
+
# File.open('/Users/thomasjbradley/Desktop/patternbot-config.json', 'w') do |f|
|
14
|
+
# f.write(JSON.pretty_generate(Config))
|
15
|
+
# end
|
16
|
+
|
17
|
+
modulifier = ModulifierParser.new(Config['patternbot']['css']['modulifier'])
|
18
|
+
PatternbotData[:css][:modulifier] = modulifier.exists? ? modulifier.info : {}
|
19
|
+
|
20
|
+
gridifier = GridifierParser.new(Config['patternbot']['css']['gridifier'])
|
21
|
+
PatternbotData[:css][:gridifier] = gridifier.exists? ? gridifier.info : {}
|
22
|
+
|
23
|
+
typografier = TypografierParser.new(Config['patternbot']['css']['typografier'])
|
24
|
+
PatternbotData[:css][:typografier] = typografier.exists? ? typografier.info : {}
|
25
|
+
|
26
|
+
theme = ThemeParser.new(Config['patternbot']['css']['theme'])
|
27
|
+
PatternbotData[:css][:theme] = theme.exists? ? theme.info : {}
|
28
|
+
|
29
|
+
logos = LogosFinder.new(Config['patternbot']['logos'])
|
30
|
+
PatternbotData[:logos] = logos.exists? ? logos.info : {}
|
31
|
+
|
32
|
+
icon_files = IconsFinder.new(Config['patternbot']['icons'])
|
33
|
+
if icon_files.exists?
|
34
|
+
icons = IconsParser.new(Config['patternbot']['icons'], icon_files.info)
|
35
|
+
PatternbotData[:icons] = icons.info
|
36
|
+
else
|
37
|
+
PatternbotData[:icons] = []
|
38
|
+
end
|
39
|
+
|
40
|
+
pattern_files = PatternsFinder.new
|
41
|
+
PatternbotData[:patterns] = {
|
42
|
+
:internal => pattern_files.internal_patterns_info,
|
43
|
+
:user => pattern_files.user_patterns_info,
|
44
|
+
}
|
45
|
+
|
46
|
+
pages = SamplePagesFinder.new
|
47
|
+
PatternbotData[:pages] = pages.info
|
48
|
+
|
49
|
+
brand_processor = BrandProcessor.new.process
|
50
|
+
modules_processor = ModulesProcessor.new.process
|
51
|
+
|
52
|
+
# File.open('/Users/thomasjbradley/Desktop/patternbot.json', 'w') do |f|
|
53
|
+
# f.write(JSON.pretty_generate(PatternbotData))
|
54
|
+
# end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
class PatternbotConsoleLogger
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@logger = Logger.new STDERR
|
6
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
7
|
+
"PATTERNBOT — #{datetime}: #{msg}\n"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def fatal(msg)
|
12
|
+
@logger.fatal "⬣ #{msg}".red
|
13
|
+
end
|
14
|
+
|
15
|
+
def warn(msg)
|
16
|
+
@logger.warn "▲ #{msg}".yellow
|
17
|
+
end
|
18
|
+
|
19
|
+
def info(msg)
|
20
|
+
@logger.info "✔ #{msg}".green
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
class CSSColorParser
|
3
|
+
|
4
|
+
def self.base
|
5
|
+
{
|
6
|
+
:primary => [],
|
7
|
+
:secondary => [],
|
8
|
+
:neutral => [],
|
9
|
+
:accent => [],
|
10
|
+
:raw => {},
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.color
|
15
|
+
{
|
16
|
+
:name => nil,
|
17
|
+
:name_pretty => nil,
|
18
|
+
:raw => nil,
|
19
|
+
:hex => nil,
|
20
|
+
:rgba => nil,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.is_color?(dec)
|
25
|
+
!!dec.match(/\-\-color\-/)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse_color(dec, val)
|
29
|
+
parsed_color = ColorHelper::color val
|
30
|
+
color = self.color.clone
|
31
|
+
color[:name] = dec
|
32
|
+
color[:name_pretty] = PatternHelper.slug_to_words(dec.sub(/\-\-color\-/, '')).unicode_titlecase
|
33
|
+
color[:raw] = val
|
34
|
+
color[:hex] = parsed_color.hex.downcase
|
35
|
+
color[:rgba] = "rgba(#{parsed_color.rgb.join(', ')}, 1)"
|
36
|
+
color
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse(data)
|
40
|
+
colors = self.base.clone
|
41
|
+
data.each do |dec, val|
|
42
|
+
if self.is_color? dec
|
43
|
+
colors[:primary].push(self.parse_color(dec, val)) if dec.match(/\-\-color\-primary/)
|
44
|
+
colors[:secondary].push(self.parse_color(dec, val)) if dec.match(/\-\-color\-secondary/)
|
45
|
+
colors[:neutral].push(self.parse_color(dec, val)) if dec.match(/\-\-color\-neutral/)
|
46
|
+
colors[:accent].push(self.parse_color(dec, val)) unless dec.match(/\-\-color\-(primary|secondary|neutral)/)
|
47
|
+
colors[:raw][dec] = val
|
48
|
+
end
|
49
|
+
end
|
50
|
+
colors
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module JekyllPatternbot
|
2
|
+
class CSSFontParser
|
3
|
+
|
4
|
+
def self.base
|
5
|
+
{
|
6
|
+
:primary => false,
|
7
|
+
:secondary => false,
|
8
|
+
:accent => [],
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.font
|
13
|
+
{
|
14
|
+
:name => nil,
|
15
|
+
:name_pretty => nil,
|
16
|
+
:css_name => nil,
|
17
|
+
:raw => nil,
|
18
|
+
:var => nil,
|
19
|
+
:weights => nil,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.font_weight
|
24
|
+
{
|
25
|
+
:css_name => nil,
|
26
|
+
:weight => 'normal',
|
27
|
+
:has_normal => false,
|
28
|
+
:has_italic => false,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.is_font?(dec)
|
33
|
+
!!dec.match(/\-\-font\-/)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.normalize_font_weight(font_weight)
|
37
|
+
font_weight_digits = font_weight.gsub /[^\d]/, ''
|
38
|
+
return 'normal' if font_weight_digits == '400'
|
39
|
+
return 'bold' if font_weight_digits == '700'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.rule_sets_to_weights(rulesets)
|
43
|
+
weights = {}
|
44
|
+
rulesets.each do |ruleset|
|
45
|
+
font_family = ruleset.get_value('font-family').gsub(/['";]/, '')
|
46
|
+
font_family_slug = font_family.to_slug.normalize.to_s
|
47
|
+
weights[font_family_slug] = {} unless weights.key? font_family_slug
|
48
|
+
font_weight = self.normalize_font_weight ruleset.get_value 'font-weight'
|
49
|
+
weights[font_family_slug][font_weight] = self.font_weight.clone unless weights[font_family_slug].key? font_weight
|
50
|
+
weights[font_family_slug][font_weight][:weight] = font_weight
|
51
|
+
weights[font_family_slug][font_weight][:css_name] = ruleset.get_value('font-family').gsub(/\;/, '').strip
|
52
|
+
weights[font_family_slug][font_weight][:has_normal] = true if ruleset.get_value('font-style').match /normal/ or ruleset.get_value('font-style').nil?
|
53
|
+
weights[font_family_slug][font_weight][:has_italic] = true if ruleset.get_value('font-style').match /italic/
|
54
|
+
end
|
55
|
+
weights
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.parse_font_file(font_url)
|
59
|
+
if font_url
|
60
|
+
parser = CssParser::Parser.new
|
61
|
+
parser.load_uri!(font_url)
|
62
|
+
font_face_rulesets = parser.find_by_selector('@font-face').map { |rules| CssParser::RuleSet.new(nil, rules) }
|
63
|
+
return nil unless font_face_rulesets
|
64
|
+
return self.rule_sets_to_weights font_face_rulesets
|
65
|
+
else
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.parse_font(dec, val, available_weights)
|
71
|
+
font_family = val.match(/[^\,\;]*/)[0].gsub(/['"]/, '')
|
72
|
+
font_family_slug = font_family.to_slug.normalize.to_s
|
73
|
+
font = self.font.clone
|
74
|
+
font[:name] = font_family_slug
|
75
|
+
font[:name_pretty] = font_family
|
76
|
+
font[:raw] = val
|
77
|
+
font[:var] = dec
|
78
|
+
if available_weights and available_weights.key? font_family_slug
|
79
|
+
font[:weights] = available_weights[font_family_slug]
|
80
|
+
font[:css_name] = available_weights[font_family_slug].values[0][:css_name]
|
81
|
+
end
|
82
|
+
font
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.parse(font_url, data)
|
86
|
+
unless PatternbotCache.key?(font_url)
|
87
|
+
if font_url != false
|
88
|
+
PatternbotLogger.warn("Patternbot downloaded CSS for fonts from the remote URL: #{font_url}")
|
89
|
+
end
|
90
|
+
fonts = self.base.clone
|
91
|
+
available_weights = self.parse_font_file(font_url)
|
92
|
+
data.each do |dec, val|
|
93
|
+
if self.is_font? dec
|
94
|
+
fonts[:primary] = self.parse_font(dec, val, available_weights) if dec.match(/\-\-font\-primary/)
|
95
|
+
fonts[:secondary] = self.parse_font(dec, val, available_weights) if dec.match(/\-\-font\-secondary/)
|
96
|
+
fonts[:accent].push self.parse_font(dec, val, available_weights) unless dec.match(/\-\-font\-(primary|secondary)/)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
PatternbotCache[font_url] = fonts
|
100
|
+
else
|
101
|
+
if font_url != false
|
102
|
+
PatternbotLogger.info("Patternbot used a cached version of the font CSS originally located at: #{font_url}")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
PatternbotCache[font_url]
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|