Skip to content

Commit

Permalink
Added Inline color plugin (#2007)
Browse files Browse the repository at this point in the history
This adds a new plugin to display an inline preview of CSS colors as most IDEs do.
  • Loading branch information
RunDevelopment committed Sep 3, 2019
1 parent 010a015 commit 8403e45
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 82 deletions.
2 changes: 1 addition & 1 deletion components.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@
"require": "ruby",
"peerDependencies": [
"css",
"css-extras",
"coffeescript",
"erb",
"javascript",
Expand Down Expand Up @@ -530,6 +531,7 @@
"less": {
"title": "Less",
"require": "css",
"peerDependencies": "css-extras",
"owner": "Golmote"
},
"lilypond": {
Expand Down Expand Up @@ -845,6 +847,7 @@
"scss": {
"title": "Sass (Scss)",
"require": "css",
"peerDependencies": "css-extras",
"owner": "MoOx"
},
"scala": {
Expand Down Expand Up @@ -1074,8 +1077,14 @@
"owner": "Golmote",
"noCSS": true
},
"inline-color": {
"title": "Inline color",
"require": "css-extras",
"owner": "RunDevelopment"
},
"previewers": {
"title": "Previewers",
"require": "css-extras",
"owner": "Golmote"
},
"autoloader": {
Expand Down
160 changes: 92 additions & 68 deletions components/prism-css-extras.js
Original file line number Diff line number Diff line change
@@ -1,80 +1,104 @@
Prism.languages.css.selector = {
pattern: Prism.languages.css.selector,
inside: {
'pseudo-element': /:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,
'pseudo-class': /:[-\w]+/,
'class': /\.[-:.\w]+/,
'id': /#[-:.\w]+/,
'attribute': {
pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/,
greedy: true,
inside: {
'punctuation': /^\[|\]$/,
'case-sensitivity': {
pattern: /(\s)[si]$/i,
lookbehind: true,
alias: 'keyword'
},
'namespace': {
pattern: /^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,
(function (Prism) {

Prism.languages.css.selector = {
pattern: Prism.languages.css.selector,
inside: {
'pseudo-element': /:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,
'pseudo-class': /:[-\w]+/,
'class': /\.[-:.\w]+/,
'id': /#[-:.\w]+/,
'attribute': {
pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/,
greedy: true,
inside: {
'punctuation': /^\[|\]$/,
'case-sensitivity': {
pattern: /(\s)[si]$/i,
lookbehind: true,
alias: 'keyword'
},
'namespace': {
pattern: /^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,
lookbehind: true,
inside: {
'punctuation': /\|$/
}
},
'attribute': {
pattern: /^(\s*)[-\w\xA0-\uFFFF]+/,
lookbehind: true
},
'value': [
/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
{
pattern: /(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,
lookbehind: true
}
],
'operator': /[|~*^$]?=/
}
},
'n-th': [
{
pattern: /(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,
lookbehind: true,
inside: {
'punctuation': /\|$/
'number': /[\dn]+/,
'operator': /[+-]/
}
},
'attribute': {
pattern: /^(\s*)[-\w\xA0-\uFFFF]+/,
{
pattern: /(\(\s*)(?:even|odd)(?=\s*\))/i,
lookbehind: true
},
'value': [
/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
{
pattern: /(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,
lookbehind: true
}
],
'operator': /[|~*^$]?=/
}
},
'n-th': [
{
pattern: /(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,
lookbehind: true,
inside: {
'number': /[\dn]+/,
'operator': /[+-]/
}
},
{
pattern: /(\(\s*)(?:even|odd)(?=\s*\))/i,
lookbehind: true
}
],
'punctuation': /[()]/
}
};
],
'punctuation': /[()]/
}
};

Prism.languages.insertBefore('css', 'property', {
'variable': {
pattern: /(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,
lookbehind: true
}
});
Prism.languages.insertBefore('css', 'property', {
'variable': {
pattern: /(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,
lookbehind: true
}
});

Prism.languages.insertBefore('css', 'function', {
'operator': {
pattern: /(\s)[+\-*\/](?=\s)/,
lookbehind: true
},
'hexcode': /#[\da-f]{3,8}/i,
'entity': /\\[\da-f]{1,8}/i,
'unit': {
var unit = {
pattern: /(\d)(?:%|[a-z]+)/,
lookbehind: true
},
'number': {
// 123 -123 .123 -.123 12.3 -12.3
};
// 123 -123 .123 -.123 12.3 -12.3
var number = {
pattern: /(^|[^\w.-])-?\d*\.?\d+/,
lookbehind: true
}
});
};

Prism.languages.insertBefore('css', 'function', {
'operator': {
pattern: /(\s)[+\-*\/](?=\s)/,
lookbehind: true
},
// CAREFUL!
// Previewers and Inline color use hexcode and color.
'hexcode': {
pattern: /\B#(?:[\da-f]{1,2}){3,4}\b/i,
alias: 'color'
},
'color': [
/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,
{
pattern: /\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,
inside: {
'unit': unit,
'number': number,
'function': /[\w-]+(?=\()/,
'punctuation': /[(),]/
}
}
],
'entity': /\\[\da-f]{1,8}/i,
'unit': unit,
'number': number
});

})(Prism);
2 changes: 1 addition & 1 deletion components/prism-css-extras.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 79 additions & 0 deletions plugins/inline-color/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="utf-8" />
<link rel="icon" href="favicon.png" />
<title>Inline color ▲ Prism plugins</title>
<base href="../.." />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
<link rel="stylesheet" href="plugins/inline-color/prism-inline-color.css" data-noprefix />
<style>
/* Also works here */
a.not-a-class {
color: red;
}
</style>
<script src="scripts/prefixfree.min.js"></script>
<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
<script src="https://www.google-analytics.com/ga.js" async></script>
</head>
<body>

<span style="display: none; color: blue;"></span>

<header>
<div class="intro" data-src="templates/header-plugins.html" data-type="text/html"></div>

<h2>Inline color</h2>
<p>This plugin adds a small inline preview for colors in style sheets.</p>
</header>

<section>
<h1>Examples</h1>

<h2>CSS</h2>
<pre><code class="language-css">span.foo {
background-color: navy;
color: #BFD;
}

span.bar {
background: rgba(105, 0, 12, .62);
color: hsl(30, 100%, 50%);
}</code></pre>

<pre data-src="themes/prism.css"></pre>

<h2>HTML (Markup)</h2>
<pre><code class="language-markup">&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;head>

&lt;meta charset="utf-8" />
&lt;title>Example&lt;/title>
&lt;style>
/* Also works here */
a.not-a-class {
color: red;
}
&lt;/style>
&lt;body style="color: black">

&lt;/body>
&lt;/html></code></pre>

</section>
<footer data-src="templates/footer.html" data-type="text/html"></footer>

<script src="prism.js"></script>
<script src="components/prism-css-extras.js"></script>
<script src="plugins/inline-color/prism-inline-color.js"></script>
<script src="scripts/utopia.js"></script>
<script src="components.js"></script>
<script src="scripts/code.js"></script>


</body>
</html>
9 changes: 9 additions & 0 deletions plugins/inline-color/prism-inline-color.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
span.inline-color {
display: inline-block;
height: 1.333ch;
width: 1.333ch;
margin: 0 .333ch;
box-sizing: border-box;
border: 1px solid white;
outline: 1px solid black;
}
88 changes: 88 additions & 0 deletions plugins/inline-color/prism-inline-color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
(function () {

if (typeof self === 'undefined' || typeof Prism === 'undefined' || typeof document === 'undefined') {
return;
}

// Copied from the markup language definition
var HTML_TAG = /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g;

// the regex explained: In first lookahead we check whether the string is valid and then we use the
// capturing groups to split the string into its components.
var HEX_COLOR = /^#?(?=(?:[\da-f]{1,2}){3,4}$)([\da-f][\da-f]?)([\da-f][\da-f]?)([\da-f][\da-f]?)([\da-f][\da-f]?)?$/i;

/**
* Parses the given hexadecimal representation and returns the parsed RGBA color.
*
* If the format of the given string is invalid, `undefined` will be returned.
* Valid formats are: `RGB`, `RGBA`, `RRGGBB`, and `RRGGBBAA`.
*
* @param {string} hex
* @returns {string | undefined}
*/
function parseHexColor(hex) {
var match = HEX_COLOR.exec(hex);
if (!match) {
return undefined;
}

// This is used to scale normalize 4bit and 8bit values
var scale = hex.length <= 4 ? 1 / 15 : 1 / 255;

var rgb = match.slice(1, 4).map(function (c) {
return String(Math.round(parseInt(c, 16) * scale * 255));
}).join(',');

var alpha = match[4] === undefined ? '1' : (parseInt(match[4], 16) * scale).toFixed(3);

return 'rgba(' + rgb + ',' + alpha + ')';
}

/**
* Validates the given Color using the current browser's internal implementation.
*
* @param {string} color
* @returns {string | undefined}
*/
function validateColor(color) {
var s = new Option().style;
s.color = color;
return s.color ? color : undefined;
}

/**
* An array of function which parse a given string representation of a color.
*
* These parser serve as validators and as a layer of compatibility to support color formats which the browser
* might not support natively.
*
* @type {((value: string) => (string|undefined))[]}
*/
var parsers = [
parseHexColor,
validateColor
];


Prism.hooks.add('wrap', function (env) {
if (env.type === 'color' || env.type === 'hexcode') {
var content = env.content;

// remove all HTML tags inside
var rawText = content.split(HTML_TAG).join('');

var color;
for (var i = 0, l = parsers.length; i < l && !color; i++) {
color = parsers[i](rawText);
}

if (!color) {
return;
}

var previewElement = '<span class="inline-color" style="background-color:' + color + ';"></span>';
env.content = previewElement + content;
}
});

}());
1 change: 1 addition & 0 deletions plugins/inline-color/prism-inline-color.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8403e45

Please sign in to comment.