Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/browser/cssValue.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import { Color } from '../common/color.js';
6
import { FileAccess } from '../common/network.js';
7
import { URI } from '../common/uri.js';
8
9
export type CssFragment = string & { readonly __cssFragment: unique symbol };
10
11
function asFragment(raw: string): CssFragment {
12
return raw as CssFragment;
13
}
14
15
export function asCssValueWithDefault(cssPropertyValue: string | undefined, dflt: string): string {
16
if (cssPropertyValue !== undefined) {
17
const variableMatch = cssPropertyValue.match(/^\s*var\((.+)\)$/);
18
if (variableMatch) {
19
const varArguments = variableMatch[1].split(',', 2);
20
if (varArguments.length === 2) {
21
dflt = asCssValueWithDefault(varArguments[1].trim(), dflt);
22
}
23
return `var(${varArguments[0]}, ${dflt})`;
24
}
25
return cssPropertyValue;
26
}
27
return dflt;
28
}
29
30
export function sizeValue(value: string): CssFragment {
31
const out = value.replaceAll(/[^\w.%+-]/gi, '');
32
if (out !== value) {
33
console.warn(`CSS size ${value} modified to ${out} to be safe for CSS`);
34
}
35
return asFragment(out);
36
}
37
38
export function hexColorValue(value: string): CssFragment {
39
const out = value.replaceAll(/[^[0-9a-fA-F#]]/gi, '');
40
if (out !== value) {
41
console.warn(`CSS hex color ${value} modified to ${out} to be safe for CSS`);
42
}
43
return asFragment(out);
44
}
45
46
export function identValue(value: string): CssFragment {
47
const out = value.replaceAll(/[^_\-a-z0-9]/gi, '');
48
if (out !== value) {
49
console.warn(`CSS ident value ${value} modified to ${out} to be safe for CSS`);
50
}
51
return asFragment(out);
52
}
53
54
export function stringValue(value: string): CssFragment {
55
return asFragment(`'${value.replaceAll(/'/g, '\\000027')}'`);
56
}
57
58
/**
59
* returns url('...')
60
*/
61
export function asCSSUrl(uri: URI | null | undefined): CssFragment {
62
if (!uri) {
63
return asFragment(`url('')`);
64
}
65
return inline`url('${asFragment(CSS.escape(FileAccess.uriToBrowserUri(uri).toString(true)))}')`;
66
}
67
68
export function className(value: string, escapingExpected = false): CssFragment {
69
const out = CSS.escape(value);
70
if (!escapingExpected && out !== value) {
71
console.warn(`CSS class name ${value} modified to ${out} to be safe for CSS`);
72
}
73
return asFragment(out);
74
}
75
76
type InlineCssTemplateValue = CssFragment | Color;
77
78
/**
79
* Template string tag that that constructs a CSS fragment.
80
*
81
* All expressions in the template must be css safe values.
82
*/
83
export function inline(strings: TemplateStringsArray, ...values: InlineCssTemplateValue[]): CssFragment {
84
return asFragment(strings.reduce((result, str, i) => {
85
const value = values[i] || '';
86
return result + str + value;
87
}, ''));
88
}
89
90
91
export class Builder {
92
private readonly _parts: CssFragment[] = [];
93
94
push(...parts: CssFragment[]): void {
95
this._parts.push(...parts);
96
}
97
98
join(joiner = '\n'): CssFragment {
99
return asFragment(this._parts.join(joiner));
100
}
101
}
102
103