diff --git a/core/fonts/private/GetFormat.html b/core/fonts/private/GetFormat.html index 1c3d5ab..b77bb9c 100644 --- a/core/fonts/private/GetFormat.html +++ b/core/fonts/private/GetFormat.html @@ -22,12 +22,12 @@ {{ $irregular := dict "vnd.ms-fontobject" "embedded-opentype" "font-woff" "woff" - "ttf" "truetype" - "font-sfnt" "truetype" - "otf" "opentype" + "font-sfnt" "opentype" + "ttf" "truetype" + "otf" "opentype" + "svgz" "svg" }} {{ with index $irregular $format }} {{ $format = . }} {{ end }} - {{ return $format }} \ No newline at end of file diff --git a/core/fonts/private/GetLocals.html b/core/fonts/private/GetLocals.html index cbb3679..b68d078 100644 --- a/core/fonts/private/GetLocals.html +++ b/core/fonts/private/GetLocals.html @@ -10,31 +10,32 @@ @return Slice of strings */}} -{{ $local := slice }} +{{ $local_output := slice }} {{ $config := partialCached "huge/config/Get" "fonts" "fonts" }} -{{/* We add local */}} -{{/* 1. Font local setting is ommited */}} -{{ $add_local := not (isset . "local") }} -{{/* 2. OR font local setting is not `false` */}} -{{ $add_local = $add_local | or (ne .local false) }} -{{/* 2. AND fonts global setting `disable_local` is not true */}} -{{ $add_local = $add_local | and (not $config.disable_local) }} - -{{ if $add_local }} - {{ with .local }} - {{/* This safely append the value of .local (a string or a slice) to the $local slice */}} - {{ $local = $local | append . }} - {{ else }} - {{/* If local is not set, we'll build it ourselves based on the font family name */}} - {{ with .family }} - {{ $local = $local | append . }} +{{/* Default is always true, meaning we built it ourselves */}} +{{ $local := true }} + +{{ if isset $ "local" }} + {{ $local = $.local }} +{{ end }} +{{/* If local is neither true nor false, it means it is a string or a slice */}} +{{ if not (in (slice true false) $local) }} + {{/* This safely append the value of .local (a string or a slice) to the $local slice */}} + {{ $local_output = $local_output | append $local }} +{{ else }} + {{/* Only if it's true... */}} + {{ if $local }} + {{ with $.family }} + {{ $local_output = $local_output | append . }} {{/* If a whitespace is in the family name, we can add a local with dash in place of ws */}} {{ if in . " " }} - {{ $local = $local | append (replace . " " "-") }} + {{ $local_output = $local_output | append (replace . " " "-") }} {{ end }} {{ end }} {{ end }} + {{ end }} -{{ return $local }} \ No newline at end of file + +{{ return $local_output }} \ No newline at end of file diff --git a/core/fonts/private/GetMediaType.html b/core/fonts/private/GetMediaType.html new file mode 100644 index 0000000..c91e3e6 --- /dev/null +++ b/core/fonts/private/GetMediaType.html @@ -0,0 +1,40 @@ +{{/* + GetFormat + Retrieves the font format of a given resource + + @author @regisphilibert + + @context Resource (.) + + @access private + + @returns String + +*/}} +{{ $MainType := "font" }} +{{ $SubType := "woff2" }} +{{/* It appears CloudFlare produces an empty string when calling .MediaType.MainType or .MediaType.SubType on a woff2... + As this is by far the best font format these days in terms of support and optimization, + making it default to ensure it is not botched by cloudflare is "ok". +*/}} +{{ with .MediaType.SubType }} + {{ $SubType = . }} +{{ end }} +{{ with .MediaType.MainType }} + {{ $MainType = . }} +{{ end }} + +{{ $format := printf "%s/%s" $MainType $SubType }} + +{{/* Another weirdness for some files depending on hosting plaftorm. + Some woff file would return application/font-woff + But Chrome will print a ` has an unsupported `type` value` warning on non-font "types". +*/}} +{{ $irregular := dict + "application/font-woff" "font/woff" +}} +{{ with index $irregular $format }} + {{ $format = . }} +{{ end }} + +{{ return $format }} \ No newline at end of file diff --git a/core/fonts/private/GetPreloadTags.html b/core/fonts/private/GetPreloadTags.html index b3b69ef..90029e7 100644 --- a/core/fonts/private/GetPreloadTags.html +++ b/core/fonts/private/GetPreloadTags.html @@ -16,26 +16,30 @@ */}} {{ $tags := slice }} {{/* We list all the fonts in order to produce the data for the "prefetch" tags on all its required files */}} -{{ range partialCached "huge/fonts/private/GetFonts" "GetFonts" }} - {{ if .preload }} - {{/* We want to print */}} - {{ range .resources }} +{{/* We want to print `` */}} +{{ range $font := partialCached "huge/fonts/private/GetFonts" "GetFonts" }} + {{ with $preload := .preload }} + {{ range $font.resources }} {{ $format := partialCached "huge/fonts/private/GetFormat" . .MediaType.SubType }} - {{/* For now it makes sens to restrict preload to the most supported file format. - Future release will allow other file formats to be preloaded. - */}} - {{ if eq $format "woff2" }} - {{ $tag := dict - "name" "link" - "attr" (dict - "href" .RelPermalink - "as" "font" - "type" "font/woff2" - "rel" "preload" - "crossorigin" "anonymous" - )}} - {{ $tags = $tags | append $tag }} + {{/* If user resrticts preloading by format */}} + {{ if reflect.IsSlice $preload }} + {{/* If said font format not in the preload format list, we skip this resource */}} + {{ if not (in $preload $format) }} + {{ continue }} + {{ end }} {{ end }} + {{/* Test above failed, we can proceeed */}} + {{ $tag := dict + "name" "link" + "attr" (dict + "href" .RelPermalink + "as" "font" + "type" (partialCached "huge/fonts/private/GetMediaType" . .) + "rel" "preload" + "crossorigin" "anonymous" + ) + }} + {{ $tags = $tags | append $tag }} {{ end }} {{ end }} {{ end }} diff --git a/core/fonts/private/ParseFont.html b/core/fonts/private/ParseFont.html index 7aa2333..0536825 100644 --- a/core/fonts/private/ParseFont.html +++ b/core/fonts/private/ParseFont.html @@ -1,6 +1,6 @@ {{/* ParseFont - Parse data from Module's settings font declaration. For now it only adds a .resources containing the font files assets. + Parse data from Module's settings font declaration and base declarations @author @regisphilibert @@ -9,50 +9,68 @@ @access private @return Map - String (.family) String (.file) Slice (.local) - Boolean (.preload) + Boolean | Slice of Strings (.preload) + String (.tech) Resources (.resources) - String (.family)? - String (.weight)? - String (.style)? - String (.display)? - String (.variant)? - String (.feature-settings)? - String (.variation-settings)? + Map (.propertiers) + String (.family) + String (.weight)? + String (.style)? + String (.display)? + String (.variant)? + String (.feature-settings)? + String (.variation-settings)? */}} -{{ $font := . }} +{{ $s := newScratch }} +{{ $s.Set "data" dict }} + {{ $config := partialCached "huge/config/Get" "fonts" "fonts" }} {{ with .file }} {{ with resources.Match (print "/" . ".*") }} {{/* This ensures woff2 and woff are declared first, it seems we can't realy rely on SubType (cloufflare as '' for woff2...) */}} {{ with sort . "Name" "desc" }} - {{ $font = merge $font (dict "resources" (sort . "Name" "desc")) }} + {{ $s.SetInMap "data" "resources" (sort . "Name" "desc") }} {{ end }} {{ else }} - {{ partial "huge/console/warn" (printf "We did not find matching font files for basename `%s`.\nFont files should be added to the project's `assets` directory and match the relative path set in the font's settings." .) }} + {{ partial "huge/console/warn" (printf "We did not find matching font files for basename `/%s`.\nAs a result no @font-face CSS at-rule will be printed for this font. \nFont files should be added to the project's `assets` directory and match the relative path set in the font's settings." .) }} {{ end }} {{ end }} -{{ with partialCached "huge/fonts/private/GetLocals" . . }} - {{ $font = merge $font (dict "local" .) }} +{{ $font := . }} +{{ with $config.cascade }} + {{ $font = merge . $font }} {{ end }} -{{/* We'll charge the parsed font with its `preload` preference. */}} -{{ $preload := false }} -{{/* First we check for the global setting */}} -{{ $preload_setting := $config.preload | default "always" }} -{{ if partialCached "huge/env/When" $preload_setting $preload_setting }} - {{ $preload = . }} +{{ with partialCached "huge/fonts/private/GetLocals" $font $font }} + {{ $s.SetInMap "data" "local" . }} {{ end }} -{{/* if preload is set (can be `false`) on the declaration itself, it overwrites global's */}} -{{ if isset $ "preload" }} - {{ $preload = $.preload }} + + +{{ with partialCached "huge/fonts/private/SanitizeProperties" $font $font }} + {{ $s.SetInMap "data" "properties" . }} +{{ end }} + +{{/* We preload by default */}} +{{ $preload := true }} +{{/* We use `isset` to ensure a falsy value is taken into account if set. */}} +{{ if isset $font "preload" }} + {{ $preload = $font.preload }} +{{ end }} + + +{{ with $font.tech }} + {{ $s.SetInMap "data" "tech" . }} +{{ end }} + +{{ $s.SetInMap "data" "preload" $preload }} + +{{ if not ($s.Get "data").resources }} + {{ $s.Set "data" dict }} {{ end }} -{{ $font = merge $font (dict "preload" $preload) }} -{{ return $font }} \ No newline at end of file +{{ return $s.Get "data" }} \ No newline at end of file diff --git a/core/fonts/private/ParseFontface.html b/core/fonts/private/ParseFontface.html index 838123a..ed1ae65 100644 --- a/core/fonts/private/ParseFontface.html +++ b/core/fonts/private/ParseFontface.html @@ -9,7 +9,7 @@ @access private @use - - huge/fonts/privateParseFont + - huge/fonts/private/ParseFont @return Map String (.font-family) @@ -35,43 +35,22 @@ {{ range . }} {{ $format := partialCached "huge/fonts/private/GetFormat" . .MediaType.SubType }} - {{ $css_srcs = $css_srcs | append (printf `url("%s") format("%s")` .RelPermalink $format) }} + {{ $src := printf `url("%s") format("%s")` .RelPermalink $format }} + {{ with $font.tech }} + {{ $src = printf `%s tech("%s")` $src . }} + {{ end }} + {{ $css_srcs = $css_srcs | append $src }} {{ end }} {{ with $css_srcs }} {{ $s.SetInMap "font" "src" (delimit . ",\n") }} {{ end }} {{ end }} -{{ end }} - -{{ $properties := slice - "family" - "weight" - "style" - "display" - "variant" - "feature-settings" - "variation-settings" - "stretch" -}} -{{/* In order to tolerate if user uses `font-{property}: value` in the settings instead of `{property}: value`, -we add font-{property} to the valid properties */}} -{{ range $properties }} - {{ $properties = $properties | append (print "font-" .) }} -{{ end }} -{{ range $property := $properties }} - {{ with index $ . }} - {{ $key := $property }} - {{/* If missing font- we prepend the property */}} - {{ if not (in $key "font-") }} - {{ $key = print "font-" $property }} + {{ with .properties }} + {{ range $key, $v := . }} + {{ $s.SetInMap "font" (print "font-" $key) . }} {{ end }} - {{ $s.SetInMap "font" $key . }} {{ end }} {{ end }} -{{ if not (index ($s.Get "font") "font-display") }} - {{ $s.SetInMap "font" "font-display" "swap" }} -{{ end }} - {{ return $s.Get "font" }} \ No newline at end of file diff --git a/core/fonts/private/SanitizeProperties.html b/core/fonts/private/SanitizeProperties.html new file mode 100644 index 0000000..c74931d --- /dev/null +++ b/core/fonts/private/SanitizeProperties.html @@ -0,0 +1,38 @@ +{{/* + SanitizeProperties + Eliminate any property which is not a font property to be used in @font-face declaration. + Also clean the key (font-display > display) + + @author @regisphilibert + + @context Map (.) + + @access private + + @returns Map + +*/}} +{{ $s := newScratch }} +{{ $s.Set "data" dict }} + +{{ $property_keys := slice + "family" + "weight" + "style" + "display" + "variant" + "feature-settings" + "variation-settings" + "stretch" +}} +{{ range $key := $property_keys }} + {{ with index $ $key }} + {{ $s.SetInMap "data" $key . }} + {{ else }} + {{ with index $ (printf "font-" $key) }} + {{ $s.SetInMap "data" $key . }} + {{ end }} + {{ end }} +{{ end }} + +{{ return $s.Get "data" }} \ No newline at end of file