Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pivica created an issue. See original summary.

pivica’s picture

Status: Active » Needs review
FileSize
1.83 KB
Berdir’s picture

Status: Needs review » Needs work
  1. +++ b/bs_base.theme
    @@ -22,6 +22,16 @@ function bs_base_theme_suggestions_page_alter(array &$suggestions, array $variab
    +  $res = \Drupal::theme()->getActiveTheme();
    

    $res seems a strange variable name for that, maybe $active_theme?

  2. +++ b/bs_base.theme
    @@ -112,3 +122,35 @@ function bs_base_preprocess_maintenance_page(&$variables) {
    +    if (strpos($font, '@') === 0) {
    +      $theme_name = substr($font, 1, strpos($font, '/') - 1);
    

    Overall looks good. You could also do this with a regex, less fiddling around with string functions and +1/-1 stuff:

    https://www.phpliveregex.com/p/CB2

    So that would be:

    if (preg_match('/^\@([^\/]+)(\/.+)$/', $font, $match)) {
      $href = '/' . drupal_get_path('theme', $match[1]) . $match[2];
    }
    

    Also, I think you want to check that the first character is a /, if not, then we could support it being in the active theme, so you can specify just "font/myfont.woff2", so I'd add an elseif for that.

  3. +++ b/bs_base.theme
    @@ -112,3 +122,35 @@ function bs_base_preprocess_maintenance_page(&$variables) {
    +      'type' => 'font/' . substr($font, strpos($font, ".") + 1),
    

    again, not a big deail, you could also use pathinfo() for this: pathinfo($font, PATHINFO_EXTENSION)

  4. +++ b/bs_base.theme
    @@ -112,3 +122,35 @@ function bs_base_preprocess_maintenance_page(&$variables) {
    +    ], TRUE];
    

    I think the second argument is expected to be a machine name, so I'd use something like 'bs_bse_preload_font'.

    it's a weird syntax and IIRC meant to be used to identify certain things to alter them.

pivica’s picture

Status: Needs work » Needs review
FileSize
365 bytes
2.1 KB

@Berdid thank you for the feedback.

1. to 3. make sense, i've implemented them.

> 4. I think the second argument is expected to be a machine name, so I'd use something like 'bs_bse_preload_font'.

I can't really find documentation about this in internet. However checking the source code of core `HtmlResponseAttachmentsProcessor::processHtmlHeadLink` and the comment of this method explains this differently:

  /**
   * Transform a html_head_link array into html_head and http_header arrays.
   *
   * Variable html_head_link is a special case of html_head which can be present
   * as a link item in the HTML head section, and also as a Link: HTTP header,
   * depending on options in the render array. Processing it can add to both the
   * html_head and http_header sections.
   *
   * @param array $html_head_link
   *   The 'html_head_link' value of a render array. Each head link is specified
   *   by a two-element array:
   *   - An array specifying the attributes of the link.
   *   - A boolean specifying whether the link should also be a Link: HTTP
   *     header.
   *
   * @return array
   *   An ['#attached'] section of a render array. This allows us to easily
   *   merge the results with other render arrays. The array could contain the
   *   following keys:
   *   - http_header
   *   - html_head
   */
  protected function processHtmlHeadLink(array $html_head_link) {

Note the part:

A boolean specifying whether the link should also be a Link: HTTP header.

So they are only specifying second argument to be of a type boolean and not a string (for example a machine name). And it is used to add this tags to response headers. I don't think this makes sense to do this for fonts preload links, tried with setting boolean to FALSE and it works fine.

Digging this a bit more I see that Drupal is emitting next thing in response headers:

Link: <http://primer.local/>; rel="canonical", <http://primer.local/>; rel="shortlink"

This look weird to me, maybe somewhere in core the same canonical and shortlink links are added in the same way with second argument set to TRUE instead of FALSE? Can't really tell is this a bug or not, opinions?

Berdir’s picture

+++ b/bs_base.theme
@@ -112,3 +122,40 @@ function bs_base_preprocess_maintenance_page(&$variables) {
+    // Support twig expansion syntax like @custom_theme/fonts/font1.woff.
+    if (preg_match('/^\@([^\/]+)(\/.+)$/', $font, $match)) {
+      $href = '/' . drupal_get_path('theme', $match[1]) . $match[2];
+    }
+    // Support fonts loading from the current active theme.
+    elseif (strpos($font, '/') !== 0) {
+      $active_theme = \Drupal::theme()->getActiveTheme();
+      $href = '/' . $active_theme->getPath() . '/' . $font;
+    }

Thinking more about this, I think you want to use something like file_url_transform_relative(file_create_url(drupal_get_path('module', 'ckeditor_test') . '/ckeditor_test.css')). file_create_url() has hooks that support things like separate domains for assets.

Found this while I was researching the header links, and crossorigin is technicaly only required if the font is from a different domain, but if we combine it with file_create_url() then that might happen on some sites, so that makes sense and doesn't hurt.

pivica’s picture

> Thinking more about this, I think you want to use...

Make sense, added this function for both cases.

pivica’s picture

Ops, wrong patch in last comment with one error, fixed now.

Berdir’s picture

+++ b/bs_base.theme
@@ -112,3 +122,40 @@ function bs_base_preprocess_maintenance_page(&$variables) {
+  foreach ($fonts as $font) {
+    $href = $font;
+    // Support twig expansion syntax like @custom_theme/fonts/font1.woff.
+    if (preg_match('/^\@([^\/]+)(\/.+)$/', $font, $match)) {
...
+    }
+    // Support fonts loading from the current active theme.
+    elseif (strpos($font, '/') !== 0) {
+      $active_theme = \Drupal::theme()->getActiveTheme();
+      $href = file_url_transform_relative(file_create_url(drupal_get_path('theme', $active_theme->getPath()) . '/' . $font));
+    }

note that one case is left now that doesn't go through file_create_url(), which would be something like '/libraries/something/....woff2'.

One option would be to rename $href to $uri, then you could change this if/elseif to if/elseif/else and the else would then basically to a $uri = ltrim($font, '/'), if and elseif is just $uri = drupal_get_path(...

and then you can do a single $href = file_url_transform_relative(file_create_url($uri)) below, for all cases.

pivica’s picture

Yeah you are right, i forgot the last case. Added it now.

> and the else would then basically to a $uri = ltrim($font, '/'),

This does not work well, if we remove first '/' the file_url_transform_relative() will not get it back so the path will be invalid. I've dropped ltrim call.

Came to my mind that we should also support remote urls (google fonts, etc). Added support for it and also made if/elseif/...else a bit more formal. Changes needs a new review.

pivica’s picture

Moved file_create_url call to file_url_transform_relative.

pivica’s picture

FileSize
2.53 KB

Added comment about 'Functions file_create_url() and file_url_transform_relative() are deprecated', see [#2940031].

  • pivica committed 4cf401b on 8.x-1.x
    Issue #3247543 by pivica, Berdir: Add fonts preloading support
    
pivica’s picture

Status: Needs review » Fixed

Committed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.