Commit 256b1971 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2276219 by Wim Leers: Asset libraries should declare their license.

parent c05668e7
Loading
Loading
Loading
Loading
+139 −35
Changes for core/core.libraries.yml: 139 added lines, 35 removed lines.
Original line number Diff line number Diff line
@@ -3,6 +3,10 @@
backbone:
  remote: https://github.com/jashkenas/backbone
  version: 1.1.0
  license:
    name: MIT
    url: https://github.com/jashkenas/backbone/blob/1.1.0/LICENSE
    gpl-compatible: true
  js:
    assets/vendor/backbone/backbone.js: { weight: -19 }
  dependencies:
@@ -12,18 +16,30 @@ classList:
  remote: https://github.com/eligrey/classList.js
  # @todo Stable release required for Drupal 8.0.
  version: master
  license:
    name: Public Domain
    url: https://github.com/eligrey/classList.js/blob/master/LICENSE.md
    gpl-compatible: true
  js:
    assets/vendor/classList/classList.min.js: { weight: -21, browsers: { IE: 'lte IE 9', '!IE': false } }

ckeditor:
  remote: https://github.com/ckeditor/ckeditor-dev
  version: 4.4.0
  license:
    name: GNU-GPL-2.0-or-later
    url: https://github.com/ckeditor/ckeditor-dev/blob/887d81ac1824008b690e439a1b29eb4f13b51212/LICENSE.md
    gpl-compatible: true
  js:
    assets/vendor/ckeditor/ckeditor.js: { preprocess: false }

domready:
  remote: https://github.com/ded/domready
  version: 1.0.4
  license:
    name: MIT
    url: https://github.com/ded/domready/blob/v1.0.4/LICENSE
    gpl-compatible: true
  js:
    assets/vendor/domready/ready.min.js: { weight: -21 }

@@ -278,18 +294,30 @@ drupal.vertical-tabs:
html5shiv:
  remote: https://github.com/aFarkas/html5shiv
  version: 3.6.2
  license:
    name: GNU-GPL-2.0-or-later
    url: http://www.gnu.org/licenses/gpl-2.0.html
    gpl-compatible: true
  js:
    assets/vendor/html5shiv/html5.js: { every_page: true, weight: -22, browsers: { IE: 'lte IE 8', '!IE': false } }

jquery:
  remote: https://github.com/jquery/jquery
  version: 2.1.0
  license:
    name: MIT
    url: https://github.com/jquery/jquery/blob/2.1.0/MIT-LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery/jquery.js: { weight: -20 }

jquery.cookie:
  remote: https://github.com/carhartl/jquery-cookie
  version: v1.4.0
  license:
    name: MIT
    url: https://github.com/carhartl/jquery-cookie/blob/v1.4.0/MIT-LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery.cookie/jquery.cookie.js: {}
  dependencies:
@@ -299,6 +327,10 @@ jquery.farbtastic:
  remote: https://github.com/mattfarina/farbtastic
  # @todo Ping @robloach or @mattfarina to retroactively create this release.
  version: 1.2
  license:
    name: GNU-GPL-2.0-or-later
    url: https://github.com/mattfarina/farbtastic/blob/master/LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/farbtastic/farbtastic.js: {}
  css:
@@ -310,6 +342,10 @@ jquery.farbtastic:
jquery.form:
  remote: https://github.com/malsup/form
  version: 3.50
  license:
    name: GNU-GPL-2.0-or-later
    url: http://malsup.github.com/gpl-license-v2.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery-form/jquery.form.js: {}
  dependencies:
@@ -325,6 +361,10 @@ jquery.intrinsic:
jquery.joyride:
  remote: https://github.com/zurb/joyride
  version: v2.0.3
  license:
    name: MIT
    url: https://github.com/zurb/joyride/blob/v2.0.3/README.markdown
    gpl-compatible: true
  js:
    assets/vendor/jquery-joyride/jquery.joyride-2.0.3.js: {}
  dependencies:
@@ -334,6 +374,10 @@ jquery.joyride:
jquery.once:
  remote: https://github.com/RobLoach/jquery-once
  version: 1.2.3
  license:
    name: GNU-GPL-2.0-or-later
    url: https://github.com/RobLoach/jquery-once/blob/1.2.3/LICENSE
    gpl-compatible: true
  js:
    assets/vendor/jquery-once/jquery.once.js: { weight: -19 }
  dependencies:
@@ -341,7 +385,11 @@ jquery.once:

jquery.ui:
  remote: https://github.com/jquery/jquery-ui
  version: &jquery_ui 1.10.2
  version: &jquery_ui_version 1.10.2
  license: &jquery_ui_license
    name: MIT
    url: https://github.com/jquery/jquery-ui/blob/1.10.2/MIT-LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.core.js: { weight: -11 }
  css:
@@ -353,7 +401,8 @@ jquery.ui:
    - core/jquery

jquery.ui.accordion:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.accordion.js: {}
  css:
@@ -364,7 +413,8 @@ jquery.ui.accordion:
    - core/jquery.ui.widget

jquery.ui.autocomplete:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.autocomplete.js: {}
  css:
@@ -377,7 +427,8 @@ jquery.ui.autocomplete:
    - core/jquery.ui.menu

jquery.ui.button:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.button.js: {}
  css:
@@ -388,7 +439,8 @@ jquery.ui.button:
    - core/jquery.ui.widget

jquery.ui.datepicker:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.datepicker.js: {}
  css:
@@ -398,7 +450,8 @@ jquery.ui.datepicker:
    - core/jquery.ui

jquery.ui.dialog:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.dialog.js: {}
  css:
@@ -414,7 +467,8 @@ jquery.ui.dialog:
    - core/jquery.ui.resizable

jquery.ui.draggable:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.draggable.js: {}
  dependencies:
@@ -423,7 +477,8 @@ jquery.ui.draggable:
    - core/jquery.ui.widget

jquery.ui.droppable:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.droppable.js: {}
  dependencies:
@@ -433,103 +488,118 @@ jquery.ui.droppable:
    - core/jquery.ui.draggable

jquery.ui.effects.core:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.core.js: { weight: -9 }

jquery.ui.effects.blind:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.blind.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.bounce:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.bounce.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.clip:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.clip.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.drop:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.drop.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.explode:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.explode.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.fade:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.fade.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.fold:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.fold.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.highlight:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.highlight.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.pulsate:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.pulsate.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.scale:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.scale.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.shake:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.shake.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.slide:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.slide.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.effects.transfer:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.effects.transfer.js: {}
  dependencies:
    - core/jquery.ui.effects.core

jquery.ui.menu:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.menu.js: {}
  css:
@@ -540,19 +610,22 @@ jquery.ui.menu:
    - core/jquery.ui.widget

jquery.ui.mouse:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.mouse.js: {}
  dependencies:
    - core/jquery.ui.widget

jquery.ui.position:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.position.js: {}

jquery.ui.progressbar:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.progressbar.js: {}
  css:
@@ -563,7 +636,8 @@ jquery.ui.progressbar:
    - core/jquery.ui.widget

jquery.ui.resizable:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.resizable.js: {}
  css:
@@ -575,7 +649,8 @@ jquery.ui.resizable:
    - core/jquery.ui.mouse

jquery.ui.selectable:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.selectable.js: {}
  css:
@@ -587,7 +662,8 @@ jquery.ui.selectable:
    - core/jquery.ui.widget

jquery.ui.slider:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.slider.js: {}
  css:
@@ -599,7 +675,8 @@ jquery.ui.slider:
    - core/jquery.ui.widget

jquery.ui.sortable:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.sortable.js: {}
  dependencies:
@@ -608,7 +685,8 @@ jquery.ui.sortable:
    - core/jquery.ui.widget

jquery.ui.spinner:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.spinner.js: {}
  dependencies:
@@ -617,7 +695,8 @@ jquery.ui.spinner:
    - core/jquery.ui.button

jquery.ui.tabs:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.tabs.js: {}
  css:
@@ -628,7 +707,8 @@ jquery.ui.tabs:
    - core/jquery.ui.widget

jquery.ui.tooltip:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.tooltip.js: {}
  css:
@@ -642,13 +722,18 @@ jquery.ui.tooltip:
jquery.ui.touch-punch:
  remote: https://github.com/furf/jquery-ui-touch-punch
  version: 0.2.2
  license:
    name: GNU-GPL-2.0-or-later
    url: https://github.com/furf/jquery-ui-touch-punch
    gpl-compatible: true
  js:
    assets/vendor/jquery-ui-touch-punch/jquery.ui.touch-punch.js: {}
  dependencies:
    - core/jquery.ui

jquery.ui.widget:
  version: *jquery_ui
  version: *jquery_ui_version
  license: *jquery_ui_license
  js:
    assets/vendor/jquery.ui/ui/jquery.ui.widget.js: { weight: -10 }
  dependencies:
@@ -659,6 +744,10 @@ matchmedia:
  # @todo Contribute upstream and replace with upstream version.
  # @see http://drupal.org/node/1815602
  version: VERSION
  license:
    name: MIT
    url: https://github.com/paulirish/matchMedia.js/blob/0.1.0/LICENSE.txt
    gpl-compatible: true
  js:
    misc/matchmedia.js: {}
  dependencies:
@@ -666,6 +755,10 @@ matchmedia:

modernizr:
  remote: https://github.com/Modernizr/Modernizr
  license:
    name: MIT
    url: http://modernizr.com/license/
    gpl-compatible: true
  version: v2.6.2
  js:
    assets/vendor/modernizr/modernizr.min.js: { every_page: true, preprocess: 0, scope: header, weight: -21 }
@@ -673,6 +766,10 @@ modernizr:
normalize:
  remote: https://github.com/necolas/normalize.css
  version: 3.0.1
  license:
    name: MIT
    url: https://github.com/necolas/normalize.css/blob/master/LICENSE.md
    gpl-compatible: true
  css:
    base:
      assets/vendor/normalize-css/normalize.css: { every_page: true, weight: -20 }
@@ -682,6 +779,10 @@ picturefill:
  # @todo Contribute upstream and/or replace with upstream version.
  # @see https://drupal.org/node/1775530
  version: VERSION
  license:
    name: MIT
    url: https://github.com/scottjehl/picturefill/blob/master/LICENSE
    gpl-compatible: true
  js:
    assets/vendor/picturefill/picturefill.js: { weight: -10 }
  dependencies:
@@ -690,6 +791,9 @@ picturefill:
underscore:
  remote: https://github.com/jashkenas/underscore
  version: 1.5.2
  license:
    name: MIT
    url: https://github.com/jashkenas/underscore/blob/1.5.2/LICENSE
    gpl-compatible: true
  js:
    assets/vendor/underscore/underscore.js: { weight: -20 }
+15 −0
Changes for core/lib/Drupal/Core/Asset/Exception/LibraryDefinitionMissingLicenseException.php: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Contains \Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException.
 */

namespace Drupal\Core\Asset\Exception;

/**
 * Defines a custom exception if a library has a remote but no license.
 */
class LibraryDefinitionMissingLicenseException extends \RuntimeException {

}
+15 −0
Changes for core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@

use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
use Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
use Drupal\Component\Serialization\Yaml;
@@ -87,6 +88,20 @@ public function buildByExtension($extension) {
        }
      }

      // If this is a 3rd party library, the license info is required.
      if (isset($library['remote']) && !isset($library['license'])) {
        throw new LibraryDefinitionMissingLicenseException(sprintf("Missing license information in library definition for '%s' in %s: it has a remote, but no license.", $id, $library_file));
      }

      // Assign Drupal's license to libraries that don't have license info.
      if (!isset($library['license'])) {
        $library['license'] = array(
          'name' => 'GNU-GPL-2.0-or-later',
          'url' => 'https://drupal.org/licensing/faq',
          'gpl-compatible' => TRUE,
        );
      }

      foreach (array('js', 'css') as $type) {
        // Prepare (flatten) the SMACSS-categorized definitions.
        // @todo After Asset(ic) changes, retain the definitions as-is and
+106 −0
Changes for core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php: 106 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -346,6 +346,112 @@ public function testLibraryWithDataTypes() {
    $this->assertEquals('public://test.css', $library['css'][3]['data']);
  }

  /**
   * Tests that an exception is thrown when license is missing when 3rd party.
   *
   * @expectedException \Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException
   * @expectedExceptionMessage Missing license information in library definition for 'no-license-info-but-remote' in core/tests/Drupal/Tests/Core/Asset/library_test_files/licenses_missing_information.libraries.yml: it has a remote, but no license.
   *
   * @covers ::buildLibrariesByExtension()
   */
  public function testLibraryThirdPartyWithMissingLicense() {
    $this->moduleHandler->expects($this->atLeastOnce())
      ->method('moduleExists')
      ->with('licenses_missing_information')
      ->will($this->returnValue(TRUE));

    $path = __DIR__ . '/library_test_files';
    $path = substr($path, strlen(DRUPAL_ROOT) + 1);
    $this->libraryDiscoveryParser->setPaths('module', 'licenses_missing_information', $path);

    $this->libraryDiscoveryParser->buildByExtension('licenses_missing_information');
  }

  /**
   * Tests a library with various licenses, some GPL-compatible, some not.
   *
   * @covers ::buildLibrariesByExtension()
   */
  public function testLibraryWithLicenses() {
    $this->moduleHandler->expects($this->atLeastOnce())
      ->method('moduleExists')
      ->with('licenses')
      ->will($this->returnValue(TRUE));

    $path = __DIR__ . '/library_test_files';
    $path = substr($path, strlen(DRUPAL_ROOT) + 1);
    $this->libraryDiscoveryParser->setPaths('module', 'licenses', $path);

    $libraries = $this->libraryDiscoveryParser->buildByExtension('licenses');


    // For libraries without license info, the default license is applied.
    $library = $libraries['no-license-info'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $this->assertTrue(isset($library['license']));
    $default_license = array(
      'name' => 'GNU-GPL-2.0-or-later',
      'url' => 'https://drupal.org/licensing/faq',
      'gpl-compatible' => TRUE,
    );
    $this->assertEquals($library['license'], $default_license);

    // GPL2-licensed libraries.
    $library = $libraries['gpl2'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $expected_license = array(
      'name' => 'gpl2',
      'url' => 'https://url-to-gpl2-license',
      'gpl-compatible' => TRUE,
    );
    $this->assertEquals($library['license'], $expected_license);

    // MIT-licensed libraries.
    $library = $libraries['mit'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $expected_license = array(
      'name' => 'MIT',
      'url' => 'https://url-to-mit-license',
      'gpl-compatible' => TRUE,
    );
    $this->assertEquals($library['license'], $expected_license);

    // Libraries in the Public Domain.
    $library = $libraries['public-domain'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $expected_license = array(
      'name' => 'Public Domain',
      'url' => 'https://url-to-public-domain-license',
      'gpl-compatible' => TRUE,
    );
    $this->assertEquals($library['license'], $expected_license);

    // Apache-licensed libraries.
    $library = $libraries['apache'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $expected_license = array(
      'name' => 'apache',
      'url' => 'https://url-to-apache-license',
      'gpl-compatible' => FALSE,
    );
    $this->assertEquals($library['license'], $expected_license);

    // Copyrighted libraries.
    $library = $libraries['copyright'];
    $this->assertCount(1, $library['css']);
    $this->assertCount(1, $library['js']);
    $expected_license = array(
      'name' => '© Some company',
      'gpl-compatible' => FALSE,
    );
    $this->assertEquals($library['license'], $expected_license);
  }

}

/**
+72 −0
Changes for core/tests/Drupal/Tests/Core/Asset/library_test_files/licenses.libraries.yml: 72 added lines, 0 removed lines.
Original line number Diff line number Diff line
# No license information: should default to GPL 2.0 or later..
no-license-info:
  version: 1.0
  js:
    no-license-info.js: {}
  css:
    base:
      no-license-info.css: {}

# A library with all assets licensed under the GPL-compatible GPL 2 license.
gpl2:
  version: 1.0
  license:
    name: gpl2
    url: https://url-to-gpl2-license
    gpl-compatible: true
  js:
    gpl2.js: {}
  css:
    base:
      gpl2.css: {}

# A library with all assets licensed under the GPL-compatible MIT license.
mit:
  version: 1.0
  license:
    name: MIT
    url: https://url-to-mit-license
    gpl-compatible: true
  js:
    mit.js: {}
  css:
    base:
      mit.css: {}

# A library with all assets licensed under the GPL-compatible Public Domain.
public-domain:
  version: 1.0
  license:
    name: Public Domain
    url: https://url-to-public-domain-license
    gpl-compatible: true
  js:
    public-domain.js: {}
  css:
    base:
      public-domain.css: {}

# A library with all assets licensed under the GPL-incompatible Apache license.
apache:
  version: 1.0
  license:
    name: apache
    url: https://url-to-apache-license
    gpl-compatible: false
  js:
    apache.js: {}
  css:
    base:
      apache.css: {}

# A library with all assets licensed under the GPL-incompatible copyright.
copyright:
  version: 1.0
  license:
    name: © Some company
    gpl-compatible: false
  js:
    copyright.js: {}
  css:
    base:
      copyright.css: {}
Loading