mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
esm - removal of CSS loader (#230206)
This commit is contained in:
+1
-2
@@ -756,7 +756,6 @@
|
|||||||
// imports that are allowed in all /test/ files
|
// imports that are allowed in all /test/ files
|
||||||
"when": "test",
|
"when": "test",
|
||||||
"allow": [
|
"allow": [
|
||||||
"vs/css.build.js",
|
|
||||||
"assert",
|
"assert",
|
||||||
"sinon",
|
"sinon",
|
||||||
"sinon-test"
|
"sinon-test"
|
||||||
@@ -1133,7 +1132,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"target": "src/vs/{loader.d.ts,css.ts,css.build.ts,monaco.d.ts,nls.ts,nls.messages.ts}",
|
"target": "src/vs/{loader.d.ts,monaco.d.ts,nls.ts,nls.messages.ts}",
|
||||||
"restrictions": []
|
"restrictions": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+9
-8
@@ -9,16 +9,9 @@
|
|||||||
* @returns {import('./lib/bundle').IEntryPoint}
|
* @returns {import('./lib/bundle').IEntryPoint}
|
||||||
*/
|
*/
|
||||||
function createModuleDescription(name, exclude) {
|
function createModuleDescription(name, exclude) {
|
||||||
|
|
||||||
let excludes = ['vs/css'];
|
|
||||||
if (Array.isArray(exclude) && exclude.length > 0) {
|
|
||||||
excludes = excludes.concat(exclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
include: [],
|
exclude
|
||||||
exclude: excludes
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,4 +58,12 @@ exports.code = [
|
|||||||
|
|
||||||
exports.codeWeb = createModuleDescription('vs/code/browser/workbench/workbench');
|
exports.codeWeb = createModuleDescription('vs/code/browser/workbench/workbench');
|
||||||
|
|
||||||
|
exports.codeServer = [
|
||||||
|
// 'vs/server/node/server.main' is not included here because it gets inlined via ./src/server-main.js
|
||||||
|
// 'vs/server/node/server.cli' is not included here because it gets inlined via ./src/server-cli.js
|
||||||
|
createModuleDescription('vs/workbench/api/node/extensionHostProcess'),
|
||||||
|
createModuleDescription('vs/platform/files/node/watcher/watcherMain'),
|
||||||
|
createModuleDescription('vs/platform/terminal/node/ptyHostMain')
|
||||||
|
];
|
||||||
|
|
||||||
exports.entrypoint = createModuleDescription;
|
exports.entrypoint = createModuleDescription;
|
||||||
|
|||||||
+1
-17
@@ -103,23 +103,7 @@ const serverWithWebResources = [
|
|||||||
...serverWithWebResourceIncludes,
|
...serverWithWebResourceIncludes,
|
||||||
...serverWithWebResourceExcludes
|
...serverWithWebResourceExcludes
|
||||||
];
|
];
|
||||||
|
const serverEntryPoints = buildfile.codeServer;
|
||||||
const serverEntryPoints = [
|
|
||||||
// 'vs/server/node/server.main' is not included here because it gets inlined via ./src/server-main.js
|
|
||||||
// 'vs/server/node/server.cli' is not included here because it gets inlined via ./src/server-cli.js
|
|
||||||
{
|
|
||||||
name: 'vs/workbench/api/node/extensionHostProcess',
|
|
||||||
exclude: ['vs/css']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'vs/platform/files/node/watcher/watcherMain',
|
|
||||||
exclude: ['vs/css']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'vs/platform/terminal/node/ptyHostMain',
|
|
||||||
exclude: ['vs/css']
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const webEntryPoints = [
|
const webEntryPoints = [
|
||||||
buildfile.workerEditor,
|
buildfile.workerEditor,
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ function optimizeESMTask(opts) {
|
|||||||
entryPoint.include?.forEach(allMentionedModules.add, allMentionedModules);
|
entryPoint.include?.forEach(allMentionedModules.add, allMentionedModules);
|
||||||
entryPoint.exclude?.forEach(allMentionedModules.add, allMentionedModules);
|
entryPoint.exclude?.forEach(allMentionedModules.add, allMentionedModules);
|
||||||
}
|
}
|
||||||
allMentionedModules.delete('vs/css'); // TODO@esm remove this when vs/css is removed
|
|
||||||
const bundleAsync = async () => {
|
const bundleAsync = async () => {
|
||||||
const files = [];
|
const files = [];
|
||||||
const tasks = [];
|
const tasks = [];
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ function optimizeESMTask(opts: IOptimizeESMTaskOpts): NodeJS.ReadWriteStream {
|
|||||||
entryPoint.exclude?.forEach(allMentionedModules.add, allMentionedModules);
|
entryPoint.exclude?.forEach(allMentionedModules.add, allMentionedModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
allMentionedModules.delete('vs/css'); // TODO@esm remove this when vs/css is removed
|
|
||||||
|
|
||||||
const bundleAsync = async () => {
|
const bundleAsync = async () => {
|
||||||
|
|
||||||
const files: VinylFile[] = [];
|
const files: VinylFile[] = [];
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ function extractEditor(options) {
|
|||||||
delete tsConfig.compilerOptions.moduleResolution;
|
delete tsConfig.compilerOptions.moduleResolution;
|
||||||
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
||||||
[
|
[
|
||||||
'vs/css.build.ts',
|
|
||||||
'vs/css.ts',
|
|
||||||
'vs/loader.js',
|
'vs/loader.js',
|
||||||
'vs/loader.d.ts'
|
'vs/loader.d.ts'
|
||||||
].forEach(copyFile);
|
].forEach(copyFile);
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
|
|||||||
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
||||||
|
|
||||||
[
|
[
|
||||||
'vs/css.build.ts',
|
|
||||||
'vs/css.ts',
|
|
||||||
'vs/loader.js',
|
'vs/loader.js',
|
||||||
'vs/loader.d.ts'
|
'vs/loader.d.ts'
|
||||||
].forEach(copyFile);
|
].forEach(copyFile);
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ async function main() {
|
|||||||
openSystemBrowser = true;
|
openSystemBrowser = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverArgs.push('--esm'); // TODO@esm this should be the default
|
|
||||||
serverArgs.push('--sourcesPath', APP_ROOT);
|
serverArgs.push('--sourcesPath', APP_ROOT);
|
||||||
|
|
||||||
serverArgs.push(...process.argv.slice(2).filter(v => !v.startsWith('--playground') && v !== '--no-playground'));
|
serverArgs.push(...process.argv.slice(2).filter(v => !v.startsWith('--playground') && v !== '--no-playground'));
|
||||||
|
|||||||
@@ -1,316 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import assert from 'assert';
|
|
||||||
import { ensureNoDisposablesAreLeakedInTestSuite } from '../common/utils.js';
|
|
||||||
import { CSSPluginUtilities, rewriteUrls } from '../../../css.build.js';
|
|
||||||
|
|
||||||
suite('CSSPlugin', () => {
|
|
||||||
|
|
||||||
ensureNoDisposablesAreLeakedInTestSuite();
|
|
||||||
|
|
||||||
test('Utilities.pathOf', () => {
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf(''), '');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('/a'), '/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('a/b/c.css'), 'a/b/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('a'), '');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('a.com/a.css'), 'a.com/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('http://a.com/a.css'), 'http://a.com/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('https://a.com/a.css'), 'https://a.com/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('http://a.com/a/b/c.css'), 'http://a.com/a/b/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('https://a.com/a/b/c.css'), 'https://a.com/a/b/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('/a.css'), '/');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.pathOf('/a/b/c.css'), '/a/b/');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.joinPaths', () => {
|
|
||||||
function mytest(a: string, b: string, expected: string) {
|
|
||||||
assert.strictEqual(CSSPluginUtilities.joinPaths(a, b), expected, '<' + a + '> + <' + b + '> = <' + expected + '>');
|
|
||||||
}
|
|
||||||
mytest('', 'a.css', 'a.css');
|
|
||||||
mytest('', './a.css', 'a.css');
|
|
||||||
mytest('', '././././a.css', 'a.css');
|
|
||||||
mytest('', './../a.css', '../a.css');
|
|
||||||
mytest('', '../../a.css', '../../a.css');
|
|
||||||
mytest('', '../../a/b/c.css', '../../a/b/c.css');
|
|
||||||
mytest('/', 'a.css', '/a.css');
|
|
||||||
mytest('/', './a.css', '/a.css');
|
|
||||||
mytest('/', '././././a.css', '/a.css');
|
|
||||||
mytest('/', './../a.css', '/a.css');
|
|
||||||
mytest('/', '../../a.css', '/a.css');
|
|
||||||
mytest('/', '../../a/b/c.css', '/a/b/c.css');
|
|
||||||
mytest('x/y/z/', 'a.css', 'x/y/z/a.css');
|
|
||||||
mytest('x/y/z/', './a.css', 'x/y/z/a.css');
|
|
||||||
mytest('x/y/z/', '././././a.css', 'x/y/z/a.css');
|
|
||||||
mytest('x/y/z/', './../a.css', 'x/y/a.css');
|
|
||||||
mytest('x/y/z/', '../../a.css', 'x/a.css');
|
|
||||||
mytest('x/y/z/', '../../a/b/c.css', 'x/a/b/c.css');
|
|
||||||
|
|
||||||
mytest('//a.com/', 'a.css', '//a.com/a.css');
|
|
||||||
mytest('//a.com/', './a.css', '//a.com/a.css');
|
|
||||||
mytest('//a.com/', '././././a.css', '//a.com/a.css');
|
|
||||||
mytest('//a.com/', './../a.css', '//a.com/a.css');
|
|
||||||
mytest('//a.com/', '../../a.css', '//a.com/a.css');
|
|
||||||
mytest('//a.com/', '../../a/b/c.css', '//a.com/a/b/c.css');
|
|
||||||
mytest('//a.com/x/y/z/', 'a.css', '//a.com/x/y/z/a.css');
|
|
||||||
mytest('//a.com/x/y/z/', './a.css', '//a.com/x/y/z/a.css');
|
|
||||||
mytest('//a.com/x/y/z/', '././././a.css', '//a.com/x/y/z/a.css');
|
|
||||||
mytest('//a.com/x/y/z/', './../a.css', '//a.com/x/y/a.css');
|
|
||||||
mytest('//a.com/x/y/z/', '../../a.css', '//a.com/x/a.css');
|
|
||||||
mytest('//a.com/x/y/z/', '../../a/b/c.css', '//a.com/x/a/b/c.css');
|
|
||||||
|
|
||||||
mytest('http://a.com/', 'a.css', 'http://a.com/a.css');
|
|
||||||
mytest('http://a.com/', './a.css', 'http://a.com/a.css');
|
|
||||||
mytest('http://a.com/', '././././a.css', 'http://a.com/a.css');
|
|
||||||
mytest('http://a.com/', './../a.css', 'http://a.com/a.css');
|
|
||||||
mytest('http://a.com/', '../../a.css', 'http://a.com/a.css');
|
|
||||||
mytest('http://a.com/', '../../a/b/c.css', 'http://a.com/a/b/c.css');
|
|
||||||
mytest('http://a.com/x/y/z/', 'a.css', 'http://a.com/x/y/z/a.css');
|
|
||||||
mytest('http://a.com/x/y/z/', './a.css', 'http://a.com/x/y/z/a.css');
|
|
||||||
mytest('http://a.com/x/y/z/', '././././a.css', 'http://a.com/x/y/z/a.css');
|
|
||||||
mytest('http://a.com/x/y/z/', './../a.css', 'http://a.com/x/y/a.css');
|
|
||||||
mytest('http://a.com/x/y/z/', '../../a.css', 'http://a.com/x/a.css');
|
|
||||||
mytest('http://a.com/x/y/z/', '../../a/b/c.css', 'http://a.com/x/a/b/c.css');
|
|
||||||
|
|
||||||
mytest('https://a.com/', 'a.css', 'https://a.com/a.css');
|
|
||||||
mytest('https://a.com/', './a.css', 'https://a.com/a.css');
|
|
||||||
mytest('https://a.com/', '././././a.css', 'https://a.com/a.css');
|
|
||||||
mytest('https://a.com/', './../a.css', 'https://a.com/a.css');
|
|
||||||
mytest('https://a.com/', '../../a.css', 'https://a.com/a.css');
|
|
||||||
mytest('https://a.com/', '../../a/b/c.css', 'https://a.com/a/b/c.css');
|
|
||||||
mytest('https://a.com/x/y/z/', 'a.css', 'https://a.com/x/y/z/a.css');
|
|
||||||
mytest('https://a.com/x/y/z/', './a.css', 'https://a.com/x/y/z/a.css');
|
|
||||||
mytest('https://a.com/x/y/z/', '././././a.css', 'https://a.com/x/y/z/a.css');
|
|
||||||
mytest('https://a.com/x/y/z/', './../a.css', 'https://a.com/x/y/a.css');
|
|
||||||
mytest('https://a.com/x/y/z/', '../../a.css', 'https://a.com/x/a.css');
|
|
||||||
mytest('https://a.com/x/y/z/', '../../a/b/c.css', 'https://a.com/x/a/b/c.css');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.commonPrefix', () => {
|
|
||||||
function mytest(a: string, b: string, expected: string) {
|
|
||||||
assert.strictEqual(CSSPluginUtilities.commonPrefix(a, b), expected, 'prefix(<' + a + '>, <' + b + '>) = <' + expected + '>');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.commonPrefix(b, a), expected, 'prefix(<' + b + '>, <' + a + '>) = <' + expected + '>');
|
|
||||||
}
|
|
||||||
mytest('', '', '');
|
|
||||||
mytest('x', '', '');
|
|
||||||
mytest('x', 'x', 'x');
|
|
||||||
mytest('aaaa', 'aaaa', 'aaaa');
|
|
||||||
mytest('aaaaxyz', 'aaaa', 'aaaa');
|
|
||||||
mytest('aaaaxyz', 'aaaatuv', 'aaaa');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.commonFolderPrefix', () => {
|
|
||||||
function mytest(a: string, b: string, expected: string) {
|
|
||||||
assert.strictEqual(CSSPluginUtilities.commonFolderPrefix(a, b), expected, 'folderPrefix(<' + a + '>, <' + b + '>) = <' + expected + '>');
|
|
||||||
assert.strictEqual(CSSPluginUtilities.commonFolderPrefix(b, a), expected, 'folderPrefix(<' + b + '>, <' + a + '>) = <' + expected + '>');
|
|
||||||
}
|
|
||||||
mytest('', '', '');
|
|
||||||
mytest('x', '', '');
|
|
||||||
mytest('x', 'x', '');
|
|
||||||
mytest('aaaa', 'aaaa', '');
|
|
||||||
mytest('aaaaxyz', 'aaaa', '');
|
|
||||||
mytest('aaaaxyz', 'aaaatuv', '');
|
|
||||||
mytest('/', '/', '/');
|
|
||||||
mytest('x/', '', '');
|
|
||||||
mytest('x/', 'x/', 'x/');
|
|
||||||
mytest('aaaa/', 'aaaa/', 'aaaa/');
|
|
||||||
mytest('aaaa/axyz', 'aaaa/a', 'aaaa/');
|
|
||||||
mytest('aaaa/axyz', 'aaaa/atuv', 'aaaa/');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.relativePath', () => {
|
|
||||||
function mytest(a: string, b: string, expected: string) {
|
|
||||||
assert.strictEqual(CSSPluginUtilities.relativePath(a, b), expected, 'relativePath(<' + a + '>, <' + b + '>) = <' + expected + '>');
|
|
||||||
}
|
|
||||||
mytest('', '', '');
|
|
||||||
mytest('x', '', '');
|
|
||||||
mytest('x', 'x', 'x');
|
|
||||||
mytest('aaaa', 'aaaa', 'aaaa');
|
|
||||||
mytest('aaaaxyz', 'aaaa', 'aaaa');
|
|
||||||
mytest('aaaaxyz', 'aaaatuv', 'aaaatuv');
|
|
||||||
|
|
||||||
mytest('x/y/aaaaxyz', 'x/aaaatuv', '../aaaatuv');
|
|
||||||
mytest('x/y/aaaaxyz', 'x/y/aaaatuv', 'aaaatuv');
|
|
||||||
mytest('z/t/aaaaxyz', 'x/y/aaaatuv', '../../x/y/aaaatuv');
|
|
||||||
mytest('aaaaxyz', 'x/y/aaaatuv', 'x/y/aaaatuv');
|
|
||||||
|
|
||||||
mytest('a', '/a', '/a');
|
|
||||||
mytest('/', '/a', '/a');
|
|
||||||
mytest('/a/b/c', '/a/b/c', '/a/b/c');
|
|
||||||
mytest('/a/b', '/a/b/c/d', '/a/b/c/d');
|
|
||||||
|
|
||||||
mytest('a', 'http://a', 'http://a');
|
|
||||||
mytest('/', 'http://a', 'http://a');
|
|
||||||
mytest('/a/b/c', 'http://a/b/c', 'http://a/b/c');
|
|
||||||
mytest('/a/b', 'http://a/b/c/d', 'http://a/b/c/d');
|
|
||||||
|
|
||||||
mytest('a', 'https://a', 'https://a');
|
|
||||||
mytest('/', 'https://a', 'https://a');
|
|
||||||
mytest('/a/b/c', 'https://a/b/c', 'https://a/b/c');
|
|
||||||
mytest('/a/b', 'https://a/b/c/d', 'https://a/b/c/d');
|
|
||||||
|
|
||||||
mytest('x/', '', '../');
|
|
||||||
mytest('x/', '', '../');
|
|
||||||
mytest('x/', 'x/', '');
|
|
||||||
mytest('x/a', 'x/a', 'a');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.rewriteUrls', () => {
|
|
||||||
function mytest(originalFile: string, newFile: string, url: string, expected: string) {
|
|
||||||
assert.strictEqual(rewriteUrls(originalFile, newFile, 'sel { background:url(\'' + url + '\'); }'), 'sel { background:url(' + expected + '); }');
|
|
||||||
assert.strictEqual(rewriteUrls(originalFile, newFile, 'sel { background:url(\"' + url + '\"); }'), 'sel { background:url(' + expected + '); }');
|
|
||||||
assert.strictEqual(rewriteUrls(originalFile, newFile, 'sel { background:url(' + url + '); }'), 'sel { background:url(' + expected + '); }');
|
|
||||||
}
|
|
||||||
|
|
||||||
// img/img.png
|
|
||||||
mytest('a.css', 'b.css', 'img/img.png', 'img/img.png');
|
|
||||||
mytest('a.css', 't/b.css', 'img/img.png', '../img/img.png');
|
|
||||||
mytest('a.css', 'x/y/b.css', 'img/img.png', '../../img/img.png');
|
|
||||||
mytest('x/a.css', 'b.css', 'img/img.png', 'x/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'b.css', 'img/img.png', 'x/y/img/img.png');
|
|
||||||
mytest('x/y/a.css', 't/u/b.css', 'img/img.png', '../../x/y/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/u/b.css', 'img/img.png', '../y/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/y/b.css', 'img/img.png', 'img/img.png');
|
|
||||||
mytest('/a.css', 'b.css', 'img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/b.css', 'img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/y/b.css', 'img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'b.css', 'img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/b.css', 'img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/y/b.css', 'img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'b.css', 'img/img.png', '/x/y/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/b.css', 'img/img.png', '/x/y/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/y/b.css', 'img/img.png', '/x/y/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', 'img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', 'img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', '/b.css', 'img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/a.css', '/x/b.css', 'img/img.png', '/x/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'b.css', 'img/img.png', 'http://www.example.com/x/y/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'http://www.example2.com/b.css', 'img/img.png', 'http://www.example.com/x/y/img/img.png');
|
|
||||||
mytest('https://www.example.com/x/y/a.css', 'b.css', 'img/img.png', 'https://www.example.com/x/y/img/img.png');
|
|
||||||
|
|
||||||
// ../img/img.png
|
|
||||||
mytest('a.css', 'b.css', '../img/img.png', '../img/img.png');
|
|
||||||
mytest('a.css', 't/b.css', '../img/img.png', '../../img/img.png');
|
|
||||||
mytest('a.css', 'x/y/b.css', '../img/img.png', '../../../img/img.png');
|
|
||||||
mytest('x/a.css', 'b.css', '../img/img.png', 'img/img.png');
|
|
||||||
mytest('x/y/a.css', 'b.css', '../img/img.png', 'x/img/img.png');
|
|
||||||
mytest('x/y/a.css', 't/u/b.css', '../img/img.png', '../../x/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/u/b.css', '../img/img.png', '../img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/y/b.css', '../img/img.png', '../img/img.png');
|
|
||||||
mytest('/a.css', 'b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/y/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/y/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'b.css', '../img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/b.css', '../img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/y/b.css', '../img/img.png', '/x/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', '/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', '/x/b.css', '../img/img.png', '/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'b.css', '../img/img.png', 'http://www.example.com/x/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'http://www.example2.com/b.css', '../img/img.png', 'http://www.example.com/x/img/img.png');
|
|
||||||
mytest('https://www.example.com/x/y/a.css', 'b.css', '../img/img.png', 'https://www.example.com/x/img/img.png');
|
|
||||||
|
|
||||||
// /img/img.png
|
|
||||||
mytest('a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('a.css', 't/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('a.css', 'x/y/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('x/a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('x/y/a.css', 't/u/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/u/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/y/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', 'x/y/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/y/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/y/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', '/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('/x/a.css', '/x/b.css', '/img/img.png', '/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'b.css', '/img/img.png', 'http://www.example.com/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'http://www.example.com/x/y/b.css', '/img/img.png', 'http://www.example.com/img/img.png');
|
|
||||||
mytest('https://www.example.com/x/y/a.css', 'b.css', '/img/img.png', 'https://www.example.com/img/img.png');
|
|
||||||
|
|
||||||
// http://example.com/img/img.png
|
|
||||||
mytest('a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('a.css', 't/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('a.css', 'x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('x/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('x/y/a.css', 't/u/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/u/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('x/y/a.css', 'x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/a.css', 'x/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/a.css', 'x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/a.css', 'x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/y/a.css', 'x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/a.css', '/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/a.css', '/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('/x/a.css', '/x/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'http://www.example.com/x/y/b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
mytest('https://www.example.com/x/y/a.css', 'b.css', 'http://example.com/img/img.png', 'http://example.com/img/img.png');
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Utilities.rewriteUrls - quotes and spaces', () => {
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url(\'../img/img.png\'); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url(\t\'../img/img.png\'); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url( \'../img/img.png\'); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url(\'../img/img.png\'\t); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url(\'../img/img.png\' ); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
assert.strictEqual(rewriteUrls('x/y/a.css', 't/u/b.css', 'sel { background:url( \t \'../img/img.png\' \t); }'), 'sel { background:url(../../x/img/img.png); }');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Bug 9601 - css should ignore data urls', () => {
|
|
||||||
const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAACHmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIEltYWdlUmVhZHk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ClC8oVQAAAGnSURBVDiNrZMxTxNxGMZ///9dZWns9a4dTHSABFiuCU5dGt2d9BsQls6GD2LCd2AiQQfixKIJE0ObdKIUSvDa5uLZihP0Sh+HOw3ipOUZ3zzvL2+e932NJBaRe7/Q8Uw5eMRrzXllDU8A5mJkLB+/TflQ+67JXb+5O0FUNS9deLckns/tn2A7hxtDawZvn37Vp78AX8rmxZLDewf89HGJ+fgKCrkrBeuXKPy44hbGN7e8eTbRZwALcFE2nuOy48j6zmaTYP8Qtxaia9A1uLWQYP8QZ7OJI+s7LjsXZeMBIIlLn61xgEbLnqadtiQp7Z0orq8rrq8r7Z1IkqadtkbLnsYBuvTZkpQBhgF7SRVFJRQ3QqW9bgY5P1V6fpoDu4oboaISSqpoGLD3GzAIOEqqaFBBURHF9TWlZxlEktKzruL6mqJi5kmqaBBwJIl7Wf+7LICBIYBSKGyE+LsHuCurzPo9Zv0e7soq/u4BhY0Qpfn68p6HCbHv4Q0qtBPfarLd1LR1nAVWzDNphJq2jjXZbirxrQYV2n0PT9Lih/Rwp/xLCz3T/+gnd2VVRJs/vngAAAAASUVORK5CYII=';
|
|
||||||
|
|
||||||
function mytest(originalFile: string, newFile: string) {
|
|
||||||
assert.strictEqual(rewriteUrls(originalFile, newFile, 'sel { background:url(' + dataUrl + '); }'), 'sel { background:url(' + dataUrl + '); }');
|
|
||||||
assert.strictEqual(rewriteUrls(originalFile, newFile, 'sel { background:url( \t' + dataUrl + '\t ); }'), 'sel { background:url(' + dataUrl + '); }');
|
|
||||||
}
|
|
||||||
|
|
||||||
mytest('a.css', 'b.css');
|
|
||||||
mytest('a.css', 't/b.css');
|
|
||||||
mytest('a.css', 'x/y/b.css');
|
|
||||||
mytest('x/a.css', 'b.css');
|
|
||||||
mytest('x/y/a.css', 'b.css');
|
|
||||||
mytest('x/y/a.css', 't/u/b.css');
|
|
||||||
mytest('x/y/a.css', 'x/u/b.css');
|
|
||||||
mytest('x/y/a.css', 'x/y/b.css');
|
|
||||||
mytest('/a.css', 'b.css');
|
|
||||||
mytest('/a.css', 'x/b.css');
|
|
||||||
mytest('/a.css', 'x/y/b.css');
|
|
||||||
mytest('/x/a.css', 'b.css');
|
|
||||||
mytest('/x/a.css', 'x/b.css');
|
|
||||||
mytest('/x/a.css', 'x/y/b.css');
|
|
||||||
mytest('/x/y/a.css', 'b.css');
|
|
||||||
mytest('/x/y/a.css', 'x/b.css');
|
|
||||||
mytest('/x/y/a.css', 'x/y/b.css');
|
|
||||||
mytest('/a.css', '/b.css');
|
|
||||||
mytest('/a.css', '/b.css');
|
|
||||||
mytest('/x/a.css', '/b.css');
|
|
||||||
mytest('/x/a.css', '/x/b.css');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'b.css');
|
|
||||||
mytest('http://www.example.com/x/y/a.css', 'http://www.example.com/x/y/b.css');
|
|
||||||
mytest('https://www.example.com/x/y/a.css', 'b.css');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
interface ICSSPluginConfig {
|
|
||||||
inlineResources?: boolean | 'base64';
|
|
||||||
inlineResourcesLimit?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICSSEntryPointData {
|
|
||||||
moduleName: string;
|
|
||||||
contents: string;
|
|
||||||
fsPath: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This file gets compiled also with the standalone editor,
|
|
||||||
// so we cannot depend on types from node.d.ts
|
|
||||||
interface INodeFS {
|
|
||||||
readFileSync(path: string, encoding: 'utf8'): string;
|
|
||||||
readFileSync(path: string): INodeBuffer;
|
|
||||||
}
|
|
||||||
interface INodeBuffer {
|
|
||||||
length: number;
|
|
||||||
toString(encoding?: 'base64'): string;
|
|
||||||
}
|
|
||||||
interface INodePath {
|
|
||||||
dirname(p: string): string;
|
|
||||||
join(...paths: string[]): string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodeReq = <T>(module: string): T | undefined => {
|
|
||||||
if (typeof (<any>require).__$__nodeRequire === 'function') {
|
|
||||||
return (<any>require).__$__nodeRequire(module);
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const fs = nodeReq<INodeFS>('fs');
|
|
||||||
const path = nodeReq<INodePath>('path');
|
|
||||||
|
|
||||||
let inlineResources: boolean | 'base64' = false;
|
|
||||||
let inlineResourcesLimit: number = 5000;
|
|
||||||
|
|
||||||
const contentsMap: { [moduleName: string]: string } = {};
|
|
||||||
const pathMap: { [moduleName: string]: string } = {};
|
|
||||||
const entryPoints: { [entryPoint: string]: ICSSEntryPointData[] } = {};
|
|
||||||
const inlinedResources: string[] = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked by the loader at build-time
|
|
||||||
*/
|
|
||||||
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
|
||||||
if (!fs) {
|
|
||||||
throw new Error(`Cannot load files without 'fs'!`);
|
|
||||||
}
|
|
||||||
config = config || {};
|
|
||||||
const myConfig = <ICSSPluginConfig>(config['vs/css'] || {});
|
|
||||||
inlineResources = (typeof myConfig.inlineResources === 'undefined' ? false : myConfig.inlineResources);
|
|
||||||
inlineResourcesLimit = (myConfig.inlineResourcesLimit || 5000);
|
|
||||||
const cssUrl = req.toUrl(name + '.css');
|
|
||||||
let contents = fs.readFileSync(cssUrl, 'utf8');
|
|
||||||
if (contents.charCodeAt(0) === 65279 /* BOM */) {
|
|
||||||
// Remove BOM
|
|
||||||
contents = contents.substring(1);
|
|
||||||
}
|
|
||||||
if (config.isBuild) {
|
|
||||||
contentsMap[name] = contents;
|
|
||||||
pathMap[name] = cssUrl;
|
|
||||||
}
|
|
||||||
load({});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked by the loader at build-time
|
|
||||||
*/
|
|
||||||
export function write(pluginName: string, moduleName: string, write: AMDLoader.IPluginWriteCallback): void {
|
|
||||||
const entryPoint = write.getEntryPoint();
|
|
||||||
|
|
||||||
entryPoints[entryPoint] = entryPoints[entryPoint] || [];
|
|
||||||
entryPoints[entryPoint].push({
|
|
||||||
moduleName: moduleName,
|
|
||||||
contents: contentsMap[moduleName],
|
|
||||||
fsPath: pathMap[moduleName],
|
|
||||||
});
|
|
||||||
|
|
||||||
write.asModule(pluginName + '!' + moduleName,
|
|
||||||
'define([\'vs/css!' + entryPoint + '\'], {});'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked by the loader at build-time
|
|
||||||
*/
|
|
||||||
export function writeFile(pluginName: string, moduleName: string, req: AMDLoader.IRelativeRequire, write: AMDLoader.IPluginWriteFileCallback, config: AMDLoader.IConfigurationOptions): void {
|
|
||||||
if (entryPoints && entryPoints.hasOwnProperty(moduleName)) {
|
|
||||||
const fileName = req.toUrl(moduleName + '.css');
|
|
||||||
const contents = [
|
|
||||||
'/*---------------------------------------------------------',
|
|
||||||
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
|
||||||
' *--------------------------------------------------------*/'
|
|
||||||
],
|
|
||||||
entries = entryPoints[moduleName];
|
|
||||||
for (let i = 0; i < entries.length; i++) {
|
|
||||||
if (inlineResources) {
|
|
||||||
contents.push(rewriteOrInlineUrls(entries[i].fsPath, entries[i].moduleName, moduleName, entries[i].contents, inlineResources === 'base64', inlineResourcesLimit));
|
|
||||||
} else {
|
|
||||||
contents.push(rewriteUrls(entries[i].moduleName, moduleName, entries[i].contents));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write(fileName, contents.join('\r\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getInlinedResources(): string[] {
|
|
||||||
return inlinedResources || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function rewriteOrInlineUrls(originalFileFSPath: string, originalFile: string, newFile: string, contents: string, forceBase64: boolean, inlineByteLimit: number): string {
|
|
||||||
if (!fs || !path) {
|
|
||||||
throw new Error(`Cannot rewrite or inline urls without 'fs' or 'path'!`);
|
|
||||||
}
|
|
||||||
return CSSPluginUtilities.replaceURL(contents, (url) => {
|
|
||||||
if (/\.(svg|png)$/.test(url)) {
|
|
||||||
const fsPath = path.join(path.dirname(originalFileFSPath), url);
|
|
||||||
const fileContents = fs.readFileSync(fsPath);
|
|
||||||
|
|
||||||
if (fileContents.length < inlineByteLimit) {
|
|
||||||
const normalizedFSPath = fsPath.replace(/\\/g, '/');
|
|
||||||
inlinedResources.push(normalizedFSPath);
|
|
||||||
|
|
||||||
const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
|
|
||||||
let DATA = ';base64,' + fileContents.toString('base64');
|
|
||||||
|
|
||||||
if (!forceBase64 && /\.svg$/.test(url)) {
|
|
||||||
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
|
|
||||||
const newText = fileContents.toString()
|
|
||||||
.replace(/"/g, '\'')
|
|
||||||
.replace(/%/g, '%25')
|
|
||||||
.replace(/</g, '%3C')
|
|
||||||
.replace(/>/g, '%3E')
|
|
||||||
.replace(/&/g, '%26')
|
|
||||||
.replace(/#/g, '%23')
|
|
||||||
.replace(/\s+/g, ' ');
|
|
||||||
const encodedData = ',' + newText;
|
|
||||||
if (encodedData.length < DATA.length) {
|
|
||||||
DATA = encodedData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '"data:' + MIME + DATA + '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const absoluteUrl = CSSPluginUtilities.joinPaths(CSSPluginUtilities.pathOf(originalFile), url);
|
|
||||||
return CSSPluginUtilities.relativePath(newFile, absoluteUrl);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function rewriteUrls(originalFile: string, newFile: string, contents: string): string {
|
|
||||||
return CSSPluginUtilities.replaceURL(contents, (url) => {
|
|
||||||
const absoluteUrl = CSSPluginUtilities.joinPaths(CSSPluginUtilities.pathOf(originalFile), url);
|
|
||||||
return CSSPluginUtilities.relativePath(newFile, absoluteUrl);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CSSPluginUtilities {
|
|
||||||
|
|
||||||
public static startsWith(haystack: string, needle: string): boolean {
|
|
||||||
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the path of a file.
|
|
||||||
*/
|
|
||||||
public static pathOf(filename: string): string {
|
|
||||||
const lastSlash = filename.lastIndexOf('/');
|
|
||||||
if (lastSlash !== -1) {
|
|
||||||
return filename.substr(0, lastSlash + 1);
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A conceptual a + b for paths.
|
|
||||||
* Takes into account if `a` contains a protocol.
|
|
||||||
* Also normalizes the result: e.g.: a/b/ + ../c => a/c
|
|
||||||
*/
|
|
||||||
public static joinPaths(a: string, b: string): string {
|
|
||||||
|
|
||||||
function findSlashIndexAfterPrefix(haystack: string, prefix: string): number {
|
|
||||||
if (CSSPluginUtilities.startsWith(haystack, prefix)) {
|
|
||||||
return Math.max(prefix.length, haystack.indexOf('/', prefix.length));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let aPathStartIndex = 0;
|
|
||||||
aPathStartIndex = aPathStartIndex || findSlashIndexAfterPrefix(a, '//');
|
|
||||||
aPathStartIndex = aPathStartIndex || findSlashIndexAfterPrefix(a, 'http://');
|
|
||||||
aPathStartIndex = aPathStartIndex || findSlashIndexAfterPrefix(a, 'https://');
|
|
||||||
|
|
||||||
function pushPiece(pieces: string[], piece: string): void {
|
|
||||||
if (piece === './') {
|
|
||||||
// Ignore
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (piece === '../') {
|
|
||||||
const prevPiece = (pieces.length > 0 ? pieces[pieces.length - 1] : null);
|
|
||||||
if (prevPiece && prevPiece === '/') {
|
|
||||||
// Ignore
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (prevPiece && prevPiece !== '../') {
|
|
||||||
// Pop
|
|
||||||
pieces.pop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Push
|
|
||||||
pieces.push(piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
function push(pieces: string[], path: string): void {
|
|
||||||
while (path.length > 0) {
|
|
||||||
const slashIndex = path.indexOf('/');
|
|
||||||
const piece = (slashIndex >= 0 ? path.substring(0, slashIndex + 1) : path);
|
|
||||||
path = (slashIndex >= 0 ? path.substring(slashIndex + 1) : '');
|
|
||||||
pushPiece(pieces, piece);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let pieces: string[] = [];
|
|
||||||
push(pieces, a.substr(aPathStartIndex));
|
|
||||||
if (b.length > 0 && b.charAt(0) === '/') {
|
|
||||||
pieces = [];
|
|
||||||
}
|
|
||||||
push(pieces, b);
|
|
||||||
|
|
||||||
return a.substring(0, aPathStartIndex) + pieces.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static commonPrefix(str1: string, str2: string): string {
|
|
||||||
const len = Math.min(str1.length, str2.length);
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
if (str1.charCodeAt(i) !== str2.charCodeAt(i)) {
|
|
||||||
return str1.substring(0, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str1.substring(0, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static commonFolderPrefix(fromPath: string, toPath: string): string {
|
|
||||||
const prefix = CSSPluginUtilities.commonPrefix(fromPath, toPath);
|
|
||||||
const slashIndex = prefix.lastIndexOf('/');
|
|
||||||
if (slashIndex === -1) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return prefix.substring(0, slashIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static relativePath(fromPath: string, toPath: string): string {
|
|
||||||
if (CSSPluginUtilities.startsWith(toPath, '/') || CSSPluginUtilities.startsWith(toPath, 'http://') || CSSPluginUtilities.startsWith(toPath, 'https://')) {
|
|
||||||
return toPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore common folder prefix
|
|
||||||
const prefix = CSSPluginUtilities.commonFolderPrefix(fromPath, toPath);
|
|
||||||
fromPath = fromPath.substr(prefix.length);
|
|
||||||
toPath = toPath.substr(prefix.length);
|
|
||||||
|
|
||||||
const upCount = fromPath.split('/').length;
|
|
||||||
let result = '';
|
|
||||||
for (let i = 1; i < upCount; i++) {
|
|
||||||
result += '../';
|
|
||||||
}
|
|
||||||
return result + toPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static replaceURL(contents: string, replacer: (url: string) => string): string {
|
|
||||||
// Use ")" as the terminator as quotes are oftentimes not used at all
|
|
||||||
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_: string, ...matches: string[]) => {
|
|
||||||
let url = matches[0];
|
|
||||||
// Eliminate starting quotes (the initial whitespace is not captured)
|
|
||||||
if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
|
|
||||||
url = url.substring(1);
|
|
||||||
}
|
|
||||||
// The ending whitespace is captured
|
|
||||||
while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) {
|
|
||||||
url = url.substring(0, url.length - 1);
|
|
||||||
}
|
|
||||||
// Eliminate ending quotes
|
|
||||||
if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') {
|
|
||||||
url = url.substring(0, url.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CSSPluginUtilities.startsWith(url, 'data:') && !CSSPluginUtilities.startsWith(url, 'http://') && !CSSPluginUtilities.startsWith(url, 'https://')) {
|
|
||||||
url = replacer(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'url(' + url + ')';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
interface ICSSPluginConfig {
|
|
||||||
disabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked by the loader at run-time
|
|
||||||
*
|
|
||||||
* @skipMangle
|
|
||||||
*/
|
|
||||||
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
|
||||||
config = config || {};
|
|
||||||
const cssConfig = <ICSSPluginConfig>(config['vs/css'] || {});
|
|
||||||
|
|
||||||
if (cssConfig.disabled) {
|
|
||||||
// the plugin is asked to not create any style sheets
|
|
||||||
load({});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cssUrl = req.toUrl(name + '.css');
|
|
||||||
loadCSS(name, cssUrl, () => {
|
|
||||||
load({});
|
|
||||||
}, (err: any) => {
|
|
||||||
if (typeof load.error === 'function') {
|
|
||||||
load.error('Could not find ' + cssUrl + '.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadCSS(name: string, cssUrl: string, callback: () => void, errorback: (err: any) => void): void {
|
|
||||||
if (linkTagExists(name, cssUrl)) {
|
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
createLinkTag(name, cssUrl, callback, errorback);
|
|
||||||
}
|
|
||||||
|
|
||||||
function linkTagExists(name: string, cssUrl: string): boolean {
|
|
||||||
// eslint-disable-next-line no-restricted-globals
|
|
||||||
const links = window.document.getElementsByTagName('link');
|
|
||||||
for (let i = 0, len = links.length; i < len; i++) {
|
|
||||||
const nameAttr = links[i].getAttribute('data-name');
|
|
||||||
const hrefAttr = links[i].getAttribute('href');
|
|
||||||
if (nameAttr === name || hrefAttr === cssUrl) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLinkTag(name: string, cssUrl: string, callback: () => void, errorback: (err: any) => void): void {
|
|
||||||
const linkNode = document.createElement('link');
|
|
||||||
linkNode.setAttribute('rel', 'stylesheet');
|
|
||||||
linkNode.setAttribute('type', 'text/css');
|
|
||||||
linkNode.setAttribute('data-name', name);
|
|
||||||
|
|
||||||
attachListeners(name, linkNode, callback, errorback);
|
|
||||||
linkNode.setAttribute('href', cssUrl);
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-globals
|
|
||||||
const head = window.document.head || window.document.getElementsByTagName('head')[0];
|
|
||||||
head.appendChild(linkNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachListeners(name: string, linkNode: HTMLLinkElement, callback: () => void, errorback: (err: any) => void): void {
|
|
||||||
const unbind = () => {
|
|
||||||
linkNode.removeEventListener('load', loadEventListener);
|
|
||||||
linkNode.removeEventListener('error', errorEventListener);
|
|
||||||
};
|
|
||||||
const loadEventListener = (e: any) => {
|
|
||||||
unbind();
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
const errorEventListener = (e: any) => {
|
|
||||||
unbind();
|
|
||||||
errorback(e);
|
|
||||||
};
|
|
||||||
linkNode.addEventListener('load', loadEventListener);
|
|
||||||
linkNode.addEventListener('error', errorEventListener);
|
|
||||||
}
|
|
||||||
@@ -114,15 +114,6 @@ function main() {
|
|||||||
* @param onError
|
* @param onError
|
||||||
*/
|
*/
|
||||||
const loader = function (modules, onLoad, onError) {
|
const loader = function (modules, onLoad, onError) {
|
||||||
|
|
||||||
modules = modules.filter(mod => {
|
|
||||||
if (mod.endsWith('css.build.test')) {
|
|
||||||
// AMD ONLY, ignore for ESM
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
const loads = modules.map(mod => import(`${baseUrl}/${mod}.js`).catch(err => {
|
const loads = modules.map(mod => import(`${baseUrl}/${mod}.js`).catch(err => {
|
||||||
console.error(`FAILED to load ${mod} as ${baseUrl}/${mod}.js`);
|
console.error(`FAILED to load ${mod} as ${baseUrl}/${mod}.js`);
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
Reference in New Issue
Block a user