@bhsd/codemirror-css-color-picker 6.3.0 → 6.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +13 -4
- package/dist/index.d.ts +6 -3
- package/dist/index.js +12 -5
- package/package.json +6 -14
- package/.replit +0 -9
- package/dev/index.html +0 -13
- package/dev/index.ts +0 -128
- package/dev/vite.config.js +0 -9
- package/pull_request_template.md +0 -23
- package/src/index.ts +0 -576
- package/src/named-colors.ts +0 -152
package/dist/index.cjs
CHANGED
|
@@ -524,7 +524,7 @@ class ColorPickerWidget extends view.WidgetType {
|
|
|
524
524
|
const colorPickerTheme = view.EditorView.baseTheme({
|
|
525
525
|
[`.${wrapperClassName}`]: {
|
|
526
526
|
display: 'inline-block',
|
|
527
|
-
|
|
527
|
+
marginLeft: '0.6ch',
|
|
528
528
|
marginRight: '0.6ch',
|
|
529
529
|
height: '1em',
|
|
530
530
|
width: '1em',
|
|
@@ -536,6 +536,7 @@ const colorPickerTheme = view.EditorView.baseTheme({
|
|
|
536
536
|
width: '100%',
|
|
537
537
|
padding: 0,
|
|
538
538
|
border: 'none',
|
|
539
|
+
outline: '1px solid #eee',
|
|
539
540
|
'&::-webkit-color-swatch-wrapper': {
|
|
540
541
|
padding: 0,
|
|
541
542
|
},
|
|
@@ -571,9 +572,9 @@ const makeColorPicker = (options) => view.ViewPlugin.fromClass(class ColorPicker
|
|
|
571
572
|
if (data.colorType === exports.ColorType.rgb) {
|
|
572
573
|
converted = `rgb(${hexToRGBComponents(target.value).join(', ')}${data.alpha})`;
|
|
573
574
|
}
|
|
574
|
-
else if (data.colorType === exports.ColorType.named) {
|
|
575
|
+
else if (data.colorType === exports.ColorType.named && options.namedColors) {
|
|
575
576
|
// If the hex is an exact match for another named color, prefer retaining name
|
|
576
|
-
for (const [key, value] of namedColors.entries()) {
|
|
577
|
+
for (const [key, value] of options.namedColors.entries()) {
|
|
577
578
|
if (value === target.value) {
|
|
578
579
|
converted = key;
|
|
579
580
|
}
|
|
@@ -595,11 +596,19 @@ const makeColorPicker = (options) => view.ViewPlugin.fromClass(class ColorPicker
|
|
|
595
596
|
},
|
|
596
597
|
},
|
|
597
598
|
});
|
|
598
|
-
const colorPicker = [
|
|
599
|
+
const colorPicker = [
|
|
600
|
+
makeColorPicker({
|
|
601
|
+
discoverColors: discoverColorsInCSS,
|
|
602
|
+
namedColors,
|
|
603
|
+
}),
|
|
604
|
+
colorPickerTheme,
|
|
605
|
+
];
|
|
599
606
|
|
|
600
607
|
exports.colorPicker = colorPicker;
|
|
601
608
|
exports.colorPickerTheme = colorPickerTheme;
|
|
609
|
+
exports.discoverColorsInCSS = discoverColorsInCSS;
|
|
602
610
|
exports.makeColorPicker = makeColorPicker;
|
|
611
|
+
exports.namedColors = namedColors;
|
|
603
612
|
exports.parseCallExpression = parseCallExpression;
|
|
604
613
|
exports.parseColorLiteral = parseColorLiteral;
|
|
605
614
|
exports.parseNamedColor = parseNamedColor;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ViewPlugin, DecorationSet, ViewUpdate } from '@codemirror/view';
|
|
2
|
-
import {
|
|
2
|
+
import { Text, Extension } from '@codemirror/state';
|
|
3
3
|
import { Tree } from '@lezer/common';
|
|
4
4
|
|
|
5
|
+
declare const namedColors: Map<string, string>;
|
|
6
|
+
|
|
5
7
|
interface PickerState {
|
|
6
8
|
from: number;
|
|
7
9
|
to: number;
|
|
@@ -26,11 +28,12 @@ declare const wrapperClassName = "cm-css-color-picker-wrapper";
|
|
|
26
28
|
declare const colorPickerTheme: Extension;
|
|
27
29
|
interface IFactoryOptions {
|
|
28
30
|
discoverColors: typeof discoverColorsInCSS;
|
|
31
|
+
namedColors?: Map<string, string>;
|
|
29
32
|
}
|
|
30
33
|
declare const makeColorPicker: (options: IFactoryOptions) => ViewPlugin<{
|
|
31
34
|
decorations: DecorationSet;
|
|
32
35
|
update(update: ViewUpdate): void;
|
|
33
|
-
}>;
|
|
36
|
+
}, undefined>;
|
|
34
37
|
declare const colorPicker: Extension;
|
|
35
38
|
|
|
36
|
-
export { ColorData, ColorType, WidgetOptions, colorPicker, colorPickerTheme, makeColorPicker, parseCallExpression, parseColorLiteral, parseNamedColor, wrapperClassName };
|
|
39
|
+
export { ColorData, ColorType, WidgetOptions, colorPicker, colorPickerTheme, discoverColorsInCSS, makeColorPicker, namedColors, parseCallExpression, parseColorLiteral, parseNamedColor, wrapperClassName };
|
package/dist/index.js
CHANGED
|
@@ -519,7 +519,7 @@ class ColorPickerWidget extends WidgetType {
|
|
|
519
519
|
const colorPickerTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
520
520
|
[`.${wrapperClassName}`]: {
|
|
521
521
|
display: 'inline-block',
|
|
522
|
-
|
|
522
|
+
marginLeft: '0.6ch',
|
|
523
523
|
marginRight: '0.6ch',
|
|
524
524
|
height: '1em',
|
|
525
525
|
width: '1em',
|
|
@@ -531,6 +531,7 @@ const colorPickerTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
|
531
531
|
width: '100%',
|
|
532
532
|
padding: 0,
|
|
533
533
|
border: 'none',
|
|
534
|
+
outline: '1px solid #eee',
|
|
534
535
|
'&::-webkit-color-swatch-wrapper': {
|
|
535
536
|
padding: 0,
|
|
536
537
|
},
|
|
@@ -566,9 +567,9 @@ const makeColorPicker = (options) => ViewPlugin.fromClass(class ColorPickerViewP
|
|
|
566
567
|
if (data.colorType === ColorType.rgb) {
|
|
567
568
|
converted = `rgb(${hexToRGBComponents(target.value).join(', ')}${data.alpha})`;
|
|
568
569
|
}
|
|
569
|
-
else if (data.colorType === ColorType.named) {
|
|
570
|
+
else if (data.colorType === ColorType.named && options.namedColors) {
|
|
570
571
|
// If the hex is an exact match for another named color, prefer retaining name
|
|
571
|
-
for (const [key, value] of namedColors.entries()) {
|
|
572
|
+
for (const [key, value] of options.namedColors.entries()) {
|
|
572
573
|
if (value === target.value) {
|
|
573
574
|
converted = key;
|
|
574
575
|
}
|
|
@@ -590,6 +591,12 @@ const makeColorPicker = (options) => ViewPlugin.fromClass(class ColorPickerViewP
|
|
|
590
591
|
},
|
|
591
592
|
},
|
|
592
593
|
});
|
|
593
|
-
const colorPicker = [
|
|
594
|
+
const colorPicker = [
|
|
595
|
+
/*@__PURE__*/makeColorPicker({
|
|
596
|
+
discoverColors: discoverColorsInCSS,
|
|
597
|
+
namedColors,
|
|
598
|
+
}),
|
|
599
|
+
colorPickerTheme,
|
|
600
|
+
];
|
|
594
601
|
|
|
595
|
-
export { ColorType, colorPicker, colorPickerTheme, makeColorPicker, parseCallExpression, parseColorLiteral, parseNamedColor, wrapperClassName };
|
|
602
|
+
export { ColorType, colorPicker, colorPickerTheme, discoverColorsInCSS, makeColorPicker, namedColors, parseCallExpression, parseColorLiteral, parseNamedColor, wrapperClassName };
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bhsd/codemirror-css-color-picker",
|
|
3
3
|
"description": "Enables a color picker input next to css colors",
|
|
4
|
-
"version": "6.3.
|
|
4
|
+
"version": "6.3.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Faris Masad",
|
|
7
7
|
"email": "faris@repl.it"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"/dist/*"
|
|
12
|
+
],
|
|
10
13
|
"main": "dist/index.cjs",
|
|
11
14
|
"exports": {
|
|
12
15
|
"import": "./dist/index.js",
|
|
@@ -17,9 +20,7 @@
|
|
|
17
20
|
"sideEffects": false,
|
|
18
21
|
"license": "MIT",
|
|
19
22
|
"scripts": {
|
|
20
|
-
"
|
|
21
|
-
"build": "cm-buildhelper src/index.ts",
|
|
22
|
-
"test": "cm-runtests"
|
|
23
|
+
"build": "cm-buildhelper src/index.ts"
|
|
23
24
|
},
|
|
24
25
|
"peerDependencies": {
|
|
25
26
|
"@codemirror/language": "^6.0.0",
|
|
@@ -28,21 +29,12 @@
|
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@codemirror/buildhelper": "^0.1.16",
|
|
31
|
-
"@codemirror/lang-css": "^6.0.0",
|
|
32
|
-
"@codemirror/lang-html": "^6.4.6",
|
|
33
32
|
"@codemirror/language": "^6.0.0",
|
|
34
33
|
"@codemirror/state": "^6.0.0",
|
|
35
|
-
"@codemirror/view": "^6.0.0"
|
|
36
|
-
"codemirror": "^6.0.0",
|
|
37
|
-
"prettier": "^2.6.0",
|
|
38
|
-
"vite": "^4.4.9"
|
|
34
|
+
"@codemirror/view": "^6.0.0"
|
|
39
35
|
},
|
|
40
36
|
"repository": {
|
|
41
37
|
"type": "git",
|
|
42
38
|
"url": "https://github.com/bhsd-harry/Codemirror-CSS-color-picker"
|
|
43
|
-
},
|
|
44
|
-
"prettier": {
|
|
45
|
-
"singleQuote": true,
|
|
46
|
-
"trailingComma": "all"
|
|
47
39
|
}
|
|
48
40
|
}
|
package/.replit
DELETED
package/dev/index.html
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Vite App</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div id="editor-css"></div>
|
|
10
|
-
<div id="editor-html"></div>
|
|
11
|
-
<script type="module" src="./index.ts"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|
package/dev/index.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { basicSetup } from 'codemirror';
|
|
2
|
-
import { css } from '@codemirror/lang-css';
|
|
3
|
-
import { html } from '@codemirror/lang-html';
|
|
4
|
-
import { EditorState } from '@codemirror/state';
|
|
5
|
-
import { EditorView } from '@codemirror/view';
|
|
6
|
-
import { colorPicker, wrapperClassName } from '../src/';
|
|
7
|
-
|
|
8
|
-
const cssDoc = `
|
|
9
|
-
.wow {
|
|
10
|
-
font-family: Helvetica Neue;
|
|
11
|
-
font-size: 17px;
|
|
12
|
-
color: #ff0000;
|
|
13
|
-
border-color: rgb(0, 255, 0%);
|
|
14
|
-
background-color: #00f;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
#alpha {
|
|
18
|
-
color: #FF00FFAA;
|
|
19
|
-
border-color: rgb(255, 50%, 64, 0.5);
|
|
20
|
-
border-color: rgba(255, 50%, 64, 0.5);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.hex4 {
|
|
24
|
-
color: #ABCD;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.named {
|
|
28
|
-
color: red;
|
|
29
|
-
background-color: blue;
|
|
30
|
-
border-top-color: aquamarine;
|
|
31
|
-
border-left-color: mediumaquamarine;
|
|
32
|
-
border-right-color: lightcoral;
|
|
33
|
-
border-bottom-color: snow;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
#hue {
|
|
37
|
-
color: hsl(0, 100%, 50%);
|
|
38
|
-
}
|
|
39
|
-
`;
|
|
40
|
-
|
|
41
|
-
const htmlDoc = `
|
|
42
|
-
<html>
|
|
43
|
-
<head>
|
|
44
|
-
<style>
|
|
45
|
-
${cssDoc}
|
|
46
|
-
</style>
|
|
47
|
-
</head>
|
|
48
|
-
<body>
|
|
49
|
-
|
|
50
|
-
<body>
|
|
51
|
-
<div
|
|
52
|
-
style="
|
|
53
|
-
font-family: Helvetica Neue;
|
|
54
|
-
font-size: 17px;
|
|
55
|
-
color: #ff0000;
|
|
56
|
-
border-color: rgb(0, 255, 0%);
|
|
57
|
-
background-color: #00f;
|
|
58
|
-
"
|
|
59
|
-
>
|
|
60
|
-
wow
|
|
61
|
-
</div>
|
|
62
|
-
<div
|
|
63
|
-
style="
|
|
64
|
-
color: #ff00ffaa;
|
|
65
|
-
border-color: rgb(255, 50%, 64, 0.5);
|
|
66
|
-
border-color: rgba(255, 50%, 64, 0.5);
|
|
67
|
-
"
|
|
68
|
-
>
|
|
69
|
-
alpha
|
|
70
|
-
</div>
|
|
71
|
-
<div style="color: #abcd">hex4</div>
|
|
72
|
-
<div
|
|
73
|
-
style="
|
|
74
|
-
color: red;
|
|
75
|
-
background-color: blue;
|
|
76
|
-
border-top-color: aquamarine;
|
|
77
|
-
border-left-color: mediumaquamarine;
|
|
78
|
-
border-right-color: lightcoral;
|
|
79
|
-
border-bottom-color: snow;
|
|
80
|
-
"
|
|
81
|
-
>
|
|
82
|
-
named
|
|
83
|
-
</div>
|
|
84
|
-
<div style="color: hsl(0, 100%, 50%)">hue</div>
|
|
85
|
-
</body>
|
|
86
|
-
</html>
|
|
87
|
-
`;
|
|
88
|
-
|
|
89
|
-
const cssParent = document.querySelector('#editor-css');
|
|
90
|
-
const htmlParent = document.querySelector('#editor-html');
|
|
91
|
-
|
|
92
|
-
if (!cssParent || !htmlParent) {
|
|
93
|
-
throw new Error('Could not find #editor-css or #editor-html');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
new EditorView({
|
|
97
|
-
state: EditorState.create({
|
|
98
|
-
doc: cssDoc,
|
|
99
|
-
extensions: [
|
|
100
|
-
colorPicker,
|
|
101
|
-
basicSetup,
|
|
102
|
-
css(),
|
|
103
|
-
EditorView.theme({
|
|
104
|
-
[`.${wrapperClassName}`]: {
|
|
105
|
-
outlineColor: '#000',
|
|
106
|
-
},
|
|
107
|
-
}),
|
|
108
|
-
],
|
|
109
|
-
}),
|
|
110
|
-
parent: cssParent,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
new EditorView({
|
|
114
|
-
state: EditorState.create({
|
|
115
|
-
doc: htmlDoc,
|
|
116
|
-
extensions: [
|
|
117
|
-
colorPicker,
|
|
118
|
-
basicSetup,
|
|
119
|
-
html(),
|
|
120
|
-
EditorView.theme({
|
|
121
|
-
[`.${wrapperClassName}`]: {
|
|
122
|
-
outlineColor: '#000',
|
|
123
|
-
},
|
|
124
|
-
}),
|
|
125
|
-
],
|
|
126
|
-
}),
|
|
127
|
-
parent: cssParent,
|
|
128
|
-
});
|
package/dev/vite.config.js
DELETED
package/pull_request_template.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Why
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
- Describe what prompted you to make the change
|
|
5
|
-
- It should be a good historical record of the motivations and context of the PR
|
|
6
|
-
-->
|
|
7
|
-
|
|
8
|
-
# What changed
|
|
9
|
-
|
|
10
|
-
<!--
|
|
11
|
-
- Describe what changed to a level of detail that someone with little context with your PR could be able to review it.
|
|
12
|
-
- People from the future should also be able to read this and understand what's going on.
|
|
13
|
-
- Annotate changes with a self-review where necessary.
|
|
14
|
-
- Post a screenshot or video when relevant
|
|
15
|
-
-->
|
|
16
|
-
|
|
17
|
-
# Test plan
|
|
18
|
-
|
|
19
|
-
<!--
|
|
20
|
-
- Test plans should allow people without context to run through a list of steps and assert behavior.
|
|
21
|
-
- If this is a bug fix, the test plan should include steps to reproduce the problem.
|
|
22
|
-
- If this is a feature, the test plan should reflect a human-readable end-to-end test.
|
|
23
|
-
-->
|
package/src/index.ts
DELETED
|
@@ -1,576 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EditorView,
|
|
3
|
-
WidgetType,
|
|
4
|
-
ViewUpdate,
|
|
5
|
-
ViewPlugin,
|
|
6
|
-
DecorationSet,
|
|
7
|
-
Decoration,
|
|
8
|
-
} from '@codemirror/view';
|
|
9
|
-
import { Range, Extension, Text } from '@codemirror/state';
|
|
10
|
-
import { NodeProp, Tree } from '@lezer/common';
|
|
11
|
-
import { language, syntaxTree } from '@codemirror/language';
|
|
12
|
-
import { namedColors } from './named-colors';
|
|
13
|
-
|
|
14
|
-
interface PickerState {
|
|
15
|
-
from: number;
|
|
16
|
-
to: number;
|
|
17
|
-
alpha: string;
|
|
18
|
-
colorType: ColorType;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface WidgetOptions extends PickerState {
|
|
22
|
-
color: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type ColorData = Omit<WidgetOptions, 'from' | 'to'>;
|
|
26
|
-
|
|
27
|
-
const pickerState = new WeakMap<HTMLInputElement, PickerState>();
|
|
28
|
-
|
|
29
|
-
export enum ColorType {
|
|
30
|
-
rgb = 'RGB',
|
|
31
|
-
hex = 'HEX',
|
|
32
|
-
named = 'NAMED',
|
|
33
|
-
hsl = 'HSL',
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const rgbCallExpRegex =
|
|
37
|
-
/rgba?\(\s*(\d{1,3}%?)\s*[,\s]\s*(\d{1,3}%?)\s*[,\s]\s*(\d{1,3}%?)\s*([,/]\s*0?\.?\d+%?)?\s*\)/;
|
|
38
|
-
const hslCallExpRegex =
|
|
39
|
-
/hsla?\(\s*(\d{1,3})(?:deg)?\s*[,\s]\s*(\d{1,3})%?\s*[,\s]\s*(\d{1,3})%?\s*([,/]\s*0?\.?\d+%?)?\s*\)/;
|
|
40
|
-
const hexRegex = /(^|\b)(#[0-9a-f]{3,9})(\b|$)/i;
|
|
41
|
-
|
|
42
|
-
function discoverColorsInCSS(
|
|
43
|
-
syntaxTree: Tree,
|
|
44
|
-
from: number,
|
|
45
|
-
to: number,
|
|
46
|
-
typeName: string,
|
|
47
|
-
doc: Text,
|
|
48
|
-
language?: string
|
|
49
|
-
): WidgetOptions | Array<WidgetOptions> | null {
|
|
50
|
-
switch (typeName) {
|
|
51
|
-
case 'AttributeValue': {
|
|
52
|
-
const innerTree = syntaxTree.resolveInner(from, 0).tree;
|
|
53
|
-
|
|
54
|
-
if (!innerTree) {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const overlayTree = innerTree.prop(NodeProp.mounted)?.tree;
|
|
59
|
-
|
|
60
|
-
if (overlayTree?.type.name !== 'Styles') {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const ret: Array<WidgetOptions> = [];
|
|
65
|
-
overlayTree.iterate({
|
|
66
|
-
from: 0,
|
|
67
|
-
to: overlayTree.length,
|
|
68
|
-
enter: ({ type, from: overlayFrom, to: overlayTo }) => {
|
|
69
|
-
const maybeWidgetOptions = discoverColorsInCSS(
|
|
70
|
-
syntaxTree,
|
|
71
|
-
// We add one because the tree doesn't include the
|
|
72
|
-
// quotation mark from the style tag
|
|
73
|
-
from + 1 + overlayFrom,
|
|
74
|
-
from + 1 + overlayTo,
|
|
75
|
-
type.name,
|
|
76
|
-
doc,
|
|
77
|
-
language
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
if (maybeWidgetOptions) {
|
|
81
|
-
if (Array.isArray(maybeWidgetOptions)) {
|
|
82
|
-
throw new Error('Unexpected nested overlays');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
ret.push(maybeWidgetOptions);
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return ret;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
case 'CallExpression': {
|
|
94
|
-
const callExp = doc.sliceString(from, to);
|
|
95
|
-
const result = parseCallExpression(callExp)
|
|
96
|
-
if (!result) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
...result,
|
|
101
|
-
from,
|
|
102
|
-
to
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
case 'ColorLiteral': {
|
|
107
|
-
const result = parseColorLiteral(doc.sliceString(from, to));
|
|
108
|
-
if (!result) {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
...result,
|
|
113
|
-
from,
|
|
114
|
-
to
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
case 'ValueName': {
|
|
119
|
-
const colorName = doc.sliceString(from, to);
|
|
120
|
-
|
|
121
|
-
const result = parseNamedColor(colorName);
|
|
122
|
-
|
|
123
|
-
if (!result) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
...result,
|
|
129
|
-
from,
|
|
130
|
-
to
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
default:
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function parseCallExpression(callExp: string): ColorData | null {
|
|
140
|
-
const fn = callExp.slice(0, 3);
|
|
141
|
-
|
|
142
|
-
switch (fn) {
|
|
143
|
-
case 'rgb': {
|
|
144
|
-
const match = rgbCallExpRegex.exec(callExp);
|
|
145
|
-
|
|
146
|
-
if (!match) {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const [_, r, g, b, a] = match;
|
|
151
|
-
const color = rgbToHex(r, g, b);
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
colorType: ColorType.rgb,
|
|
155
|
-
color,
|
|
156
|
-
alpha: a?.replace(/^\//, ',') || '',
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
case 'hsl': {
|
|
160
|
-
const match = hslCallExpRegex.exec(callExp);
|
|
161
|
-
|
|
162
|
-
if (!match) {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const [_, h, s, l, a] = match;
|
|
167
|
-
const color = hslToHex(h, s, l);
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
colorType: ColorType.hsl,
|
|
171
|
-
color,
|
|
172
|
-
alpha: a?.replace(/^\//, ',') || '',
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
default:
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function parseColorLiteral(colorLiteral: string): ColorData | null {
|
|
181
|
-
const match = hexRegex.exec(colorLiteral);
|
|
182
|
-
if (!match) {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
const [color, alpha] = toFullHex(colorLiteral);
|
|
186
|
-
|
|
187
|
-
return {
|
|
188
|
-
colorType: ColorType.hex,
|
|
189
|
-
color,
|
|
190
|
-
alpha,
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export function parseNamedColor(colorName: string): ColorData | null {
|
|
195
|
-
|
|
196
|
-
const color = namedColors.get(colorName);
|
|
197
|
-
|
|
198
|
-
if (!color) {
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return {
|
|
203
|
-
colorType: ColorType.named,
|
|
204
|
-
color,
|
|
205
|
-
alpha: '',
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function colorPickersDecorations(view: EditorView, discoverColors: typeof discoverColorsInCSS) {
|
|
210
|
-
const widgets: Array<Range<Decoration>> = [];
|
|
211
|
-
|
|
212
|
-
const st = syntaxTree(view.state);
|
|
213
|
-
|
|
214
|
-
for (const range of view.visibleRanges) {
|
|
215
|
-
st.iterate({
|
|
216
|
-
from: range.from,
|
|
217
|
-
to: range.to,
|
|
218
|
-
enter: ({ type, from, to }) => {
|
|
219
|
-
const maybeWidgetOptions = discoverColors(
|
|
220
|
-
st,
|
|
221
|
-
from,
|
|
222
|
-
to,
|
|
223
|
-
type.name,
|
|
224
|
-
view.state.doc,
|
|
225
|
-
view.state.facet(language)?.name
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
if (!maybeWidgetOptions) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (!Array.isArray(maybeWidgetOptions)) {
|
|
233
|
-
widgets.push(
|
|
234
|
-
Decoration.widget({
|
|
235
|
-
widget: new ColorPickerWidget(maybeWidgetOptions),
|
|
236
|
-
side: 1,
|
|
237
|
-
}).range(maybeWidgetOptions.from),
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
for (const wo of maybeWidgetOptions) {
|
|
244
|
-
widgets.push(
|
|
245
|
-
Decoration.widget({
|
|
246
|
-
widget: new ColorPickerWidget(wo),
|
|
247
|
-
side: 1,
|
|
248
|
-
}).range(wo.from),
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return Decoration.set(widgets);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function toFullHex(color: string): string[] {
|
|
259
|
-
if (color.length === 4) {
|
|
260
|
-
// 3-char hex
|
|
261
|
-
return [
|
|
262
|
-
`#${color[1].repeat(2)}${color[2].repeat(2)}${color[3].repeat(2)}`,
|
|
263
|
-
'',
|
|
264
|
-
];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (color.length === 5) {
|
|
268
|
-
// 4-char hex (alpha)
|
|
269
|
-
return [
|
|
270
|
-
`#${color[1].repeat(2)}${color[2].repeat(2)}${color[3].repeat(2)}`,
|
|
271
|
-
color[4].repeat(2),
|
|
272
|
-
];
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (color.length === 9) {
|
|
276
|
-
// 8-char hex (alpha)
|
|
277
|
-
return [`#${color.slice(1, -2)}`, color.slice(-2)];
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return [color, ''];
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function rgbComponentToHex(component: string): string {
|
|
284
|
-
let numericValue: number;
|
|
285
|
-
if (component.endsWith('%')) {
|
|
286
|
-
// 0-100%
|
|
287
|
-
const percent = Number(component.slice(0, -1));
|
|
288
|
-
numericValue = Math.round((percent / 100) * 255.0);
|
|
289
|
-
} else {
|
|
290
|
-
numericValue = Number(component); // assume 0-255
|
|
291
|
-
}
|
|
292
|
-
return decimalToHex(numericValue);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function decimalToHex(decimal: number): string {
|
|
296
|
-
const hex = decimal.toString(16);
|
|
297
|
-
return hex.length === 1 ? '0' + hex : hex;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function hexToRGBComponents(hex: string): number[] {
|
|
301
|
-
const r = hex.slice(1, 3);
|
|
302
|
-
const g = hex.slice(3, 5);
|
|
303
|
-
const b = hex.slice(5, 7);
|
|
304
|
-
return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16)];
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function rgbToHex(r: string, g: string, b: string): string {
|
|
308
|
-
return `#${rgbComponentToHex(r)}${rgbComponentToHex(g)}${rgbComponentToHex(
|
|
309
|
-
b,
|
|
310
|
-
)}`;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function hslToHex(h: string, s: string, l: string): string {
|
|
314
|
-
const sFloat = Number(s) / 100;
|
|
315
|
-
const lFloat = Number(l) / 100;
|
|
316
|
-
const [r, g, b] = hslToRGB(Number(h), sFloat, lFloat);
|
|
317
|
-
return `#${decimalToHex(r)}${decimalToHex(g)}${decimalToHex(b)}`;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function hslToRGB(
|
|
321
|
-
hue: number,
|
|
322
|
-
saturation: number,
|
|
323
|
-
luminance: number,
|
|
324
|
-
): number[] {
|
|
325
|
-
// If there is no Saturation it means that it’s a shade of grey.
|
|
326
|
-
// So in that case we just need to convert the Luminance and set R,G and B to that level.
|
|
327
|
-
if (saturation === 0) {
|
|
328
|
-
const value = Math.round(luminance * 255);
|
|
329
|
-
return [value, value, value];
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
let temp1: number;
|
|
333
|
-
// If Luminance is smaller then 0.5 (50%) then temporary_1 = Luminance x (1.0+Saturation)
|
|
334
|
-
if (luminance < 0.5) {
|
|
335
|
-
temp1 = luminance * (1.0 + saturation);
|
|
336
|
-
} else {
|
|
337
|
-
// If Luminance is equal or larger then 0.5 (50%) then temporary_1 = Luminance + Saturation – Luminance x Saturation
|
|
338
|
-
temp1 = luminance + saturation - luminance * saturation;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// temporary_2 = 2 x Luminance – temporary _1
|
|
342
|
-
const temp2 = 2 * luminance - temp1;
|
|
343
|
-
|
|
344
|
-
// The next step is to convert the 360 degrees in a circle to 1 by dividing the angle by 360.
|
|
345
|
-
hue = hue / 360.0;
|
|
346
|
-
|
|
347
|
-
// And now we need another temporary variable for each color channel, temporary_R, temporary_G and temporary_B.
|
|
348
|
-
// All values need to be between 0 and 1. In our case all the values are between 0 and 1
|
|
349
|
-
const tempR = clamp(hue + 0.333);
|
|
350
|
-
const tempG = hue;
|
|
351
|
-
const tempB = clamp(hue - 0.333);
|
|
352
|
-
|
|
353
|
-
const red = hueToRGB(temp1, temp2, tempR);
|
|
354
|
-
const green = hueToRGB(temp1, temp2, tempG);
|
|
355
|
-
const blue = hueToRGB(temp1, temp2, tempB);
|
|
356
|
-
return [
|
|
357
|
-
Math.round(red * 255),
|
|
358
|
-
Math.round(green * 255),
|
|
359
|
-
Math.round(blue * 255),
|
|
360
|
-
];
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// If you get a negative value you need to add 1 to it.
|
|
364
|
-
// If you get a value above 1 you need to subtract 1 from it.
|
|
365
|
-
function clamp(num: number): number {
|
|
366
|
-
if (num < 0) {
|
|
367
|
-
return num + 1;
|
|
368
|
-
}
|
|
369
|
-
if (num > 1) {
|
|
370
|
-
return num - 1;
|
|
371
|
-
}
|
|
372
|
-
return num;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Now we need to do up to 3 tests to select the correct formula for each color channel. Let’s start with Red.
|
|
377
|
-
*
|
|
378
|
-
* test 1 – If 6 x temporary_R is smaller then 1, Red = temporary_2 + (temporary_1 – temporary_2) x 6 x temporary_R
|
|
379
|
-
* In the case the first test is larger then 1 check the following
|
|
380
|
-
*
|
|
381
|
-
* test 2 – If 2 x temporary_R is smaller then 1, Red = temporary_1
|
|
382
|
-
* In the case the second test also is larger then 1 do the following
|
|
383
|
-
*
|
|
384
|
-
* test 3 – If 3 x temporary_R is smaller then 2, Red = temporary_2 + (temporary_1 – temporary_2) x (0.666 – temporary_R) x 6
|
|
385
|
-
* In the case the third test also is larger then 2 you do the following
|
|
386
|
-
*
|
|
387
|
-
* Red = temporary_2
|
|
388
|
-
*/
|
|
389
|
-
function hueToRGB(temp1: number, temp2: number, tempHue: number): number {
|
|
390
|
-
if (6 * tempHue < 1) {
|
|
391
|
-
return temp2 + (temp1 - temp2) * 6 * tempHue;
|
|
392
|
-
}
|
|
393
|
-
if (2 * tempHue < 1) {
|
|
394
|
-
return temp1;
|
|
395
|
-
}
|
|
396
|
-
if (3 * tempHue < 2) {
|
|
397
|
-
return temp2 + (temp1 - temp2) * (0.666 - tempHue) * 6;
|
|
398
|
-
}
|
|
399
|
-
return temp2;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
|
|
403
|
-
function rgbToHSL(r: number, g: number, b: number): number[] {
|
|
404
|
-
const redPercent = r / 255;
|
|
405
|
-
const greenPercent = g / 255;
|
|
406
|
-
const bluePercent = b / 255;
|
|
407
|
-
const min = Math.min(redPercent, greenPercent, bluePercent);
|
|
408
|
-
const max = Math.max(redPercent, greenPercent, bluePercent);
|
|
409
|
-
const luminance = (max + min) / 2;
|
|
410
|
-
// If the min and max value are the same, it means that there is no saturation. ...
|
|
411
|
-
// If there is no Saturation, we don’t need to calculate the Hue. So we set it to 0 degrees.
|
|
412
|
-
if (max === min) {
|
|
413
|
-
return [0, 0, luminance];
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
let saturation: number;
|
|
417
|
-
// If Luminance is less or equal to 0.5, then Saturation = (max-min)/(max+min)
|
|
418
|
-
if (luminance <= 0.5) {
|
|
419
|
-
saturation = (max - min) / (max + min);
|
|
420
|
-
} else {
|
|
421
|
-
// If Luminance is bigger then 0.5. then Saturation = ( max-min)/(2.0-max-min)
|
|
422
|
-
saturation = (max - min) / (2.0 - max - min);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
let hue: number;
|
|
426
|
-
// If Red is max, then Hue = (G-B)/(max-min)
|
|
427
|
-
if (max === redPercent) {
|
|
428
|
-
hue = (greenPercent - bluePercent) / (max - min);
|
|
429
|
-
} else if (greenPercent === max) {
|
|
430
|
-
// If Green is max, then Hue = 2.0 + (B-R)/(max-min)
|
|
431
|
-
hue = 2.0 + (bluePercent - redPercent) / (max - min);
|
|
432
|
-
} else {
|
|
433
|
-
// If Blue is max, then Hue = 4.0 + (R-G)/(max-min)
|
|
434
|
-
hue = 4.0 + (redPercent - greenPercent) / (max - min);
|
|
435
|
-
}
|
|
436
|
-
hue = Math.round(hue * 60); // convert to degrees
|
|
437
|
-
// make hue positive angle/degrees
|
|
438
|
-
while (hue < 0) {
|
|
439
|
-
hue += 360;
|
|
440
|
-
}
|
|
441
|
-
return [hue, saturation, luminance];
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
export const wrapperClassName = 'cm-css-color-picker-wrapper';
|
|
445
|
-
|
|
446
|
-
class ColorPickerWidget extends WidgetType {
|
|
447
|
-
private readonly state: PickerState;
|
|
448
|
-
private readonly color: string;
|
|
449
|
-
|
|
450
|
-
constructor({ color, ...state }: WidgetOptions) {
|
|
451
|
-
super();
|
|
452
|
-
this.state = state;
|
|
453
|
-
this.color = color;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
eq(other: ColorPickerWidget) {
|
|
457
|
-
return (
|
|
458
|
-
other.state.colorType === this.state.colorType &&
|
|
459
|
-
other.color === this.color &&
|
|
460
|
-
other.state.from === this.state.from &&
|
|
461
|
-
other.state.to === this.state.to &&
|
|
462
|
-
other.state.alpha === this.state.alpha
|
|
463
|
-
);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
toDOM() {
|
|
467
|
-
const picker = document.createElement('input');
|
|
468
|
-
pickerState.set(picker, this.state);
|
|
469
|
-
picker.type = 'color';
|
|
470
|
-
picker.value = this.color;
|
|
471
|
-
|
|
472
|
-
const wrapper = document.createElement('span');
|
|
473
|
-
wrapper.appendChild(picker);
|
|
474
|
-
wrapper.className = wrapperClassName;
|
|
475
|
-
|
|
476
|
-
return wrapper;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
ignoreEvent() {
|
|
480
|
-
return false;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
export const colorPickerTheme = EditorView.baseTheme({
|
|
485
|
-
[`.${wrapperClassName}`]: {
|
|
486
|
-
display: 'inline-block',
|
|
487
|
-
outline: '1px solid #eee',
|
|
488
|
-
marginRight: '0.6ch',
|
|
489
|
-
height: '1em',
|
|
490
|
-
width: '1em',
|
|
491
|
-
transform: 'translateY(1px)',
|
|
492
|
-
},
|
|
493
|
-
[`.${wrapperClassName} input[type="color"]`]: {
|
|
494
|
-
cursor: 'pointer',
|
|
495
|
-
height: '100%',
|
|
496
|
-
width: '100%',
|
|
497
|
-
padding: 0,
|
|
498
|
-
border: 'none',
|
|
499
|
-
'&::-webkit-color-swatch-wrapper': {
|
|
500
|
-
padding: 0,
|
|
501
|
-
},
|
|
502
|
-
'&::-webkit-color-swatch': {
|
|
503
|
-
border: 'none',
|
|
504
|
-
},
|
|
505
|
-
'&::-moz-color-swatch': {
|
|
506
|
-
border: 'none',
|
|
507
|
-
},
|
|
508
|
-
},
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
interface IFactoryOptions {
|
|
512
|
-
discoverColors: typeof discoverColorsInCSS;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
export const makeColorPicker = (options: IFactoryOptions) => ViewPlugin.fromClass(
|
|
516
|
-
class ColorPickerViewPlugin {
|
|
517
|
-
decorations: DecorationSet;
|
|
518
|
-
|
|
519
|
-
constructor(view: EditorView) {
|
|
520
|
-
this.decorations = colorPickersDecorations(view, options.discoverColors);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
update(update: ViewUpdate) {
|
|
524
|
-
if (update.docChanged || update.viewportChanged) {
|
|
525
|
-
this.decorations = colorPickersDecorations(update.view, options.discoverColors);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
decorations: (v) => v.decorations,
|
|
531
|
-
eventHandlers: {
|
|
532
|
-
change: (e, view) => {
|
|
533
|
-
const target = e.target as HTMLInputElement;
|
|
534
|
-
if (
|
|
535
|
-
target.nodeName !== 'INPUT' ||
|
|
536
|
-
!target.parentElement ||
|
|
537
|
-
!target.parentElement.classList.contains(wrapperClassName)
|
|
538
|
-
) {
|
|
539
|
-
return false;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const data = pickerState.get(target)!;
|
|
543
|
-
|
|
544
|
-
let converted = target.value + data.alpha;
|
|
545
|
-
if (data.colorType === ColorType.rgb) {
|
|
546
|
-
converted = `rgb(${hexToRGBComponents(target.value).join(', ')}${
|
|
547
|
-
data.alpha
|
|
548
|
-
})`;
|
|
549
|
-
} else if (data.colorType === ColorType.named) {
|
|
550
|
-
// If the hex is an exact match for another named color, prefer retaining name
|
|
551
|
-
for (const [key, value] of namedColors.entries()) {
|
|
552
|
-
if (value === target.value) {converted = key;}
|
|
553
|
-
}
|
|
554
|
-
} else if (data.colorType === ColorType.hsl) {
|
|
555
|
-
const [r, g, b] = hexToRGBComponents(target.value);
|
|
556
|
-
const [h, s, l] = rgbToHSL(r, g, b);
|
|
557
|
-
converted = `hsl(${h}, ${Math.round(s * 100)}%, ${Math.round(
|
|
558
|
-
l * 100,
|
|
559
|
-
)}%${data.alpha})`;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
view.dispatch({
|
|
563
|
-
changes: {
|
|
564
|
-
from: data.from,
|
|
565
|
-
to: data.to,
|
|
566
|
-
insert: converted,
|
|
567
|
-
},
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
return true;
|
|
571
|
-
},
|
|
572
|
-
},
|
|
573
|
-
},
|
|
574
|
-
);
|
|
575
|
-
|
|
576
|
-
export const colorPicker: Extension = [makeColorPicker({discoverColors: discoverColorsInCSS}), colorPickerTheme];
|
package/src/named-colors.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
const namedColors = new Map<string, string>([
|
|
2
|
-
['aliceblue', '#f0f8ff'],
|
|
3
|
-
['antiquewhite', '#faebd7'],
|
|
4
|
-
['aqua', '#00ffff'],
|
|
5
|
-
['aquamarine', '#7fffd4'],
|
|
6
|
-
['azure', '#f0ffff'],
|
|
7
|
-
['beige', '#f5f5dc'],
|
|
8
|
-
['bisque', '#ffe4c4'],
|
|
9
|
-
['black', '#000000'],
|
|
10
|
-
['blanchedalmond', '#ffebcd'],
|
|
11
|
-
['blue', '#0000ff'],
|
|
12
|
-
['blueviolet', '#8a2be2'],
|
|
13
|
-
['brown', '#a52a2a'],
|
|
14
|
-
['burlywood', '#deb887'],
|
|
15
|
-
['cadetblue', '#5f9ea0'],
|
|
16
|
-
['chartreuse', '#7fff00'],
|
|
17
|
-
['chocolate', '#d2691e'],
|
|
18
|
-
['coral', '#ff7f50'],
|
|
19
|
-
['cornflowerblue', '#6495ed'],
|
|
20
|
-
['cornsilk', '#fff8dc'],
|
|
21
|
-
['crimson', '#dc143c'],
|
|
22
|
-
['cyan', '#00ffff'],
|
|
23
|
-
['darkblue', '#00008b'],
|
|
24
|
-
['darkcyan', '#008b8b'],
|
|
25
|
-
['darkgoldenrod', '#b8860b'],
|
|
26
|
-
['darkgray', '#a9a9a9'],
|
|
27
|
-
['darkgreen', '#006400'],
|
|
28
|
-
['darkgrey', '#a9a9a9'],
|
|
29
|
-
['darkkhaki', '#bdb76b'],
|
|
30
|
-
['darkmagenta', '#8b008b'],
|
|
31
|
-
['darkolivegreen', '#556b2f'],
|
|
32
|
-
['darkorange', '#ff8c00'],
|
|
33
|
-
['darkorchid', '#9932cc'],
|
|
34
|
-
['darkred', '#8b0000'],
|
|
35
|
-
['darksalmon', '#e9967a'],
|
|
36
|
-
['darkseagreen', '#8fbc8f'],
|
|
37
|
-
['darkslateblue', '#483d8b'],
|
|
38
|
-
['darkslategray', '#2f4f4f'],
|
|
39
|
-
['darkslategrey', '#2f4f4f'],
|
|
40
|
-
['darkturquoise', '#00ced1'],
|
|
41
|
-
['darkviolet', '#9400d3'],
|
|
42
|
-
['deeppink', '#ff1493'],
|
|
43
|
-
['deepskyblue', '#00bfff'],
|
|
44
|
-
['dimgray', '#696969'],
|
|
45
|
-
['dimgrey', '#696969'],
|
|
46
|
-
['dodgerblue', '#1e90ff'],
|
|
47
|
-
['firebrick', '#b22222'],
|
|
48
|
-
['floralwhite', '#fffaf0'],
|
|
49
|
-
['forestgreen', '#228b22'],
|
|
50
|
-
['fuchsia', '#ff00ff'],
|
|
51
|
-
['gainsboro', '#dcdcdc'],
|
|
52
|
-
['ghostwhite', '#f8f8ff'],
|
|
53
|
-
['goldenrod', '#daa520'],
|
|
54
|
-
['gold', '#ffd700'],
|
|
55
|
-
['gray', '#808080'],
|
|
56
|
-
['green', '#008000'],
|
|
57
|
-
['greenyellow', '#adff2f'],
|
|
58
|
-
['grey', '#808080'],
|
|
59
|
-
['honeydew', '#f0fff0'],
|
|
60
|
-
['hotpink', '#ff69b4'],
|
|
61
|
-
['indianred', '#cd5c5c'],
|
|
62
|
-
['indigo', '#4b0082'],
|
|
63
|
-
['ivory', '#fffff0'],
|
|
64
|
-
['khaki', '#f0e68c'],
|
|
65
|
-
['lavenderblush', '#fff0f5'],
|
|
66
|
-
['lavender', '#e6e6fa'],
|
|
67
|
-
['lawngreen', '#7cfc00'],
|
|
68
|
-
['lemonchiffon', '#fffacd'],
|
|
69
|
-
['lightblue', '#add8e6'],
|
|
70
|
-
['lightcoral', '#f08080'],
|
|
71
|
-
['lightcyan', '#e0ffff'],
|
|
72
|
-
['lightgoldenrodyellow', '#fafad2'],
|
|
73
|
-
['lightgray', '#d3d3d3'],
|
|
74
|
-
['lightgreen', '#90ee90'],
|
|
75
|
-
['lightgrey', '#d3d3d3'],
|
|
76
|
-
['lightpink', '#ffb6c1'],
|
|
77
|
-
['lightsalmon', '#ffa07a'],
|
|
78
|
-
['lightseagreen', '#20b2aa'],
|
|
79
|
-
['lightskyblue', '#87cefa'],
|
|
80
|
-
['lightslategray', '#778899'],
|
|
81
|
-
['lightslategrey', '#778899'],
|
|
82
|
-
['lightsteelblue', '#b0c4de'],
|
|
83
|
-
['lightyellow', '#ffffe0'],
|
|
84
|
-
['lime', '#00ff00'],
|
|
85
|
-
['limegreen', '#32cd32'],
|
|
86
|
-
['linen', '#faf0e6'],
|
|
87
|
-
['magenta', '#ff00ff'],
|
|
88
|
-
['maroon', '#800000'],
|
|
89
|
-
['mediumaquamarine', '#66cdaa'],
|
|
90
|
-
['mediumblue', '#0000cd'],
|
|
91
|
-
['mediumorchid', '#ba55d3'],
|
|
92
|
-
['mediumpurple', '#9370db'],
|
|
93
|
-
['mediumseagreen', '#3cb371'],
|
|
94
|
-
['mediumslateblue', '#7b68ee'],
|
|
95
|
-
['mediumspringgreen', '#00fa9a'],
|
|
96
|
-
['mediumturquoise', '#48d1cc'],
|
|
97
|
-
['mediumvioletred', '#c71585'],
|
|
98
|
-
['midnightblue', '#191970'],
|
|
99
|
-
['mintcream', '#f5fffa'],
|
|
100
|
-
['mistyrose', '#ffe4e1'],
|
|
101
|
-
['moccasin', '#ffe4b5'],
|
|
102
|
-
['navajowhite', '#ffdead'],
|
|
103
|
-
['navy', '#000080'],
|
|
104
|
-
['oldlace', '#fdf5e6'],
|
|
105
|
-
['olive', '#808000'],
|
|
106
|
-
['olivedrab', '#6b8e23'],
|
|
107
|
-
['orange', '#ffa500'],
|
|
108
|
-
['orangered', '#ff4500'],
|
|
109
|
-
['orchid', '#da70d6'],
|
|
110
|
-
['palegoldenrod', '#eee8aa'],
|
|
111
|
-
['palegreen', '#98fb98'],
|
|
112
|
-
['paleturquoise', '#afeeee'],
|
|
113
|
-
['palevioletred', '#db7093'],
|
|
114
|
-
['papayawhip', '#ffefd5'],
|
|
115
|
-
['peachpuff', '#ffdab9'],
|
|
116
|
-
['peru', '#cd853f'],
|
|
117
|
-
['pink', '#ffc0cb'],
|
|
118
|
-
['plum', '#dda0dd'],
|
|
119
|
-
['powderblue', '#b0e0e6'],
|
|
120
|
-
['purple', '#800080'],
|
|
121
|
-
['rebeccapurple', '#663399'],
|
|
122
|
-
['red', '#ff0000'],
|
|
123
|
-
['rosybrown', '#bc8f8f'],
|
|
124
|
-
['royalblue', '#4169e1'],
|
|
125
|
-
['saddlebrown', '#8b4513'],
|
|
126
|
-
['salmon', '#fa8072'],
|
|
127
|
-
['sandybrown', '#f4a460'],
|
|
128
|
-
['seagreen', '#2e8b57'],
|
|
129
|
-
['seashell', '#fff5ee'],
|
|
130
|
-
['sienna', '#a0522d'],
|
|
131
|
-
['silver', '#c0c0c0'],
|
|
132
|
-
['skyblue', '#87ceeb'],
|
|
133
|
-
['slateblue', '#6a5acd'],
|
|
134
|
-
['slategray', '#708090'],
|
|
135
|
-
['slategrey', '#708090'],
|
|
136
|
-
['snow', '#fffafa'],
|
|
137
|
-
['springgreen', '#00ff7f'],
|
|
138
|
-
['steelblue', '#4682b4'],
|
|
139
|
-
['tan', '#d2b48c'],
|
|
140
|
-
['teal', '#008080'],
|
|
141
|
-
['thistle', '#d8bfd8'],
|
|
142
|
-
['tomato', '#ff6347'],
|
|
143
|
-
['turquoise', '#40e0d0'],
|
|
144
|
-
['violet', '#ee82ee'],
|
|
145
|
-
['wheat', '#f5deb3'],
|
|
146
|
-
['white', '#ffffff'],
|
|
147
|
-
['whitesmoke', '#f5f5f5'],
|
|
148
|
-
['yellow', '#ffff00'],
|
|
149
|
-
['yellowgreen', '#9acd32'],
|
|
150
|
-
]);
|
|
151
|
-
|
|
152
|
-
export { namedColors };
|