@uiw/codemirror-extensions-color
Version:
Color Extensions for CodeMirror6.
322 lines (321 loc) • 14.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.colorView = exports.colorTheme = exports.color = exports.ColorType = void 0;
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _callSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/callSuper"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
var _view = require("@codemirror/view");
var _language = require("@codemirror/language");
var _colorsNamed = _interopRequireDefault(require("colors-named"));
var _colorsNamedHex = _interopRequireDefault(require("colors-named-hex"));
var _hslMatcher = _interopRequireWildcard(require("hsl-matcher"));
var _utils = require("./utils");
var _excluded = ["color", "colorRaw"];
var ColorType = exports.ColorType = /*#__PURE__*/function (ColorType) {
ColorType["rgb"] = "RGB";
ColorType["hex"] = "HEX";
ColorType["named"] = "NAMED";
ColorType["hsl"] = "HSL";
return ColorType;
}({});
var colorState = new WeakMap();
function colorDecorations(view) {
var widgets = [];
var _iterator = (0, _createForOfIteratorHelper2["default"])(view.visibleRanges),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var range = _step.value;
(0, _language.syntaxTree)(view.state).iterate({
from: range.from,
to: range.to,
enter: function enter(_ref) {
var type = _ref.type,
from = _ref.from,
to = _ref.to;
var callExp = view.state.doc.sliceString(from, to);
/**
* ```
* rgb(0 107 128, .5); ❌ ❌ ❌
* rgb( 0 107 128 ); ✅ ✅ ✅
* RGB( 0 107 128 ); ✅ ✅ ✅
* Rgb( 0 107 128 ); ✅ ✅ ✅
* rgb( 0 107 128 / ); ❌ ❌ ❌
* rgb( 0 107 128 / 60%); ✅ ✅ ✅
* rgb(0,107,128 / 60%); ❌ ❌ ❌
* rgb( 255, 255, 255 ) ✅ ✅ ✅
* rgba( 255, 255, 255 ) ✅ ✅ ✅
* rgba( 255, 255 , 255, ) ❌ ❌ ❌
* rgba( 255, 255 , 255, .5 ) ✅ ✅ ✅
* rgba( 255 255 255 / 0.5 ); ✅ ✅ ✅
* rgba( 255 255 255 0.5 ); ❌ ❌ ❌
* rgba( 255 255 255 / ); ❌ ❌ ❌
* ```
*/
if (type.name === 'CallExpression' && callExp.startsWith('rgb')) {
var match = /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(\d{1,3})\s*(,\s*\d*\.\d*\s*)?\)/i.exec(callExp) || /rgba?\(\s*(\d{1,3})\s*(\d{1,3})\s*(\d{1,3})\s*(\/?\s*\d+%)?(\/\s*\d+\.\d\s*)?\)/i.exec(callExp);
if (!match) return;
var _match = (0, _slicedToArray2["default"])(match, 5),
_ = _match[0],
r = _match[1],
g = _match[2],
b = _match[3],
a = _match[4];
var hex = (0, _utils.rgbToHex)(Number(r), Number(g), Number(b));
var widget = _view.Decoration.widget({
widget: new ColorWidget({
colorType: ColorType.rgb,
color: hex,
colorRaw: callExp,
from: from,
to: to,
alpha: a ? a.replace(/(\/|,)/g, '') : ''
}),
side: 0
});
widgets.push(widget.range(from));
} else if (type.name === 'CallExpression' && (0, _hslMatcher["default"])(callExp)) {
/**
* # valid
* hsl(240, 100%, 50%) // ✅ comma separated
* hsl(240, 100%, 50%, 0.1) // ✅ comma separated with opacity
* hsl(240, 100%, 50%, 10%) // ✅ comma separated with % opacity
* hsl(240,100%,50%,0.1) // ✅ comma separated without spaces
* hsl(180deg, 100%, 50%, 0.1) // ✅ hue with 'deg'
* hsl(3.14rad, 100%, 50%, 0.1) // ✅ hue with 'rad'
* hsl(200grad, 100%, 50%, 0.1) // ✅ hue with 'grad'
* hsl(0.5turn, 100%, 50%, 0.1) // ✅ hue with 'turn'
* hsl(-240, -100%, -50%, -0.1) // ✅ negative values
* hsl(+240, +100%, +50%, +0.1) // ✅ explicit positive sign
* hsl(240.5, 99.99%, 49.999%, 0.9999) // ✅ non-integer values
* hsl(.9, .99%, .999%, .9999) // ✅ fraction w/o leading zero
* hsl(0240, 0100%, 0050%, 01) // ✅ leading zeros
* hsl(240.0, 100.00%, 50.000%, 1.0000) // ✅ trailing decimal zeros
* hsl(2400, 1000%, 1000%, 10) // ✅ out of range values
* hsl(-2400.01deg, -1000.5%, -1000.05%, -100) // ✅ combination of above
* hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3) // ✅ scientific notation
* hsl(240 100% 50%) // ✅ space separated (CSS Color Level 4)
* hsl(240 100% 50% / 0.1) // ✅ space separated with opacity
* hsla(240, 100%, 50%) // ✅ hsla() alias
* hsla(240, 100%, 50%, 0.1) // ✅ hsla() with opacity
* HSL(240Deg, 100%, 50%) // ✅ case insensitive
*/
var _match2 = (0, _hslMatcher.hlsStringToRGB)(callExp);
if (!_match2) return;
var _r = _match2.r,
_g = _match2.g,
_b = _match2.b;
var _hex = (0, _utils.rgbToHex)(Number(_r), Number(_g), Number(_b));
var _widget = _view.Decoration.widget({
widget: new ColorWidget({
colorType: ColorType.hsl,
color: _hex,
colorRaw: callExp,
from: from,
to: to,
alpha: _match2.a ? _match2.a.toString() : ''
}),
side: 0
});
widgets.push(_widget.range(from));
} else if (type.name === 'ColorLiteral') {
var _toFullHex = (0, _utils.toFullHex)(callExp),
_toFullHex2 = (0, _slicedToArray2["default"])(_toFullHex, 2),
_color = _toFullHex2[0],
alpha = _toFullHex2[1];
var _widget2 = _view.Decoration.widget({
widget: new ColorWidget({
colorType: ColorType.hex,
color: _color,
colorRaw: callExp,
from: from,
to: to,
alpha: alpha
}),
side: 0
});
widgets.push(_widget2.range(from));
} else if (type.name === 'ValueName') {
var name = callExp;
if (_colorsNamed["default"].includes(name)) {
var _widget3 = _view.Decoration.widget({
widget: new ColorWidget({
colorType: ColorType.named,
color: _colorsNamedHex["default"][_colorsNamed["default"].indexOf(name)],
colorRaw: callExp,
from: from,
to: to,
alpha: ''
}),
side: 0
});
widgets.push(_widget3.range(from));
}
}
}
});
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return _view.Decoration.set(widgets);
}
var ColorWidget = /*#__PURE__*/function (_WidgetType) {
function ColorWidget(_ref2) {
var _this;
var color = _ref2.color,
colorRaw = _ref2.colorRaw,
state = (0, _objectWithoutProperties2["default"])(_ref2, _excluded);
(0, _classCallCheck2["default"])(this, ColorWidget);
_this = (0, _callSuper2["default"])(this, ColorWidget);
(0, _defineProperty2["default"])(_this, "state", void 0);
(0, _defineProperty2["default"])(_this, "color", void 0);
(0, _defineProperty2["default"])(_this, "colorRaw", void 0);
_this.state = state;
_this.color = color;
_this.colorRaw = colorRaw;
return _this;
}
(0, _inherits2["default"])(ColorWidget, _WidgetType);
return (0, _createClass2["default"])(ColorWidget, [{
key: "eq",
value: function eq(other) {
return other.state.colorType === this.state.colorType && other.color === this.color && other.state.from === this.state.from && other.state.to === this.state.to && other.state.alpha === this.state.alpha;
}
}, {
key: "toDOM",
value: function toDOM() {
var picker = document.createElement('input');
colorState.set(picker, this.state);
picker.type = 'color';
picker.value = this.color;
picker.dataset['color'] = this.color;
picker.dataset['colorraw'] = this.colorRaw;
var wrapper = document.createElement('span');
wrapper.appendChild(picker);
wrapper.dataset['color'] = this.color;
wrapper.style.backgroundColor = this.colorRaw;
return wrapper;
}
}, {
key: "ignoreEvent",
value: function ignoreEvent() {
return false;
}
}]);
}(_view.WidgetType);
var colorView = exports.colorView = function colorView() {
var showPicker = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
return _view.ViewPlugin.fromClass(/*#__PURE__*/function () {
function ColorView(view) {
(0, _classCallCheck2["default"])(this, ColorView);
(0, _defineProperty2["default"])(this, "decorations", void 0);
this.decorations = colorDecorations(view);
}
return (0, _createClass2["default"])(ColorView, [{
key: "update",
value: function update(_update) {
if (_update.docChanged || _update.viewportChanged) {
this.decorations = colorDecorations(_update.view);
}
var readOnly = _update.view.contentDOM.ariaReadOnly === 'true';
var editable = _update.view.contentDOM.contentEditable === 'true';
var canBeEdited = readOnly === false && editable;
this.changePicker(_update.view, canBeEdited);
}
}, {
key: "changePicker",
value: function changePicker(view, canBeEdited) {
var doms = view.contentDOM.querySelectorAll('input[type=color]');
doms.forEach(function (inp) {
if (!showPicker) {
inp.setAttribute('disabled', '');
} else {
canBeEdited ? inp.removeAttribute('disabled') : inp.setAttribute('disabled', '');
}
});
}
}]);
}(), {
decorations: function decorations(v) {
return v.decorations;
},
eventHandlers: {
change: function change(e, view) {
var target = e.target;
if (target.nodeName !== 'INPUT' || !target.parentElement || !target.dataset.color && !target.dataset.colorraw) return false;
var data = colorState.get(target);
var value = target.value;
var rgb = (0, _utils.hexToRgb)(value);
var colorraw = target.dataset.colorraw;
var slash = (target.dataset.colorraw || '').indexOf('/') > 4;
var comma = (target.dataset.colorraw || '').indexOf(',') > 4;
var converted = target.value;
if (data.colorType === ColorType.rgb) {
var funName = colorraw !== null && colorraw !== void 0 && colorraw.match(/^(rgba?)/) ? colorraw === null || colorraw === void 0 ? void 0 : colorraw.match(/^(rgba?)/)[0] : undefined;
if (comma) {
converted = rgb ? "".concat(funName, "(").concat(rgb.r, ", ").concat(rgb.g, ", ").concat(rgb.b).concat(data.alpha ? ', ' + data.alpha.trim() : '', ")") : value;
} else if (slash) {
converted = rgb ? "".concat(funName, "(").concat(rgb.r, " ").concat(rgb.g, " ").concat(rgb.b).concat(data.alpha ? ' / ' + data.alpha.trim() : '', ")") : value;
} else {
converted = rgb ? "".concat(funName, "(").concat(rgb.r, " ").concat(rgb.g, " ").concat(rgb.b, ")") : value;
}
} else if (data.colorType === ColorType.hsl) {
var _rgb = (0, _utils.hexToRgb)(value);
if (_rgb) {
var _RGBToHSL = (0, _utils.RGBToHSL)(_rgb === null || _rgb === void 0 ? void 0 : _rgb.r, _rgb === null || _rgb === void 0 ? void 0 : _rgb.g, _rgb === null || _rgb === void 0 ? void 0 : _rgb.b),
h = _RGBToHSL.h,
s = _RGBToHSL.s,
l = _RGBToHSL.l;
converted = "hsl(".concat(h, "deg ").concat(s, "% ").concat(l, "%").concat(data.alpha ? ' / ' + data.alpha : '', ")");
}
}
view.dispatch({
changes: {
from: data.from,
to: data.to,
insert: converted
}
});
return true;
}
}
});
};
var colorTheme = exports.colorTheme = _view.EditorView.baseTheme({
'span[data-color]': {
width: '12px',
height: '12px',
display: 'inline-block',
borderRadius: '2px',
marginRight: '0.5ch',
outline: '1px solid #00000040',
overflow: 'hidden',
verticalAlign: 'middle',
marginTop: '-2px'
},
'span[data-color] input[type="color"]': {
background: 'transparent',
display: 'block',
border: 'none',
outline: '0',
paddingLeft: '24px',
height: '12px'
},
'span[data-color] input[type="color"]::-webkit-color-swatch': {
border: 'none',
paddingLeft: '24px'
}
});
var color = exports.color = [colorView(), colorTheme];