Skip to content

Commit

Permalink
Merge pull request #767 from Golmote/css-colors
Browse files Browse the repository at this point in the history
Plugin: color previewer
  • Loading branch information
LeaVerou committed Sep 13, 2015
2 parents 44beac5 + c75826a commit cf764c0
Show file tree
Hide file tree
Showing 7 changed files with 348 additions and 0 deletions.
9 changes: 9 additions & 0 deletions components.js
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,15 @@ var components = {
"title": "Remove initial line feed",
"owner": "Golmote",
"noCSS": true
},
"previewer-base": {
"title": "Previewer Base",
"owner": "Golmote"
},
"previewer-color": {
"title": "Previewer Color",
"require": "previewer-base",
"owner": "Golmote"
}
}
};
76 changes: 76 additions & 0 deletions plugins/previewer-base/prism-previewer-base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
.prism-previewer,
.prism-previewer:before,
.prism-previewer:after {
position: absolute;
pointer-events: none;
}
.prism-previewer,
.prism-previewer:after {
left: 50%;
}
.prism-previewer {
margin-top: -48px;
width: 32px;
height: 32px;
margin-left: -16px;

-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=$opacity)";
filter: alpha(opacity=0);
-khtml-opacity: 0;
-moz-opacity: 0;
opacity: 0;
-webkit-transition: opacity .25s;
-moz-transition: opacity .25s;
-o-transition: opacity .25s;
transition: opacity .25s;
}
.prism-previewer.flipped {
margin-top: 0;
margin-bottom: -48px;
}
.prism-previewer:before,
.prism-previewer:after {
content: '';
position: absolute;
pointer-events: none;
}
.prism-previewer:before {
top: -5px;
right: -5px;
left: -5px;
bottom: -5px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
border: 5px solid #fff;
-webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
-ms-box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
-o-box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
}

.prism-previewer:after {
top: 100%;
width: 0;
height: 0;
margin: 5px 0 0 -7px;
border: 7px solid transparent;
border-color: rgba(255, 0, 0, 0);
border-top-color: #fff;
}
.prism-previewer.flipped:after {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 5px;
border-top-color: rgba(255, 0, 0, 0);
border-bottom-color: #fff;
}
.prism-previewer.active {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=$opacity)";
filter: alpha(opacity=1);
-khtml-opacity: 1;
-moz-opacity: 1;
opacity: 1;
}
186 changes: 186 additions & 0 deletions plugins/previewer-base/prism-previewer-base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
(function() {

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

/**
* Returns the absolute X, Y offsets for an element
* @param {HTMLElement} element
* @returns {{top: number, right: number, bottom: number, left: number}}
*/
var getOffset = function (element) {
var left = 0, top = 0, el = element;

if (el.parentNode) {
do {
left += el.offsetLeft;
top += el.offsetTop;
} while ((el = el.offsetParent) && el.nodeType < 9);

el = element;

do {
left -= el.scrollLeft;
top -= el.scrollTop;
} while ((el = el.parentNode) && !/body/i.test(el.nodeName));
}

return {
top: top,
right: innerWidth - left - element.offsetWidth,
bottom: innerHeight - top - element.offsetHeight,
left: left
};
};

var tokenRegexp = /(?:^|\s)token(?=$|\s)/;
var activeRegexp = /(?:^|\s)active(?=$|\s)/g;
var flippedRegexp = /(?:^|\s)flipped(?=$|\s)/g;

/**
* Previewer constructor
* @param {string} type Unique previewer type
* @param {function} updater Function that will be called on mouseover.
* @param {string[]|string=} supportedLanguages Aliases of the languages this previewer must be enabled for. Defaults to "*", all languages.
* @constructor
*/
var Previewer = function (type, updater, supportedLanguages) {
this._elt = null;
this._type = type;
this._clsRegexp = RegExp('(?:^|\\s)' + type + '(?=$|\\s)');
this._token = null;
this.updater = updater;
this._mouseout = this.mouseout.bind(this);

var self = this;

if (!supportedLanguages) {
supportedLanguages = ['*'];
}
if (Prism.util.type(supportedLanguages) !== 'Array') {
supportedLanguages = [supportedLanguages];
}
supportedLanguages.forEach(function (lang) {
if (typeof lang !== 'string') {
lang = lang.lang;
}
if (!Previewer.byLanguages[lang]) {
Previewer.byLanguages[lang] = [];
}
if (Previewer.byLanguages[lang].indexOf(self) < 0) {
Previewer.byLanguages[lang].push(self);
}
});
};

/**
* Creates the HTML element for the previewer.
*/
Previewer.prototype.init = function () {
if (this._elt) {
return;
}
this._elt = document.createElement('div');
this._elt.className = 'prism-previewer prism-previewer-' + this._type;
document.body.appendChild(this._elt);
};

/**
* Checks the class name of each hovered element
* @param token
*/
Previewer.prototype.check = function (token) {
if (tokenRegexp.test(token.className) && this._clsRegexp.test(token.className)) {
if (token !== this._token) {
this._token = token;
this.show();
}
}
};

/**
* Called on mouseout
*/
Previewer.prototype.mouseout = function() {
this._token.removeEventListener('mouseout', this._mouseout, false);
this._token = null;
this.hide();
};

/**
* Shows the previewer positioned properly for the current token.
*/
Previewer.prototype.show = function () {
if (!this._elt) {
this.init();
}
if (!this._token) {
return;
}

if (this.updater.call(this._elt, this._token.textContent)) {
this._token.addEventListener('mouseout', this._mouseout, false);

var offset = getOffset(this._token);
this._elt.className += ' active';

if (offset.top - this._elt.offsetHeight > 0) {
this._elt.className = this._elt.className.replace(flippedRegexp, '');
this._elt.style.top = offset.top + 'px';
this._elt.style.bottom = '';
} else {
this._elt.className += ' flipped';
this._elt.style.bottom = offset.bottom + 'px';
this._elt.style.top = '';
}

this._elt.style.left = offset.left + Math.min(200, this._token.offsetWidth / 2) + 'px';
} else {
this.hide();
}
};

/**
* Hides the previewer.
*/
Previewer.prototype.hide = function () {
this._elt.className = this._elt.className.replace(activeRegexp, '');
};

/**
* Map of all registered previewers by language
* @type {{}}
*/
Previewer.byLanguages = {};

/**
* Initializes the mouseover event on the code block.
* @param {HTMLElement} elt The code block (env.element)
* @param {string} lang The language (env.language)
*/
Previewer.initEvents = function (elt, lang) {
var previewers = [];
if (Previewer.byLanguages[lang]) {
previewers = previewers.concat(Previewer.byLanguages[lang]);
}
if (Previewer.byLanguages['*']) {
previewers = previewers.concat(Previewer.byLanguages['*']);
}
elt.addEventListener('mouseover', function (e) {
var target = e.target;
previewers.forEach(function (previewer) {
previewer.check(target);
});
}, false);
};
Prism.plugins.Previewer = Previewer;

// Initialize the previewers only when needed
Prism.hooks.add('after-highlight', function (env) {
if(Previewer.byLanguages['*'] || Previewer.byLanguages[env.language]) {
Previewer.initEvents(env.element, env.language);
}
});

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

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

9 changes: 9 additions & 0 deletions plugins/previewer-color/prism-previewer-color.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.prism-previewer-color {
background-image: linear-gradient(45deg, #bbb 25%, transparent 25%, transparent 75%, #bbb 75%, #bbb), linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
}
.prism-previewer-color:before {
background-color: inherit;
background-clip: padding-box;
}
66 changes: 66 additions & 0 deletions plugins/previewer-color/prism-previewer-color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
(function() {

if (
typeof self !== 'undefined' && !self.Prism ||
typeof global !== 'undefined' && !global.Prism
) {
return;
}

var languages = [
'css',
'less',
{
lang: 'markup',
before: 'punctuation',
inside: 'inside',
root: Prism.languages.markup && Prism.languages.markup['tag'].inside['attr-value']
},
{
lang: 'sass',
inside: 'inside',
root: Prism.languages.sass && Prism.languages.sass['property-line']
},
'scss',
{
lang: 'stylus',
before: 'hexcode',
inside: 'rest',
root: Prism.languages.stylus && Prism.languages.stylus['property-declaration'].inside
},
{
lang: 'stylus',
before: 'hexcode',
inside: 'rest',
root: Prism.languages.stylus && Prism.languages.stylus['variable-declaration'].inside
}
];

languages.forEach(function (lang) {
var before, inside, root, skip;
if (typeof lang === 'string') {
before = 'important';
inside = lang;
} else {
before = lang.before || 'important';
inside = lang.inside || lang.lang;
root = lang.root || Prism.languages;
skip = lang.skip;
lang = lang.lang;
}
if(!skip && Prism.languages[lang]) {
Prism.languages.insertBefore(inside, before, {
'color': /(?:\B#(?:[0-9a-f]{3}){1,2}\b|\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|\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|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|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|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b)/i
}, root);
}
});

if (Prism.plugins.Previewer) {
new Prism.plugins.Previewer('color', function(value) {
this.style.backgroundColor = '';
this.style.backgroundColor = value;
return !!this.style.backgroundColor;
});
}

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

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

0 comments on commit cf764c0

Please sign in to comment.