Issue #2258313 by Wim Leers, nod_, ravi.shankar, lauriii, catch, mfb, longwave, corbacho, alexpott, sun, Owen Barton, tstoeckler: Add license information to aggregated assets
parent
d0154b5bfd
commit
53a59af925
|
@ -138,6 +138,8 @@ class AssetResolver implements AssetResolverInterface {
|
|||
if (isset($definition['css'])) {
|
||||
foreach ($definition['css'] as $options) {
|
||||
$options += $default_options;
|
||||
// Copy the asset library license information to each file.
|
||||
$options['license'] = $definition['license'];
|
||||
|
||||
// Files with a query string cannot be preprocessed.
|
||||
if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
|
||||
|
@ -244,6 +246,8 @@ class AssetResolver implements AssetResolverInterface {
|
|||
if (isset($definition['js'])) {
|
||||
foreach ($definition['js'] as $options) {
|
||||
$options += $default_options;
|
||||
// Copy the asset library license information to each file.
|
||||
$options['license'] = $definition['license'];
|
||||
|
||||
// 'scope' is a calculated option, based on which libraries are
|
||||
// marked to be loaded from the header (see above).
|
||||
|
|
|
@ -124,7 +124,14 @@ class CssCollectionOptimizer implements AssetCollectionOptimizerInterface {
|
|||
if (empty($uri) || !file_exists($uri)) {
|
||||
// Optimize each asset within the group.
|
||||
$data = '';
|
||||
$current_license = FALSE;
|
||||
foreach ($css_group['items'] as $css_asset) {
|
||||
// Ensure license information is available as a comment after
|
||||
// optimization.
|
||||
if ($css_asset['license'] !== $current_license) {
|
||||
$data .= "/* @license " . $css_asset['license']['name'] . " " . $css_asset['license']['url'] . " */\n";
|
||||
}
|
||||
$current_license = $css_asset['license'];
|
||||
$data .= $this->optimizer->optimize($css_asset);
|
||||
}
|
||||
// Per the W3C specification at
|
||||
|
@ -138,7 +145,7 @@ class CssCollectionOptimizer implements AssetCollectionOptimizerInterface {
|
|||
REGEXP;
|
||||
preg_match_all($regexp, $data, $matches);
|
||||
$data = preg_replace($regexp, '', $data);
|
||||
$data = implode('', $matches[0]) . $data;
|
||||
$data = implode('', $matches[0]) . (!empty($matches[0]) ? "\n" : '') . $data;
|
||||
// Dump the optimized CSS for this group into an aggregate file.
|
||||
$uri = $this->dumper->dump($data, 'css');
|
||||
// Set the URI for this group's aggregate file.
|
||||
|
|
|
@ -160,7 +160,14 @@ class CssCollectionOptimizerLazy implements AssetCollectionGroupOptimizerInterfa
|
|||
public function optimizeGroup(array $group): string {
|
||||
// Optimize each asset within the group.
|
||||
$data = '';
|
||||
$current_license = FALSE;
|
||||
foreach ($group['items'] as $css_asset) {
|
||||
// Ensure license information is available as a comment after
|
||||
// optimization.
|
||||
if ($css_asset['license'] !== $current_license) {
|
||||
$data .= "/* @license " . $css_asset['license']['name'] . " " . $css_asset['license']['url'] . " */\n";
|
||||
}
|
||||
$current_license = $css_asset['license'];
|
||||
$data .= $this->optimizer->optimize($css_asset);
|
||||
}
|
||||
// Per the W3C specification at
|
||||
|
@ -174,7 +181,7 @@ class CssCollectionOptimizerLazy implements AssetCollectionGroupOptimizerInterfa
|
|||
REGEXP;
|
||||
preg_match_all($regexp, $data, $matches);
|
||||
$data = preg_replace($regexp, '', $data);
|
||||
return implode('', $matches[0]) . $data;
|
||||
return implode('', $matches[0]) . (!empty($matches[0]) ? "\n" : '') . $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -124,7 +124,14 @@ class JsCollectionOptimizer implements AssetCollectionOptimizerInterface {
|
|||
if (empty($uri) || !file_exists($uri)) {
|
||||
// Concatenate each asset within the group.
|
||||
$data = '';
|
||||
$current_license = FALSE;
|
||||
foreach ($js_group['items'] as $js_asset) {
|
||||
// Ensure license information is available as a comment after
|
||||
// optimization.
|
||||
if ($js_asset['license'] !== $current_license) {
|
||||
$data .= "/* @license " . $js_asset['license']['name'] . " " . $js_asset['license']['url'] . " */\n";
|
||||
}
|
||||
$current_license = $js_asset['license'];
|
||||
// Optimize this JS file, but only if it's not yet minified.
|
||||
if (isset($js_asset['minified']) && $js_asset['minified']) {
|
||||
$data .= file_get_contents($js_asset['data']);
|
||||
|
|
|
@ -172,7 +172,14 @@ class JsCollectionOptimizerLazy implements AssetCollectionGroupOptimizerInterfac
|
|||
*/
|
||||
public function optimizeGroup(array $group): string {
|
||||
$data = '';
|
||||
$current_license = FALSE;
|
||||
foreach ($group['items'] as $js_asset) {
|
||||
// Ensure license information is available as a comment after
|
||||
// optimization.
|
||||
if ($js_asset['license'] !== $current_license) {
|
||||
$data .= "/* @license " . $js_asset['license']['name'] . " " . $js_asset['license']['url'] . " */\n";
|
||||
}
|
||||
$current_license = $js_asset['license'];
|
||||
// Optimize this JS file, but only if it's not yet minified.
|
||||
if (isset($js_asset['minified']) && $js_asset['minified']) {
|
||||
$data .= file_get_contents($js_asset['data']);
|
||||
|
|
|
@ -53,6 +53,11 @@ class CssCollectionOptimizerLazyUnitTest extends UnitTestCase {
|
|||
$mock_time = $this->createMock(TimeInterface::class);
|
||||
$mock_language = $this->createMock(LanguageManagerInterface::class);
|
||||
$optimizer = new CssCollectionOptimizerLazy($mock_grouper, $mock_optimizer, $mock_theme_manager, $mock_dependency_resolver, new RequestStack(), $mock_file_system, $mock_config_factory, $mock_file_url_generator, $mock_time, $mock_language, $mock_state);
|
||||
$gpl_license = [
|
||||
'name' => 'GNU-GPL-2.0-or-later',
|
||||
'url' => 'https://www.drupal.org/licensing/faq',
|
||||
'gpl-compatible' => TRUE,
|
||||
];
|
||||
$aggregate = $optimizer->optimizeGroup(
|
||||
[
|
||||
'items' => [
|
||||
|
@ -60,11 +65,13 @@ class CssCollectionOptimizerLazyUnitTest extends UnitTestCase {
|
|||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import_not_preprocessed.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
@ -72,4 +79,74 @@ class CssCollectionOptimizerLazyUnitTest extends UnitTestCase {
|
|||
self::assertStringEqualsFile(__DIR__ . '/css_test_files/css_input_with_import.css.optimized.aggregated.css', $aggregate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that license information is added correctly to aggregated CSS.
|
||||
*
|
||||
* Checks that license information is added only once when several files
|
||||
* have the same license. Checks that multiple licenses are added properly.
|
||||
*/
|
||||
public function testCssLicenseAggregation(): void {
|
||||
$mock_grouper = $this->createMock(AssetCollectionGrouperInterface::class);
|
||||
$mock_grouper->method('group')
|
||||
->willReturnCallback(function ($assets) {
|
||||
return [
|
||||
[
|
||||
'items' => $assets,
|
||||
'type' => 'file',
|
||||
'preprocess' => TRUE,
|
||||
],
|
||||
];
|
||||
});
|
||||
$mock_optimizer = $this->createMock(AssetOptimizerInterface::class);
|
||||
$mock_optimizer->method('optimize')
|
||||
->willReturn(
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_input_with_import.css.optimized.css'),
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_subfolder/css_input_with_import.css.optimized.css'),
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_input_without_import.css.optimized.css')
|
||||
);
|
||||
$mock_theme_manager = $this->createMock(ThemeManagerInterface::class);
|
||||
$mock_dependency_resolver = $this->createMock(LibraryDependencyResolverInterface::class);
|
||||
$mock_state = $this->createMock(StateInterface::class);
|
||||
$mock_file_system = $this->createMock(FileSystemInterface::class);
|
||||
$mock_config_factory = $this->createMock(ConfigFactoryInterface::class);
|
||||
$mock_file_url_generator = $this->createMock(FileUrlGeneratorInterface::class);
|
||||
$mock_time = $this->createMock(TimeInterface::class);
|
||||
$mock_language = $this->createMock(LanguageManagerInterface::class);
|
||||
$optimizer = new CssCollectionOptimizerLazy($mock_grouper, $mock_optimizer, $mock_theme_manager, $mock_dependency_resolver, new RequestStack(), $mock_file_system, $mock_config_factory, $mock_file_url_generator, $mock_time, $mock_language, $mock_state);
|
||||
$gpl_license = [
|
||||
'name' => 'GNU-GPL-2.0-or-later',
|
||||
'url' => 'https://www.drupal.org/licensing/faq',
|
||||
'gpl-compatible' => TRUE,
|
||||
];
|
||||
$aggregate = $optimizer->optimizeGroup(
|
||||
[
|
||||
'items' => [
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import_not_preprocessed.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/css_input_without_import.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/css_input_without_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => [
|
||||
'name' => 'MIT',
|
||||
'url' => 'https://opensource.org/licenses/MIT',
|
||||
'gpl-compatible' => TRUE,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
self::assertStringEqualsFile(__DIR__ . '/css_test_files/css_license.css.optimized.aggregated.css', $aggregate);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,20 +64,96 @@ class CssCollectionOptimizerUnitTest extends UnitTestCase {
|
|||
$mock_file_system = $this->createMock(FileSystemInterface::class);
|
||||
$mock_time = $this->createMock(TimeInterface::class);
|
||||
$this->optimizer = new CssCollectionOptimizer($mock_grouper, $mock_optimizer, $mock_dumper, $mock_state, $mock_file_system, $mock_time);
|
||||
$gpl_license = [
|
||||
'name' => 'GNU-GPL-2.0-or-later',
|
||||
'url' => 'https://www.drupal.org/licensing/faq',
|
||||
'gpl-compatible' => TRUE,
|
||||
];
|
||||
$this->optimizer->optimize([
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import_not_preprocessed.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
],
|
||||
[]);
|
||||
self::assertEquals(file_get_contents(__DIR__ . '/css_test_files/css_input_with_import.css.optimized.aggregated.css'), $this->dumperData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that CSS imports with strange letters do not destroy the CSS output.
|
||||
*
|
||||
* Checks that license information is added only once when several files
|
||||
* have the same license. Checks that multiple licenses are added properly.
|
||||
*
|
||||
* @group legacy
|
||||
*/
|
||||
public function testCssLicenseAggregation() {
|
||||
$mock_grouper = $this->createMock(AssetCollectionGrouperInterface::class);
|
||||
$mock_grouper->method('group')
|
||||
->willReturnCallback(function ($assets) {
|
||||
return [
|
||||
[
|
||||
'items' => $assets,
|
||||
'type' => 'file',
|
||||
'preprocess' => TRUE,
|
||||
],
|
||||
];
|
||||
});
|
||||
$mock_optimizer = $this->createMock(AssetOptimizerInterface::class);
|
||||
$mock_optimizer->method('optimize')
|
||||
->willReturn(
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_input_with_import.css.optimized.css'),
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_subfolder/css_input_with_import.css.optimized.css'),
|
||||
file_get_contents(__DIR__ . '/css_test_files/css_input_without_import.css.optimized.css')
|
||||
);
|
||||
$mock_dumper = $this->createMock(AssetDumperInterface::class);
|
||||
$mock_dumper->method('dump')
|
||||
->willReturnCallback(function ($css) {
|
||||
$this->dumperData = $css;
|
||||
});
|
||||
$mock_state = $this->createMock(StateInterface::class);
|
||||
$mock_file_system = $this->createMock(FileSystemInterface::class);
|
||||
$mock_time = $this->createMock(TimeInterface::class);
|
||||
$this->optimizer = new CssCollectionOptimizer($mock_grouper, $mock_optimizer, $mock_dumper, $mock_state, $mock_file_system, $mock_time);
|
||||
$gpl_license = [
|
||||
'name' => 'GNU-GPL-2.0-or-later',
|
||||
'url' => 'https://www.drupal.org/licensing/faq',
|
||||
'gpl-compatible' => TRUE,
|
||||
];
|
||||
$this->optimizer->optimize([
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/common_test_css_import_not_preprocessed.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/common_test_css_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => $gpl_license,
|
||||
],
|
||||
'core/modules/system/tests/modules/common_test/css_input_without_import.css' => [
|
||||
'type' => 'file',
|
||||
'data' => 'core/modules/system/tests/modules/common_test/css_input_without_import.css',
|
||||
'preprocess' => TRUE,
|
||||
'license' => [
|
||||
'name' => 'MIT',
|
||||
'url' => 'https://opensource.org/licenses/MIT',
|
||||
'gpl-compatible' => TRUE,
|
||||
],
|
||||
],
|
||||
],
|
||||
[]);
|
||||
self::assertEquals(file_get_contents(__DIR__ . '/css_test_files/css_license.css.optimized.aggregated.css'), $this->dumperData);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap") print;@import url('import1.css') screen;@import url("http://example.com/style.css");@import url("//example.com/style.css");@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap");@import url("http://example.com/style.css") screen and (orientation:landscape);@import "http://example.com/style.css" screen;@import "http://example.com/style.css" supports(display:table-cell);@import "http://example.com/style.css" supports(display:table-cell) screen;@import url("http://example.com/style.css") screen and (orientation:landscape);@import url("http://example.com/style.css") screen;@import url("http://user:pass@example.com/style.css") screen and (orientation:landscape);@import url(http://example.com/cus\(t;om.css);@import url('http://example.com/cu(st;o)m.css');@import url("http://user:pass@example.com/cu(s)t;om.css");@import url(http://user:pass@example.com/cu\(s\)t;om.css);ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap") print;@import url('import1.css') screen;@import url("http://example.com/style.css");@import url("//example.com/style.css");@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap");@import url("http://example.com/style.css") screen and (orientation:landscape);@import "http://example.com/style.css" screen;@import "http://example.com/style.css" supports(display:table-cell);@import "http://example.com/style.css" supports(display:table-cell) screen;@import url("http://example.com/style.css") screen and (orientation:landscape);@import url("http://example.com/style.css") screen;@import url("http://user:pass@example.com/style.css") screen and (orientation:landscape);@import url(http://example.com/cus\(t;om.css);@import url('http://example.com/cu(st;o)m.css');@import url("http://user:pass@example.com/cu(s)t;om.css");@import url(http://user:pass@example.com/cu\(s\)t;om.css);
|
||||
/* @license GNU-GPL-2.0-or-later https://www.drupal.org/licensing/faq */
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
p,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap") print;@import url('import1.css') screen;@import url("http://example.com/style.css");@import url("//example.com/style.css");@import url("https://fonts.fontprovider.com/css2?family=Roboto+Mono:wght@300;400&family=Roboto:ital,wght@0,300;0,400;1,300;1,400&display=swap");@import url("http://example.com/style.css") screen and (orientation:landscape);@import "http://example.com/style.css" screen;@import "http://example.com/style.css" supports(display:table-cell);@import "http://example.com/style.css" supports(display:table-cell) screen;@import url("http://example.com/style.css") screen and (orientation:landscape);@import url("http://example.com/style.css") screen;@import url("http://user:pass@example.com/style.css") screen and (orientation:landscape);@import url(http://example.com/cus\(t;om.css);@import url('http://example.com/cu(st;o)m.css');@import url("http://user:pass@example.com/cu(s)t;om.css");@import url(http://user:pass@example.com/cu\(s\)t;om.css);
|
||||
/* @license GNU-GPL-2.0-or-later https://www.drupal.org/licensing/faq */
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
p,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
ul,select{font:1em/160% Verdana,sans-serif;color:#494949;}.ui-icon{background-image:url(../images/icon.png);}.data .double-quote{background-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");}.data .single-quote{background-image:url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AKAAH//Z');}.data .no-quote{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAEAQAAAAAo/mtHAAAAIElEQVQIHWMRnWHwcRNLN8NZ7QYWwT8PlBlYsgqVBRsAankIMw5MtnoAAAAASUVORK5CYII=);}
|
||||
p,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
||||
/* @license MIT https://opensource.org/licenses/MIT */
|
||||
body{margin:0;padding:0;background:#edf5fa;font:76%/170% Verdana,sans-serif;color:#494949;}.this .is .a .test{font:1em/100% Verdana,sans-serif;color:#494949;}.this
|
||||
.is
|
||||
.a
|
||||
.test{font:1em/100% Verdana,sans-serif;color:#494949;}some :pseudo .thing{border-radius:3px;}::-moz-selection{background:#000;color:#fff;}::selection{background:#000;color:#fff;}@media print{*{background:#000 !important;color:#fff !important;}@page{margin:0.5cm;}}@media screen and (max-device-width:480px){background:#000;color:#fff;}textarea,select{font:1em/160% Verdana,sans-serif;color:#494949;}
|
Loading…
Reference in New Issue