Created
July 27, 2018 18:43
-
-
Save berstend/2eb6132f57a2eb3b9544d80998e60255 to your computer and use it in GitHub Desktop.
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | |
(function (global){ | |
const csso = require('csso'); | |
const shrthnd = require('shrthnd'); | |
const specificity = require('specificity'); | |
const postcss = require('postcss'); | |
const cssDeclarationSorter = require('css-declaration-sorter'); | |
const postCssMergeLonghand = require('postcss-merge-longhand'); | |
const extension_styles = ` | |
#cssscan-css, | |
#cssscan-close, | |
#cssscan-buttons, | |
.cssscan-button { | |
z-index: 2147483647; | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
font-weight: 400; | |
} | |
#cssscan-css, | |
#cssscan-title, | |
#cssscan-copy, | |
#cssscan-code, | |
#cssscan-close, | |
#cssscan-dimensions, | |
.cssscan-button, | |
#cssscan-buttons { | |
color: #fff; | |
font-family: -apple-system, BlinkMacSystemFont, 'Roboto', sans-serif; | |
line-height: 24px; | |
outline: 0 !important; | |
width: initial !important; | |
} | |
#cssscan-css { | |
background: rgba(0, 0, 0, .9); | |
max-width: 400px; | |
margin-top: 2em; | |
padding: 20px; | |
font-size: 14px; | |
border-radius: 5px; | |
line-height: 24px; | |
min-width: 250px; | |
position: absolute; | |
display: none; | |
text-align: left; | |
will-change: transform; | |
top: 0; | |
left: 0; | |
} | |
#cssscan-copy, | |
#cssscan-dimensions { | |
opacity: .7; | |
//margin-top: 5px; | |
font-size: .8em; | |
//margin-bottom: -10px; | |
} | |
#cssscan-copy { | |
margin-top: 1em; | |
} | |
#cssscan-dimensions { | |
margin-top: 0px; | |
margin-bottom: 1em; | |
} | |
#cssscan-code { | |
white-space: pre-line; | |
//margin-top: 1em; | |
font-size: 14px; | |
} | |
#cssscan-code:empty { | |
display: none; | |
} | |
#cssscan-title { | |
margin-top: 0; | |
margin-bottom: 0; | |
font-weight: bold; | |
font-size: 16px; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
overflow: hidden; | |
width: 100%; | |
} | |
body.cssscan-grid-show * { | |
outline: rgba(255, 0, 0, .15) solid 1px !important; | |
} | |
.cssscan-current, | |
body.cssscan-grid-show .cssscan-current { | |
outline: red solid 1px !important; | |
} | |
#cssscan-close, | |
.cssscan-button { | |
background: rgba(0, 0, 0, .8); | |
border-radius: 50px; | |
padding: 4px 20px; | |
border: 0; | |
outline: 0; | |
font-size: 14px; | |
width: initial; | |
line-height: 24px; | |
box-shadow: none; | |
margin: 0; | |
transition: 0.1s ease-in all; | |
display: inline-block; | |
vertical-align: middle; | |
} | |
#cssscan-buttons { | |
top: 6px; | |
right: 6px; | |
position: fixed; | |
} | |
#cssscan-close:hover { | |
background: #000; | |
}` | |
function loadCSSCors(stylesheet_uri, order) { | |
if (stylesheet_uri.endsWith('.ico') || stylesheet_uri.endsWith('.png')) | |
return false | |
if (stylesheet_uri.endsWith('.less')) { | |
console.error('CSS Scan error: Less is not supported: ' + stylesheet_uri) | |
return false | |
} | |
var _xhr = global.XMLHttpRequest; | |
var has_cred = false; | |
try { | |
has_cred = _xhr && ('withCredentials' in (new _xhr())); | |
} catch(e) { | |
console.error('CSS Scan error', e) | |
} | |
if (!has_cred) { | |
console.error(`CSS Scan error: Can't load CSS because CORS not supported`) | |
return; | |
} | |
var xhr = new _xhr(); | |
xhr.open('GET', stylesheet_uri); | |
xhr.onload = function() { | |
xhr.onload = xhr.onerror = null; | |
if (xhr.status < 200 || xhr.status >= 300) { | |
console.error('CSS Scan error: Style failed to load: ' + stylesheet_uri); | |
} else { | |
const style_tag = document.createElement('style') | |
style_tag.innerText = xhr.responseText | |
iframe.contentDocument.body.appendChild(style_tag) | |
styles.splice(order, 0, style_tag) | |
} | |
}; | |
xhr.onerror = function() { | |
xhr.onload = xhr.onerror = null; | |
console.error('CSS Scan error: XHR CORS CSS fail, ' + styleURI); | |
}; | |
xhr.send(); | |
} | |
const styles = [] | |
const iframe = document.createElement('iframe') | |
iframe.setAttribute('style', 'display: none') | |
iframe.setAttribute('id', 'cssscan-iframe') | |
document.body.appendChild(iframe) | |
// Add all styles tags to styles array | |
const css_tags = document.querySelectorAll('link, style') | |
for (let i = 0; i < css_tags.length; i++) { | |
if (css_tags[i].localName == 'style') { | |
styles.push(css_tags[i]); | |
} else { | |
loadCSSCors(css_tags[i].href, i) | |
} | |
} | |
const html = document.getElementsByTagName('html')[0] | |
// Inject extension CSS to page | |
const style_loader = document.createElement('style'); | |
style_loader.innerText = extension_styles | |
document.head.appendChild(style_loader) | |
const body = document.getElementsByTagName('body')[0]; | |
function addElement(parent, elementTag, elementId, html) { | |
var newElement = document.createElement(elementTag); | |
newElement.setAttribute('id', elementId); | |
newElement.innerHTML = html; | |
parent.appendChild(newElement); | |
} | |
addElement(body, 'div', 'cssscan-css', | |
`<p id="cssscan-title"></p> | |
<p id="cssscan-dimensions"></p> | |
<p id="cssscan-code"></p> | |
<p id="cssscan-copy">Click to copy</p>`) | |
addElement(body, 'div', 'cssscan-buttons', | |
`<div class="cssscan-button" id="cssscan-ignore-box-sizing-div"><input type="checkbox" id="cssscan-checkbox-ignore-box-sizing"> Ignore box-sizing</div> | |
<div class="cssscan-button" id="cssscan-ignore-hover-div"><input type="checkbox" id="cssscan-checkbox-ignore-hover"> Ignore :hover styles</div> | |
<div class="cssscan-button" id="cssscan-grid-btn"><input type="checkbox" id="cssscan-checkbox-grid"> Show grid</div> | |
<button id="cssscan-close">Exit CSSScan</button>`) | |
var css_div = document.getElementById('cssscan-css'); | |
var title_div = document.getElementById('cssscan-title'); | |
var copy_div = document.getElementById('cssscan-copy'); | |
var code_div = document.getElementById('cssscan-code'); | |
var dimensions_div = document.getElementById('cssscan-dimensions'); | |
var buttons_div = document.getElementById('cssscan-buttons'); | |
var ignore_box_sizing = false | |
var ignore_hover = false | |
var show_grid = false | |
var checkbox_grid = document.getElementById("cssscan-checkbox-grid"); | |
var checkbox_ignore_box_sizing = document.getElementById("cssscan-checkbox-ignore-box-sizing"); | |
var checkbox_ignore_hover = document.getElementById("cssscan-checkbox-ignore-hover"); | |
function close () { | |
//style_loader.parentNode.removeChild(style_loader) | |
//iframe.parentNode.removeChild(iframe) | |
//css_div.parentNode.removeChild(css_div) | |
//buttons_div.parentNode.removeChild(buttons_div) | |
css_div.style.display = 'none' | |
buttons_div.style.display = 'none' | |
lastE.classList.remove('cssscan-current') | |
body.removeEventListener('click', handle_click_body) | |
body.removeEventListener('mouseout', handle_mouseout_body) | |
html.removeEventListener('mousemove', handle_mousemove_html) | |
if (body.className.includes('cssscan-grid-show')) | |
body.classList.remove('cssscan-grid-show') | |
//chrome.runtime.sendMessage('close') | |
} | |
document.onkeydown = function(evt) { | |
evt = evt || window.event; | |
var isEscape = false; | |
if ("key" in evt) { | |
isEscape = (evt.key == "Escape" || evt.key == "Esc"); | |
} else { | |
isEscape = (evt.keyCode == 27); | |
} | |
if (isEscape) { | |
close() | |
} | |
}; | |
var handle_click_body = function(e) { | |
if (e.target.id === 'cssscan-close') { | |
close() | |
} else if (code_div.textContent !== 'No styles found' && e.target.id !== 'cssscan-css' && e.target.id !== 'cssscan-checkbox-grid' && e.target.id !== 'cssscan-checkbox-ignore-box-sizing' && e.target.id !== 'cssscan-checkbox-ignore-hover' && e.isTrusted == true) { | |
//copy to clipboard | |
var tempInput = document.createElement("textarea"); | |
tempInput.style = "position: absolute; left: -1000px; top: -1000px"; | |
// Remove first and last character + jump each line | |
tempInput.value = code_div.textContent.slice(2, -1); | |
document.body.appendChild(tempInput); | |
tempInput.select(); | |
document.execCommand('copy'); | |
document.body.removeChild(tempInput); | |
title_div.textContent = 'Copied to clipboard!'; | |
code_div.innerHTML = ''; | |
dimensions_div.innerHTML = ''; | |
copy_div.parentNode.removeChild(copy_div) | |
e.stopPropagation() | |
e.preventDefault() | |
} | |
} | |
function handler(ev, ev_target_from_function) { | |
let target = {} | |
if (ev_target_from_function === undefined) { | |
target = ev.target | |
} else { | |
target = ev_target_from_function | |
} | |
if (target.offsetWidth && target.offsetHeight) { | |
dimensions_div.textContent = `${target.offsetWidth}x${target.offsetHeight}` | |
} else { | |
dimensions_div.textContent = '' | |
} | |
var classOrIdLabel = ''; | |
code_div.innerHTML = ''; | |
if (target.id && target.className && target.classList.value !== '') { | |
classOrIdLabel = `#${target.id}.${target.classList.value.replace(/ /g, '.').replace(/.cssscan-grid-show/g, '')}` | |
} else if (target.id) { | |
classOrIdLabel = `#${target.id}` | |
} else if (target.className && target.classList.value !== '') { | |
classOrIdLabel = `.${target.classList.value.replace(/ /g, '.').replace(/.cssscan-grid-show/g, '')}` | |
} | |
title_div.textContent = `${target.localName} ${classOrIdLabel}` | |
let processed_css = css(target) | |
if (processed_css != '') { | |
let optimized = shrthnd(csso.minify('body {' + processed_css + '}').css).string; | |
postcss([postCssMergeLonghand, cssDeclarationSorter({order: 'alphabetically'})]) | |
.process(optimized) | |
.then(function (result) { | |
if (result.css) { | |
code_div.textContent = result.css.match(/{\n([^}]+)}/)[1] | |
} else { | |
code_div.textContent = 'No styles found' | |
} | |
}); | |
if (copy_div && copy_div.style.display == 'none') | |
copy_div.style.display = 'block' | |
} else { | |
code_div.textContent = 'No styles found' | |
copy_div.style.display = 'none' | |
} | |
} | |
let lastE = {}; | |
let matches = function(el, selector) { | |
return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); | |
}; | |
let isOnIframe = false | |
const handle_mouseout_body = function(e) { | |
if (e.relatedTarget != null && e.relatedTarget.localName === 'iframe') { | |
lastE.classList.remove('cssscan-current'); | |
css_div.style.display = 'none' | |
isOnIframe = true | |
} else { | |
isOnIframe = false | |
} | |
} | |
const handle_mousemove_html = function(e){ | |
const ignore = ['cssscan-grid-btn', 'cssscan-checkbox-grid', 'cssscan-close', | |
'cssscan-css', 'cssscan-code', 'cssscan-copy', 'cssscan-title', | |
'cssscan-dimensions', 'cssscan-buttons', 'cssscan-ignore-box-sizing-div', | |
'cssscan-checkbox-ignore-box-sizing', 'cssscan-ignore-hover-div', 'cssscan-checkbox-ignore-hover'] | |
const target = e.target | |
if (target.id === 'cssscan-close' || target.id === 'cssscan-grid-btn' || target.id === 'cssscan-checkbox-grid' | |
|| target.id === 'cssscan-checkbox-ignore-hover' || target.id === 'cssscan-checkbox-ignore-box-sizing' | |
|| target.id === 'cssscan-ignore-hover-div' || target.id === 'cssscan-ignore-box-sizing-div') { | |
if (lastE.classList !== undefined) { | |
lastE.classList.remove('cssscan-current'); | |
} | |
css_div.style.display = 'none' | |
} else { | |
if (css_div.style.display !== 'inline-block' && !isOnIframe) | |
css_div.style.display = 'inline-block' | |
} | |
if (target != lastE && ignore.indexOf(target.id) === -1) { | |
handler(e); | |
if (lastE.classList !== undefined) { | |
lastE.classList.remove('cssscan-current'); | |
} | |
target.classList.add('cssscan-current'); | |
lastE = target; | |
} | |
let outlined_elements = document.getElementsByClassName('cssscan-current') | |
if (outlined_elements.length > 1) { | |
for (var i = 1; i < outlined_elements.length; i++) { | |
outlined_elements[i].classList.remove('cssscan-current'); | |
} | |
} | |
let translateX = 0, translateY = 0 | |
if (e.clientX + css_div.offsetWidth + 15 > window.innerWidth) { | |
translateX = e.pageX - css_div.offsetWidth - 13; | |
} else { | |
translateX = e.pageX + 20; | |
} | |
if (e.clientY + css_div.offsetHeight + 15 > window.innerHeight && (e.clientY - css_div.offsetHeight > -20)) { | |
translateY = e.pageY - 30 - css_div.offsetHeight | |
} else { | |
translateY = e.pageY | |
} | |
css_div.style.webkitTransform = `translate(${translateX}px, ${translateY}px)` | |
css_div.style.MozTransform = `translate(${translateX}px, ${translateY}px)` | |
css_div.style.msTransform = `translate(${translateX}px, ${translateY}px)` | |
css_div.style.OTransform = `translate(${translateX}px, ${translateY}px)` | |
//console.log(window.innerWidth, e.clientX) | |
//console.log(window.innerHeight, e.clientY) | |
//console.log(css_div.offsetWidth, css_div.offsetHeight) | |
} | |
function css(el) { | |
var arr = []; | |
for (var i in styles) { | |
var rules = styles[i].sheet.rules || styles[i].sheet.cssRules; | |
//console.log(rules.length) | |
for (var r in rules) { | |
if (rules[r].selectorText !== undefined && rules[r].selectorText !== '' && matches(el, rules[r].selectorText) && rules[r].selectorText !== 'body.cssscan-grid-show *') { | |
//console.log('ruless', rules[r].selectorText) | |
if (ignore_hover && rules[r].selectorText.includes(':hover')) { | |
continue; | |
} | |
arr.push([css2json(rules[r].style, el), specificity.calculate(rules[r].selectorText)[0].specificity]) | |
} else if (rules[r] instanceof CSSMediaRule && rules[r].conditionText !== 'print' && window.matchMedia(rules[r].conditionText).matches) { | |
for (var k of rules[r].cssRules) { | |
if (matches(el, k.selectorText)) { | |
arr.push([css2json(k.style), specificity.calculate(k.selectorText)[0].specificity]) | |
} | |
} | |
} | |
} | |
} | |
// Get inline style | |
arr.push([css2json(el.getAttribute('style'), el), '1,0,0,0']) | |
arr = arr.sort(function(a, b) { | |
if (a[1] > b[1]) { | |
return 1; | |
} else if (a[1] < b[1]) { | |
return -1; | |
} | |
return 0; | |
}); | |
arr = arr.map(function(i) { | |
return i.shift() | |
}) | |
return arr.join(' '); | |
} | |
function css2json(css, el) { | |
var s = ''; | |
if (!css) return s; | |
//CSS Style Declaration = type of object | |
if (css instanceof CSSStyleDeclaration) { | |
//s+= css.cssText; | |
for (var i in css) { | |
if ((css[i]).toLowerCase && css[css[i]] !== undefined && isNaN(css[i]) && css[i] in document.body.style) { | |
if (css[css[i]].startsWith('var(--')) { | |
// replace css var to value | |
// match: 'var(--teste)' > '--teste' | |
s += `${css[i].toLowerCase()}: ${window.getComputedStyle(el).getPropertyValue(css[css[i]].match(/var\(([^}]+)\)/)[1])};` | |
} else if (ignore_box_sizing && css[i] === 'box-sizing') { | |
continue; | |
} else { | |
s += `${css[i].toLowerCase()}: ${css[css[i]]};` | |
} | |
} | |
} | |
} else if (typeof css == "string") { | |
//s += css; | |
css = css.split(";"); | |
for (var i in css) { | |
if (css[i] !== '' && css[i] !== '\n') { | |
s += `${css[i]};` | |
} | |
} | |
} | |
//console.log(s) | |
return s; | |
} | |
function start () { | |
buttons_div.style.display = 'block' | |
html.addEventListener('mousemove', handle_mousemove_html) | |
body.addEventListener('mouseout', handle_mouseout_body) | |
body.addEventListener('click', handle_click_body) | |
checkbox_ignore_box_sizing.checked = ignore_box_sizing | |
checkbox_ignore_hover.checked = ignore_hover | |
checkbox_grid.checked = show_grid | |
if (show_grid) { | |
body.classList.add('cssscan-grid-show') | |
} | |
checkbox_grid.addEventListener('change', function() { | |
if (this.checked) { | |
body.classList.add('cssscan-grid-show') | |
} else { | |
body.classList.remove('cssscan-grid-show') | |
} | |
show_grid = this.checked | |
}); | |
checkbox_ignore_box_sizing.addEventListener('change', function() { | |
ignore_box_sizing = this.checked | |
handler({}, lastE) | |
}); | |
checkbox_ignore_hover.addEventListener('change', function() { | |
ignore_hover = this.checked | |
handler({}, lastE) | |
}); | |
} | |
function ready() { | |
if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading"){ | |
start() | |
} else { | |
document.addEventListener('DOMContentLoaded', function() { | |
start() | |
}); | |
} | |
} | |
const demo_btn = document.getElementById('demo-btn') | |
css_div.style.display = 'none' | |
buttons_div.style.display = 'none' | |
demo_btn.addEventListener('click', function (e) { | |
if (css_div.style.display === 'none') { | |
ready() | |
} | |
e.preventDefault() | |
e.stopPropagation() | |
}) | |
/* | |
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { | |
if (msg.text === 'are_you_there_content_script?') { | |
sendResponse({ | |
status: "yes" | |
}); | |
if (css_div.style.display === 'none') { | |
css_div.style.display = 'inline-block' | |
buttons_div.style.display = 'block' | |
start() | |
} | |
} | |
});*/ | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"css-declaration-sorter":37,"csso":182,"postcss":309,"postcss-merge-longhand":220,"shrthnd":322,"specificity":341}],2:[function(require,module,exports){ | |
(function (process,__filename){ | |
/** vim: et:ts=4:sw=4:sts=4 | |
* @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved. | |
* Available via the MIT or new BSD license. | |
* see: http://github.com/jrburke/amdefine for details | |
*/ | |
/*jslint node: true */ | |
/*global module, process */ | |
'use strict'; | |
/** | |
* Creates a define for node. | |
* @param {Object} module the "module" object that is defined by Node for the | |
* current module. | |
* @param {Function} [requireFn]. Node's require function for the current module. | |
* It only needs to be passed in Node versions before 0.5, when module.require | |
* did not exist. | |
* @returns {Function} a define function that is usable for the current node | |
* module. | |
*/ | |
function amdefine(module, requireFn) { | |
'use strict'; | |
var defineCache = {}, | |
loaderCache = {}, | |
alreadyCalled = false, | |
path = require('path'), | |
makeRequire, stringRequire; | |
/** | |
* Trims the . and .. from an array of path segments. | |
* It will keep a leading path segment if a .. will become | |
* the first path segment, to help with module name lookups, | |
* which act like paths, but can be remapped. But the end result, | |
* all paths that use this function should look normalized. | |
* NOTE: this method MODIFIES the input array. | |
* @param {Array} ary the array of path segments. | |
*/ | |
function trimDots(ary) { | |
var i, part; | |
for (i = 0; ary[i]; i+= 1) { | |
part = ary[i]; | |
if (part === '.') { | |
ary.splice(i, 1); | |
i -= 1; | |
} else if (part === '..') { | |
if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { | |
//End of the line. Keep at least one non-dot | |
//path segment at the front so it can be mapped | |
//correctly to disk. Otherwise, there is likely | |
//no path mapping for a path starting with '..'. | |
//This can still fail, but catches the most reasonable | |
//uses of .. | |
break; | |
} else if (i > 0) { | |
ary.splice(i - 1, 2); | |
i -= 2; | |
} | |
} | |
} | |
} | |
function normalize(name, baseName) { | |
var baseParts; | |
//Adjust any relative paths. | |
if (name && name.charAt(0) === '.') { | |
//If have a base name, try to normalize against it, | |
//otherwise, assume it is a top-level require that will | |
//be relative to baseUrl in the end. | |
if (baseName) { | |
baseParts = baseName.split('/'); | |
baseParts = baseParts.slice(0, baseParts.length - 1); | |
baseParts = baseParts.concat(name.split('/')); | |
trimDots(baseParts); | |
name = baseParts.join('/'); | |
} | |
} | |
return name; | |
} | |
/** | |
* Create the normalize() function passed to a loader plugin's | |
* normalize method. | |
*/ | |
function makeNormalize(relName) { | |
return function (name) { | |
return normalize(name, relName); | |
}; | |
} | |
function makeLoad(id) { | |
function load(value) { | |
loaderCache[id] = value; | |
} | |
load.fromText = function (id, text) { | |
//This one is difficult because the text can/probably uses | |
//define, and any relative paths and requires should be relative | |
//to that id was it would be found on disk. But this would require | |
//bootstrapping a module/require fairly deeply from node core. | |
//Not sure how best to go about that yet. | |
throw new Error('amdefine does not implement load.fromText'); | |
}; | |
return load; | |
} | |
makeRequire = function (systemRequire, exports, module, relId) { | |
function amdRequire(deps, callback) { | |
if (typeof deps === 'string') { | |
//Synchronous, single module require('') | |
return stringRequire(systemRequire, exports, module, deps, relId); | |
} else { | |
//Array of dependencies with a callback. | |
//Convert the dependencies to modules. | |
deps = deps.map(function (depName) { | |
return stringRequire(systemRequire, exports, module, depName, relId); | |
}); | |
//Wait for next tick to call back the require call. | |
if (callback) { | |
process.nextTick(function () { | |
callback.apply(null, deps); | |
}); | |
} | |
} | |
} | |
amdRequire.toUrl = function (filePath) { | |
if (filePath.indexOf('.') === 0) { | |
return normalize(filePath, path.dirname(module.filename)); | |
} else { | |
return filePath; | |
} | |
}; | |
return amdRequire; | |
}; | |
//Favor explicit value, passed in if the module wants to support Node 0.4. | |
requireFn = requireFn || function req() { | |
return module.require.apply(module, arguments); | |
}; | |
function runFactory(id, deps, factory) { | |
var r, e, m, result; | |
if (id) { | |
e = loaderCache[id] = {}; | |
m = { | |
id: id, | |
uri: __filename, | |
exports: e | |
}; | |
r = makeRequire(requireFn, e, m, id); | |
} else { | |
//Only support one define call per file | |
if (alreadyCalled) { | |
throw new Error('amdefine with no module ID cannot be called more than once per file.'); | |
} | |
alreadyCalled = true; | |
//Use the real variables from node | |
//Use module.exports for exports, since | |
//the exports in here is amdefine exports. | |
e = module.exports; | |
m = module; | |
r = makeRequire(requireFn, e, m, module.id); | |
} | |
//If there are dependencies, they are strings, so need | |
//to convert them to dependency values. | |
if (deps) { | |
deps = deps.map(function (depName) { | |
return r(depName); | |
}); | |
} | |
//Call the factory with the right dependencies. | |
if (typeof factory === 'function') { | |
result = factory.apply(m.exports, deps); | |
} else { | |
result = factory; | |
} | |
if (result !== undefined) { | |
m.exports = result; | |
if (id) { | |
loaderCache[id] = m.exports; | |
} | |
} | |
} | |
stringRequire = function (systemRequire, exports, module, id, relId) { | |
//Split the ID by a ! so that | |
var index = id.indexOf('!'), | |
originalId = id, | |
prefix, plugin; | |
if (index === -1) { | |
id = normalize(id, relId); | |
//Straight module lookup. If it is one of the special dependencies, | |
//deal with it, otherwise, delegate to node. | |
if (id === 'require') { | |
return makeRequire(systemRequire, exports, module, relId); | |
} else if (id === 'exports') { | |
return exports; | |
} else if (id === 'module') { | |
return module; | |
} else if (loaderCache.hasOwnProperty(id)) { | |
return loaderCache[id]; | |
} else if (defineCache[id]) { | |
runFactory.apply(null, defineCache[id]); | |
return loaderCache[id]; | |
} else { | |
if(systemRequire) { | |
return systemRequire(originalId); | |
} else { | |
throw new Error('No module with ID: ' + id); | |
} | |
} | |
} else { | |
//There is a plugin in play. | |
prefix = id.substring(0, index); | |
id = id.substring(index + 1, id.length); | |
plugin = stringRequire(systemRequire, exports, module, prefix, relId); | |
if (plugin.normalize) { | |
id = plugin.normalize(id, makeNormalize(relId)); | |
} else { | |
//Normalize the ID normally. | |
id = normalize(id, relId); | |
} | |
if (loaderCache[id]) { | |
return loaderCache[id]; | |
} else { | |
plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); | |
return loaderCache[id]; | |
} | |
} | |
}; | |
//Create a define function specific to the module asking for amdefine. | |
function define(id, deps, factory) { | |
if (Array.isArray(id)) { | |
factory = deps; | |
deps = id; | |
id = undefined; | |
} else if (typeof id !== 'string') { | |
factory = id; | |
id = deps = undefined; | |
} | |
if (deps && !Array.isArray(deps)) { | |
factory = deps; | |
deps = undefined; | |
} | |
if (!deps) { | |
deps = ['require', 'exports', 'module']; | |
} | |
//Set up properties for this module. If an ID, then use | |
//internal cache. If no ID, then use the external variables | |
//for this node module. | |
if (id) { | |
//Put the module in deep freeze until there is a | |
//require call for it. | |
defineCache[id] = [id, deps, factory]; | |
} else { | |
runFactory(id, deps, factory); | |
} | |
} | |
//define.require, which has access to all the values in the | |
//cache. Useful for AMD modules that all have IDs in the file, | |
//but need to finally export a value to node based on one of those | |
//IDs. | |
define.require = function (id) { | |
if (loaderCache[id]) { | |
return loaderCache[id]; | |
} | |
if (defineCache[id]) { | |
runFactory.apply(null, defineCache[id]); | |
return loaderCache[id]; | |
} | |
}; | |
define.amd = {}; | |
return define; | |
} | |
module.exports = amdefine; | |
}).call(this,require('_process'),"/node_modules/amdefine/amdefine.js") | |
},{"_process":398,"path":397}],3:[function(require,module,exports){ | |
var BrowserslistError = require('./error') | |
function noop () { } | |
module.exports = { | |
loadQueries: function loadQueries () { | |
throw new BrowserslistError( | |
'Sharable configs are not supported in client-side build of Browserslist') | |
}, | |
getStat: function getStat (opts) { | |
return opts.stats | |
}, | |
loadConfig: function loadConfig (opts) { | |
if (opts.config) { | |
throw new BrowserslistError( | |
'Browserslist config are not supported in client-side build') | |
} | |
}, | |
loadCountry: function loadCountry () { | |
throw new BrowserslistError( | |
'Country statistics is not supported ' + | |
'in client-side build of Browserslist') | |
}, | |
parseConfig: noop, | |
readConfig: noop, | |
findConfig: noop, | |
clearCaches: noop, | |
oldDataWarning: noop | |
} | |
},{"./error":4}],4:[function(require,module,exports){ | |
function BrowserslistError (message) { | |
this.name = 'BrowserslistError' | |
this.message = message | |
this.browserslist = true | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, BrowserslistError) | |
} | |
} | |
BrowserslistError.prototype = Error.prototype | |
module.exports = BrowserslistError | |
},{}],5:[function(require,module,exports){ | |
var jsReleases = require('node-releases/data/processed/envs.json') | |
var agents = require('caniuse-lite/dist/unpacker/agents').agents | |
var jsEOL = require('node-releases/data/release-schedule/release-schedule.json') | |
var path = require('path') | |
var e2c = require('electron-to-chromium/versions') | |
var BrowserslistError = require('./error') | |
var env = require('./node') // Will load browser.js in webpack | |
var FLOAT_RANGE = /^\d+(\.\d+)?(-\d+(\.\d+)?)*$/ | |
function normalize (versions) { | |
return versions.filter(function (version) { | |
return typeof version === 'string' | |
}) | |
} | |
function nameMapper (name) { | |
return function mapName (version) { | |
return name + ' ' + version | |
} | |
} | |
function getMajor (version) { | |
return parseInt(version.split('.')[0]) | |
} | |
function getMajorVersions (released, number) { | |
if (released.length === 0) return [] | |
var minimum = getMajor(released[released.length - 1]) - parseInt(number) + 1 | |
var selected = [] | |
for (var i = released.length - 1; i >= 0; i--) { | |
if (minimum > getMajor(released[i])) break | |
selected.unshift(released[i]) | |
} | |
return selected | |
} | |
function uniq (array) { | |
var filtered = [] | |
for (var i = 0; i < array.length; i++) { | |
if (filtered.indexOf(array[i]) === -1) filtered.push(array[i]) | |
} | |
return filtered | |
} | |
// Helpers | |
function fillUsage (result, name, data) { | |
for (var i in data) { | |
result[name + ' ' + i] = data[i] | |
} | |
} | |
function generateFilter (sign, version) { | |
version = parseFloat(version) | |
if (sign === '>') { | |
return function (v) { | |
return parseFloat(v) > version | |
} | |
} else if (sign === '>=') { | |
return function (v) { | |
return parseFloat(v) >= version | |
} | |
} else if (sign === '<') { | |
return function (v) { | |
return parseFloat(v) < version | |
} | |
} else { | |
return function (v) { | |
return parseFloat(v) <= version | |
} | |
} | |
} | |
function compareStrings (a, b) { | |
if (a < b) return -1 | |
if (a > b) return +1 | |
return 0 | |
} | |
function normalizeVersion (data, version) { | |
if (data.versions.indexOf(version) !== -1) { | |
return version | |
} else if (browserslist.versionAliases[data.name][version]) { | |
return browserslist.versionAliases[data.name][version] | |
} else if (data.versions.length === 1) { | |
return data.versions[0] | |
} else { | |
return false | |
} | |
} | |
function filterByYear (since) { | |
return Object.keys(agents).reduce(function (selected, name) { | |
var data = byName(name) | |
if (!data) return selected | |
var versions = Object.keys(data.releaseDate).filter(function (v) { | |
return data.releaseDate[v] >= since | |
}) | |
return selected.concat(versions.map(nameMapper(data.name))) | |
}, []) | |
} | |
function byName (name) { | |
name = name.toLowerCase() | |
name = browserslist.aliases[name] || name | |
return browserslist.data[name] | |
} | |
function checkName (name) { | |
var data = byName(name) | |
if (!data) throw new BrowserslistError('Unknown browser ' + name) | |
return data | |
} | |
function unknownQuery (query) { | |
return new BrowserslistError('Unknown browser query `' + query + '`') | |
} | |
function resolve (queries, context) { | |
return queries.reduce(function (result, selection, index) { | |
selection = selection.trim() | |
if (selection === '') return result | |
var isExclude = selection.indexOf('not ') === 0 | |
if (isExclude) { | |
if (index === 0) { | |
throw new BrowserslistError( | |
'Write any browsers query (for instance, `defaults`) ' + | |
'before `' + selection + '`') | |
} | |
selection = selection.slice(4) | |
} | |
for (var i = 0; i < QUERIES.length; i++) { | |
var type = QUERIES[i] | |
var match = selection.match(type.regexp) | |
if (match) { | |
var args = [context].concat(match.slice(1)) | |
var array = type.select.apply(browserslist, args) | |
if (isExclude) { | |
array = array.concat(array.map(function (j) { | |
return j.replace(/\s\S+/, ' 0') | |
})) | |
return result.filter(function (j) { | |
return array.indexOf(j) === -1 | |
}) | |
} | |
return result.concat(array) | |
} | |
} | |
throw unknownQuery(selection) | |
}, []) | |
} | |
/** | |
* Return array of browsers by selection queries. | |
* | |
* @param {(string|string[])} [queries=browserslist.defaults] Browser queries. | |
* @param {object} [opts] Options. | |
* @param {string} [opts.path="."] Path to processed file. | |
* It will be used to find config files. | |
* @param {string} [opts.env="production"] Processing environment. | |
* It will be used to take right | |
* queries from config file. | |
* @param {string} [opts.config] Path to config file with queries. | |
* @param {object} [opts.stats] Custom browser usage statistics | |
* for "> 1% in my stats" query. | |
* @param {boolean} [opts.ignoreUnknownVersions=false] Do not throw on unknown | |
* version in direct query. | |
* @param {boolean} [opts.dangerousExtend] Disable security checks | |
* for extend query. | |
* @return {string[]} Array with browser names in Can I Use. | |
* | |
* @example | |
* browserslist('IE >= 10, IE 8') //=> ['ie 11', 'ie 10', 'ie 8'] | |
*/ | |
function browserslist (queries, opts) { | |
if (typeof opts === 'undefined') opts = { } | |
if (typeof opts.path === 'undefined') { | |
opts.path = path.resolve ? path.resolve('.') : '.' | |
} | |
if (typeof queries === 'undefined' || queries === null) { | |
var config = browserslist.loadConfig(opts) | |
if (config) { | |
queries = config | |
} else { | |
queries = browserslist.defaults | |
} | |
} | |
if (typeof queries === 'string') { | |
queries = queries.split(/,\s*/) | |
} | |
if (!Array.isArray(queries)) { | |
throw new BrowserslistError( | |
'Browser queries must be an array. Got ' + typeof queries + '.') | |
} | |
var context = { | |
ignoreUnknownVersions: opts.ignoreUnknownVersions, | |
dangerousExtend: opts.dangerousExtend | |
} | |
env.oldDataWarning(browserslist.data) | |
var stats = env.getStat(opts) | |
if (stats) { | |
context.customUsage = { } | |
for (var browser in stats) { | |
fillUsage(context.customUsage, browser, stats[browser]) | |
} | |
} | |
var result = resolve(queries, context).map(function (i) { | |
var parts = i.split(' ') | |
var name = parts[0] | |
var version = parts[1] | |
if (version === '0') { | |
return name + ' ' + byName(name).versions[0] | |
} else { | |
return i | |
} | |
}).sort(function (name1, name2) { | |
name1 = name1.split(' ') | |
name2 = name2.split(' ') | |
if (name1[0] === name2[0]) { | |
if (FLOAT_RANGE.test(name1[1]) && FLOAT_RANGE.test(name2[1])) { | |
return parseFloat(name2[1]) - parseFloat(name1[1]) | |
} else { | |
return compareStrings(name2[1], name1[1]) | |
} | |
} else { | |
return compareStrings(name1[0], name2[0]) | |
} | |
}) | |
return uniq(result) | |
} | |
// Will be filled by Can I Use data below | |
browserslist.data = { } | |
browserslist.usage = { | |
global: { }, | |
custom: null | |
} | |
// Default browsers query | |
browserslist.defaults = [ | |
'> 0.5%', | |
'last 2 versions', | |
'Firefox ESR', | |
'not dead' | |
] | |
// Browser names aliases | |
browserslist.aliases = { | |
fx: 'firefox', | |
ff: 'firefox', | |
ios: 'ios_saf', | |
explorer: 'ie', | |
blackberry: 'bb', | |
explorermobile: 'ie_mob', | |
operamini: 'op_mini', | |
operamobile: 'op_mob', | |
chromeandroid: 'and_chr', | |
firefoxandroid: 'and_ff', | |
ucandroid: 'and_uc', | |
qqandroid: 'and_qq' | |
} | |
// Aliases to work with joined versions like `ios_saf 7.0-7.1` | |
browserslist.versionAliases = { } | |
browserslist.clearCaches = env.clearCaches | |
browserslist.parseConfig = env.parseConfig | |
browserslist.readConfig = env.readConfig | |
browserslist.findConfig = env.findConfig | |
browserslist.loadConfig = env.loadConfig | |
/** | |
* Return browsers market coverage. | |
* | |
* @param {string[]} browsers Browsers names in Can I Use. | |
* @param {string|object} [stats="global"] Which statistics should be used. | |
* Country code or custom statistics. | |
* Pass `"my stats"` to load statistics | |
* from Browserslist files. | |
* | |
* @return {number} Total market coverage for all selected browsers. | |
* | |
* @example | |
* browserslist.coverage(browserslist('> 1% in US'), 'US') //=> 83.1 | |
*/ | |
browserslist.coverage = function (browsers, stats) { | |
var data | |
if (typeof stats === 'undefined') { | |
data = browserslist.usage.global | |
} else if (stats === 'my stats') { | |
var opts = {} | |
opts.path = path.resolve ? path.resolve('.') : '.' | |
var customStats = env.getStat(opts) | |
if (!customStats) { | |
throw new BrowserslistError('Custom usage statistics was not provided') | |
} | |
data = {} | |
for (var browser in customStats) { | |
fillUsage(data, browser, customStats[browser]) | |
} | |
} else if (typeof stats === 'string') { | |
if (stats.length > 2) { | |
stats = stats.toLowerCase() | |
} else { | |
stats = stats.toUpperCase() | |
} | |
env.loadCountry(browserslist.usage, stats) | |
data = browserslist.usage[stats] | |
} else { | |
if ('dataByBrowser' in stats) { | |
stats = stats.dataByBrowser | |
} | |
data = { } | |
for (var name in stats) { | |
for (var version in stats[name]) { | |
data[name + ' ' + version] = stats[name][version] | |
} | |
} | |
} | |
return browsers.reduce(function (all, i) { | |
var usage = data[i] | |
if (usage === undefined) { | |
usage = data[i.replace(/ \S+$/, ' 0')] | |
} | |
return all + (usage || 0) | |
}, 0) | |
} | |
var QUERIES = [ | |
{ | |
regexp: /^last\s+(\d+)\s+major versions?$/i, | |
select: function (context, versions) { | |
return Object.keys(agents).reduce(function (selected, name) { | |
var data = byName(name) | |
if (!data) return selected | |
var array = getMajorVersions(data.released, versions) | |
array = array.map(nameMapper(data.name)) | |
return selected.concat(array) | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+versions?$/i, | |
select: function (context, versions) { | |
return Object.keys(agents).reduce(function (selected, name) { | |
var data = byName(name) | |
if (!data) return selected | |
var array = data.released.slice(-versions) | |
array = array.map(nameMapper(data.name)) | |
return selected.concat(array) | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+electron\s+major versions?$/i, | |
select: function (context, versions) { | |
var validVersions = getMajorVersions(Object.keys(e2c).reverse(), versions) | |
return validVersions.map(function (i) { | |
return 'chrome ' + e2c[i] | |
}) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+(\w+)\s+major versions?$/i, | |
select: function (context, versions, name) { | |
var data = checkName(name) | |
var validVersions = getMajorVersions(data.released, versions) | |
return validVersions.map(nameMapper(data.name)) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+electron\s+versions?$/i, | |
select: function (context, versions) { | |
return Object.keys(e2c).reverse().slice(-versions).map(function (i) { | |
return 'chrome ' + e2c[i] | |
}) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+(\w+)\s+versions?$/i, | |
select: function (context, versions, name) { | |
var data = checkName(name) | |
return data.released.slice(-versions).map(nameMapper(data.name)) | |
} | |
}, | |
{ | |
regexp: /^unreleased\s+versions$/i, | |
select: function () { | |
return Object.keys(agents).reduce(function (selected, name) { | |
var data = byName(name) | |
if (!data) return selected | |
var array = data.versions.filter(function (v) { | |
return data.released.indexOf(v) === -1 | |
}) | |
array = array.map(nameMapper(data.name)) | |
return selected.concat(array) | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^unreleased\s+electron\s+versions?$/i, | |
select: function () { | |
return [] | |
} | |
}, | |
{ | |
regexp: /^unreleased\s+(\w+)\s+versions?$/i, | |
select: function (context, name) { | |
var data = checkName(name) | |
return data.versions.filter(function (v) { | |
return data.released.indexOf(v) === -1 | |
}).map(nameMapper(data.name)) | |
} | |
}, | |
{ | |
regexp: /^last\s+(\d+)\s+years?$/i, | |
select: function (context, years) { | |
var date = new Date() | |
var since = date.setFullYear(date.getFullYear() - years) / 1000 | |
return filterByYear(since) | |
} | |
}, | |
{ | |
regexp: /^since (\d+)(?:-(\d+))?(?:-(\d+))?$/i, | |
select: function (context, year, month, date) { | |
year = parseInt(year) | |
month = parseInt(month || '01') - 1 | |
date = parseInt(date || '01') | |
var since = Date.UTC(year, month, date, 0, 0, 0) / 1000 | |
return filterByYear(since) | |
} | |
}, | |
{ | |
regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%$/, | |
select: function (context, sign, popularity) { | |
popularity = parseFloat(popularity) | |
var usage = browserslist.usage.global | |
return Object.keys(usage).reduce(function (result, version) { | |
if (sign === '>') { | |
if (usage[version] > popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<') { | |
if (usage[version] < popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<=') { | |
if (usage[version] <= popularity) { | |
result.push(version) | |
} | |
} else if (usage[version] >= popularity) { | |
result.push(version) | |
} | |
return result | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+my\s+stats$/, | |
select: function (context, sign, popularity) { | |
popularity = parseFloat(popularity) | |
if (!context.customUsage) { | |
throw new BrowserslistError('Custom usage statistics was not provided') | |
} | |
var usage = context.customUsage | |
return Object.keys(usage).reduce(function (result, version) { | |
if (sign === '>') { | |
if (usage[version] > popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<') { | |
if (usage[version] < popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<=') { | |
if (usage[version] <= popularity) { | |
result.push(version) | |
} | |
} else if (usage[version] >= popularity) { | |
result.push(version) | |
} | |
return result | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^(>=?|<=?)\s*(\d*\.?\d+)%\s+in\s+((alt-)?\w\w)$/, | |
select: function (context, sign, popularity, place) { | |
popularity = parseFloat(popularity) | |
if (place.length === 2) { | |
place = place.toUpperCase() | |
} else { | |
place = place.toLowerCase() | |
} | |
env.loadCountry(browserslist.usage, place) | |
var usage = browserslist.usage[place] | |
return Object.keys(usage).reduce(function (result, version) { | |
if (sign === '>') { | |
if (usage[version] > popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<') { | |
if (usage[version] < popularity) { | |
result.push(version) | |
} | |
} else if (sign === '<=') { | |
if (usage[version] <= popularity) { | |
result.push(version) | |
} | |
} else if (usage[version] >= popularity) { | |
result.push(version) | |
} | |
return result | |
}, []) | |
} | |
}, | |
{ | |
regexp: /^cover\s+(\d*\.?\d+)%(\s+in\s+(my\s+stats|(alt-)?\w\w))?$/, | |
select: function (context, coverage, statMode) { | |
coverage = parseFloat(coverage) | |
var usage = browserslist.usage.global | |
if (statMode) { | |
if (statMode.match(/^\s+in\s+my\s+stats$/)) { | |
if (!context.customUsage) { | |
throw new BrowserslistError( | |
'Custom usage statistics was not provided' | |
) | |
} | |
usage = context.customUsage | |
} else { | |
var match = statMode.match(/\s+in\s+((alt-)?\w\w)/) | |
var place = match[1] | |
if (place.length === 2) { | |
place = place.toUpperCase() | |
} else { | |
place = place.toLowerCase() | |
} | |
env.loadCountry(browserslist.usage, place) | |
usage = browserslist.usage[place] | |
} | |
} | |
var versions = Object.keys(usage).sort(function (a, b) { | |
return usage[b] - usage[a] | |
}) | |
var coveraged = 0 | |
var result = [] | |
var version | |
for (var i = 0; i <= versions.length; i++) { | |
version = versions[i] | |
if (usage[version] === 0) break | |
coveraged += usage[version] | |
result.push(version) | |
if (coveraged >= coverage) break | |
} | |
return result | |
} | |
}, | |
{ | |
regexp: /^electron\s+([\d.]+)\s*-\s*([\d.]+)$/i, | |
select: function (context, from, to) { | |
if (!e2c[from]) { | |
throw new BrowserslistError('Unknown version ' + from + ' of electron') | |
} | |
if (!e2c[to]) { | |
throw new BrowserslistError('Unknown version ' + to + ' of electron') | |
} | |
from = parseFloat(from) | |
to = parseFloat(to) | |
return Object.keys(e2c).filter(function (i) { | |
var parsed = parseFloat(i) | |
return parsed >= from && parsed <= to | |
}).map(function (i) { | |
return 'chrome ' + e2c[i] | |
}) | |
} | |
}, | |
{ | |
regexp: /^(\w+)\s+([\d.]+)\s*-\s*([\d.]+)$/i, | |
select: function (context, name, from, to) { | |
var data = checkName(name) | |
from = parseFloat(normalizeVersion(data, from) || from) | |
to = parseFloat(normalizeVersion(data, to) || to) | |
function filter (v) { | |
var parsed = parseFloat(v) | |
return parsed >= from && parsed <= to | |
} | |
return data.released.filter(filter).map(nameMapper(data.name)) | |
} | |
}, | |
{ | |
regexp: /^electron\s*(>=?|<=?)\s*([\d.]+)$/i, | |
select: function (context, sign, version) { | |
return Object.keys(e2c) | |
.filter(generateFilter(sign, version)) | |
.map(function (i) { | |
return 'chrome ' + e2c[i] | |
}) | |
} | |
}, | |
{ | |
regexp: /^(\w+)\s*(>=?|<=?)\s*([\d.]+)$/, | |
select: function (context, name, sign, version) { | |
var data = checkName(name) | |
var alias = browserslist.versionAliases[data.name][version] | |
if (alias) { | |
version = alias | |
} | |
return data.released | |
.filter(generateFilter(sign, version)) | |
.map(function (v) { | |
return data.name + ' ' + v | |
}) | |
} | |
}, | |
{ | |
regexp: /^(firefox|ff|fx)\s+esr$/i, | |
select: function () { | |
return ['firefox 52', 'firefox 60'] | |
} | |
}, | |
{ | |
regexp: /(operamini|op_mini)\s+all/i, | |
select: function () { | |
return ['op_mini all'] | |
} | |
}, | |
{ | |
regexp: /^electron\s+([\d.]+)$/i, | |
select: function (context, version) { | |
var chrome = e2c[version] | |
if (!chrome) { | |
throw new BrowserslistError( | |
'Unknown version ' + version + ' of electron') | |
} | |
return ['chrome ' + chrome] | |
} | |
}, | |
{ | |
regexp: /^node\s+(\d+(\.\d+)?(\.\d+)?)$/i, | |
select: function (context, version) { | |
var nodeReleases = jsReleases.filter(function (i) { | |
return i.name === 'nodejs' | |
}) | |
var matched = nodeReleases.filter(function (i) { | |
return (i.version + '.').indexOf(version + '.') === 0 | |
}) | |
if (matched.length === 0) { | |
if (context.ignoreUnknownVersions) { | |
return [] | |
} else { | |
throw new BrowserslistError( | |
'Unknown version ' + version + ' of Node.js') | |
} | |
} | |
return ['node ' + matched[matched.length - 1].version] | |
} | |
}, | |
{ | |
regexp: /^maintained\s+node\s+versions$/i, | |
select: function (context) { | |
var now = Date.now() | |
var queries = Object.keys(jsEOL).filter(function (key) { | |
return now < Date.parse(jsEOL[key].end) | |
}).map(function (key) { | |
return 'node ' + key.slice(1) | |
}) | |
return resolve(queries, context) | |
} | |
}, | |
{ | |
regexp: /^(\w+)\s+(tp|[\d.]+)$/i, | |
select: function (context, name, version) { | |
if (/^tp$/i.test(version)) version = 'TP' | |
var data = checkName(name) | |
var alias = normalizeVersion(data, version) | |
if (alias) { | |
version = alias | |
} else { | |
if (version.indexOf('.') === -1) { | |
alias = version + '.0' | |
} else { | |
alias = version.replace(/\.0$/, '') | |
} | |
alias = normalizeVersion(data, alias) | |
if (alias) { | |
version = alias | |
} else if (context.ignoreUnknownVersions) { | |
return [] | |
} else { | |
throw new BrowserslistError( | |
'Unknown version ' + version + ' of ' + name) | |
} | |
} | |
return [data.name + ' ' + version] | |
} | |
}, | |
{ | |
regexp: /^extends (.+)$/i, | |
select: function (context, name) { | |
return resolve(env.loadQueries(context, name), context) | |
} | |
}, | |
{ | |
regexp: /^defaults$/i, | |
select: function () { | |
return browserslist(browserslist.defaults) | |
} | |
}, | |
{ | |
regexp: /^dead$/i, | |
select: function (context) { | |
var dead = ['ie <= 10', 'ie_mob <= 10', 'bb <= 10', 'op_mob <= 12.1'] | |
return resolve(dead, context) | |
} | |
}, | |
{ | |
regexp: /^(\w+)$/i, | |
select: function (context, name) { | |
if (byName(name)) { | |
throw new BrowserslistError( | |
'Specify versions in Browserslist query for browser ' + name) | |
} else { | |
throw unknownQuery(name) | |
} | |
} | |
} | |
]; | |
// Get and convert Can I Use data | |
(function () { | |
for (var name in agents) { | |
var browser = agents[name] | |
browserslist.data[name] = { | |
name: name, | |
versions: normalize(agents[name].versions), | |
released: normalize(agents[name].versions.slice(0, -3)), | |
releaseDate: agents[name].release_date | |
} | |
fillUsage(browserslist.usage.global, name, browser.usage_global) | |
browserslist.versionAliases[name] = { } | |
for (var i = 0; i < browser.versions.length; i++) { | |
var full = browser.versions[i] | |
if (!full) continue | |
if (full.indexOf('-') !== -1) { | |
var interval = full.split('-') | |
for (var j = 0; j < interval.length; j++) { | |
browserslist.versionAliases[name][interval[j]] = full | |
} | |
} | |
} | |
} | |
}()) | |
module.exports = browserslist | |
},{"./error":4,"./node":3,"caniuse-lite/dist/unpacker/agents":9,"electron-to-chromium/versions":214,"node-releases/data/processed/envs.json":218,"node-releases/data/release-schedule/release-schedule.json":219,"path":393}],6:[function(require,module,exports){ | |
module.exports={A:{A:{H:0.00895953,D:0.0134393,G:0.179191,E:0.161271,A:0.107514,B:2.71026,FB:0.009298},B:"ms",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","FB","H","D","G","E","A","B","","",""],E:"IE",F:{FB:962323200,H:998870400,D:1161129600,G:1237420800,E:1300060800,A:1346716800,B:1381968000}},B:{A:{C:0.026214,p:0.026214,x:0.065535,J:0.074273,L:0.48059,N:1.15342,I:0},B:"ms",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","C","p","x","J","L","N","I","",""],E:"Edge",F:{C:1438128000,p:1447286400,x:1470096000,J:1491868800,L:1508198400,N:1525046400,I:null}},C:{A:{"0":0.017476,"1":0.026214,"2":0.039321,"3":0.08738,"4":0.056797,"5":0.048059,"6":0.148546,"8":0.21845,"9":0.013107,ZB:0.013107,CB:0.004369,F:0.004369,K:0.004879,H:0.020136,D:0.005725,G:0.008738,E:0.00533,A:0.004283,B:0.004369,C:0.004471,p:0.004486,x:0.00453,J:0.013107,L:0.004417,N:0.004349,I:0.004393,O:0.004443,P:0.004283,Q:0.004369,R:0.004393,S:0.013107,T:0.008786,U:0.004369,V:0.004393,W:0.004393,X:0.004418,Y:0.004369,Z:0.004369,b:0.004471,c:0.008738,d:0.013107,e:0.004369,f:0.004369,g:0.008738,h:0.04369,i:0.008738,j:0.008738,k:0.013107,l:0.008738,m:0.026214,n:0.008738,o:0.034952,M:0.008738,q:0.069904,r:0.126701,s:0.021845,t:0.021845,u:0.056797,v:0.432531,w:0.021845,y:3.23743,AB:0,XB:0.008786,RB:0.008738},B:"moz",C:["","","ZB","CB","XB","RB","F","K","H","D","G","E","A","B","C","p","x","J","L","N","I","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","b","c","d","e","f","g","h","i","j","k","l","m","n","o","M","q","r","s","t","u","v","w","1","2","3","4","5","6","y","8","9","AB",""],E:"Firefox",F:{"0":1405987200,"1":1497312000,"2":1502150400,"3":1506556800,"4":1510617600,"5":1516665600,"6":1520985600,"8":1529971200,"9":null,ZB:1161648000,CB:1213660800,XB:1246320000,RB:1264032000,F:1300752000,K:1308614400,H:1313452800,D:1317081600,G:1317081600,E:1320710400,A:1324339200,B:1327968000,C:1331596800,p:1335225600,x:1338854400,J:1342483200,L:1346112000,N:1349740800,I:1353628800,O:1357603200,P:1361232000,Q:1364860800,R:1368489600,S:1372118400,T:1375747200,U:1379376000,V:1386633600,W:1391472000,X:1395100800,Y:1398729600,Z:1402358400,b:1409616000,c:1413244800,d:1417392000,e:1421107200,f:1424736000,g:1428278400,h:1431475200,i:1435881600,j:1439251200,k:1442880000,l:1446508800,m:1450137600,n:1453852800,o:1457395200,M:1461628800,q:1465257600,r:1470096000,s:1474329600,t:1479168000,u:1485216000,v:1488844800,w:1492560000,y:1525824000,AB:null}},D:{A:{"0":0.026214,"1":0.074273,"2":0.336413,"3":0.104856,"4":0.074273,"5":0.113594,"6":0.056797,"8":0.100487,"9":0.144177,F:0.004706,K:0.004879,H:0.004879,D:0.005591,G:0.005591,E:0.005591,A:0.004534,B:0.008738,C:0.004283,p:0.004879,x:0.004706,J:0.009154,L:0.004393,N:0.004393,I:0.013107,O:0.004418,P:0.004393,Q:0.004369,R:0.017476,S:0.008786,T:0.026214,U:0.013107,V:0.008738,W:0.004369,X:0.008738,Y:0.196605,Z:0.017476,b:0.008738,c:0.013107,d:0.021845,e:0.026214,f:0.017476,g:0.017476,h:0.030583,i:0.013107,j:0.017476,k:0.017476,l:0.026214,m:0.061166,n:0.008738,o:0.017476,M:0.017476,q:0.030583,r:0.039321,s:0.712147,t:0.026214,u:0.04369,v:0.048059,w:0.026214,y:0.08738,AB:0.432531,LB:0.227188,bB:0.4369,GB:9.00451,a:15.4925,HB:0.061166,IB:0.030583,JB:0},B:"webkit",C:["F","K","H","D","G","E","A","B","C","p","x","J","L","N","I","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","b","c","d","e","f","g","h","i","j","k","l","m","n","o","M","q","r","s","t","u","v","w","1","2","3","4","5","6","y","8","9","AB","LB","bB","GB","a","HB","IB","JB"],E:"Chrome",F:{"0":1384214400,"1":1476230400,"2":1480550400,"3":1485302400,"4":1489017600,"5":1492560000,"6":1496707200,"8":1504569600,"9":1508198400,F:1264377600,K:1274745600,H:1283385600,D:1287619200,G:1291248000,E:1296777600,A:1299542400,B:1303862400,C:1307404800,p:1312243200,x:1316131200,J:1316131200,L:1319500800,N:1323734400,I:1328659200,O:1332892800,P:1337040000,Q:1340668800,R:1343692800,S:1348531200,T:1352246400,U:1357862400,V:1361404800,W:1364428800,X:1369094400,Y:1374105600,Z:1376956800,b:1389657600,c:1392940800,d:1397001600,e:1400544000,f:1405468800,g:1409011200,h:1412640000,i:1416268800,j:1421798400,k:1425513600,l:1429401600,m:1432080000,n:1437523200,o:1441152000,M:1444780800,q:1449014400,r:1453248000,s:1456963200,t:1460592000,u:1464134400,v:1469059200,w:1472601600,y:1500940800,AB:1512518400,LB:1516752000,bB:1520294400,GB:1523923200,a:1527552000,HB:null,IB:null,JB:null}},E:{A:{F:0,K:0.013107,H:0.004349,D:0.008738,G:0.039321,E:0.04369,A:0.069904,B:0.288354,C:0.004369,KB:0,DB:0.008692,MB:0.065535,NB:0.013107,OB:0.004283,PB:0.135439,QB:0.244664,z:1.38497,SB:0},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","KB","DB","F","K","MB","H","NB","D","OB","G","E","PB","A","QB","B","z","C","SB",""],E:"Safari",F:{KB:1205798400,DB:1226534400,F:1244419200,K:1275868800,MB:1311120000,H:1343174400,NB:1382400000,D:1382400000,OB:1410998400,G:1413417600,E:1443657600,PB:1458518400,A:1474329600,QB:1490572800,B:1505779200,z:1522281600,C:null,SB:null}},F:{A:{"0":0.008738,"7":0.034952,E:0.0082,B:0.016581,C:0.004369,J:0.00685,L:0.00685,N:0.00685,I:0.005014,O:0.006015,P:0.004879,Q:0.006597,R:0.006597,S:0.013434,T:0.006702,U:0.006015,V:0.005595,W:0.004393,X:0.004369,Y:0.004879,Z:0.004879,b:0.005152,c:0.005014,d:0.009758,e:0.004879,f:0.026214,g:0.004283,h:0.004367,i:0.004534,j:0.004367,k:0.004227,l:0.004418,m:0.008668,n:0.004227,o:0.004471,M:0.004417,q:0.008942,r:0.004369,s:0.008738,t:0.004369,u:0.004369,v:0.026214,w:0.843217,TB:0.00685,UB:0.008738,VB:0.008392,WB:0.004706,z:0.006229,BB:0.004879,YB:0.008786},B:"webkit",C:["","","","","","","","","","","","","","","E","TB","UB","VB","WB","B","z","BB","YB","C","7","J","L","N","I","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","b","c","d","e","f","g","h","i","j","k","l","m","n","o","M","q","r","s","t","u","v","w","","",""],E:"Opera",F:{"0":1438646400,"7":1352073600,E:1150761600,TB:1223424000,UB:1251763200,VB:1267488000,WB:1277942400,B:1292457600,z:1302566400,BB:1309219200,YB:1323129600,C:1323129600,J:1372723200,L:1377561600,N:1381104000,I:1386288000,O:1390867200,P:1393891200,Q:1399334400,R:1401753600,S:1405987200,T:1409616000,U:1413331200,V:1417132800,W:1422316800,X:1425945600,Y:1430179200,Z:1433808000,b:1442448000,c:1445904000,d:1449100800,e:1454371200,f:1457308800,g:1462320000,h:1465344000,i:1470096000,j:1474329600,k:1477267200,l:1481587200,m:1486425600,n:1490054400,o:1494374400,M:1498003200,q:1502236800,r:1506470400,s:1510099200,t:1515024000,u:1517961600,v:1521676800,w:1525910400},D:{"7":"o",E:"o",B:"o",C:"o",TB:"o",UB:"o",VB:"o",WB:"o",z:"o",BB:"o",YB:"o"}},G:{A:{G:0.0116667,C:0.0291667,DB:0.000972222,aB:0,EB:0.00194444,cB:0.0145833,dB:0.00777778,eB:0.0408333,fB:0.06125,gB:0.0466667,hB:0.279028,iB:0.30625,jB:0.701945,kB:1.57597,lB:6.63542},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","DB","aB","EB","cB","dB","eB","G","fB","gB","hB","iB","jB","kB","lB","C","",""],E:"iOS Safari",F:{DB:1270252800,aB:1283904000,EB:1299628800,cB:1331078400,dB:1359331200,eB:1394409600,G:1410912000,fB:1413763200,gB:1442361600,hB:1458518400,iB:1473724800,jB:1490572800,kB:1505779200,lB:1522281600,C:null}},H:{A:{mB:2.42564},B:"o",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","mB","","",""],E:"Opera Mini",F:{mB:1426464000}},I:{A:{CB:0,F:0,a:0,nB:0,oB:0,pB:0,qB:0.0683595,EB:0.156,rB:0.578426,sB:0.362831},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","nB","oB","pB","CB","F","qB","EB","rB","sB","a","","",""],E:"Android Browser",F:{nB:1256515200,oB:1274313600,pB:1291593600,CB:1298332800,F:1318896000,qB:1341792000,EB:1374624000,rB:1386547200,sB:1401667200,a:1494115200}},J:{A:{D:0.0090096,A:0.0360384},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","D","A","","",""],E:"Blackberry Browser",F:{D:1325376000,A:1359504000}},K:{A:{"7":0,A:0,B:0,C:0,M:0.0111391,z:0,BB:0},B:"o",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A","B","z","BB","C","7","M","","",""],E:"Opera Mobile",F:{"7":1349740800,A:1287100800,B:1300752000,z:1314835200,BB:1318291200,C:1330300800,M:1474588800},D:{M:"webkit"}},L:{A:{a:31.6889},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","a","","",""],E:"Chrome for Android",F:{a:1527724800}},M:{A:{y:0.16893},B:"moz",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","y","","",""],E:"Firefox for Android",F:{y:1525824000}},N:{A:{A:0.0232279,B:0.162595},B:"ms",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","A","B","","",""],E:"IE Mobile",F:{A:1340150400,B:1353456000}},O:{A:{tB:7.53991},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","tB","","",""],E:"UC Browser for Android",F:{tB:1471392000},D:{tB:"webkit"}},P:{A:{F:0.830777,K:0.166155,uB:1.12155,vB:0},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","F","K","uB","vB","","",""],E:"Samsung Internet",F:{F:1461024000,K:1481846400,uB:1509408000,vB:1528329600}},Q:{A:{wB:0},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","wB","","",""],E:"QQ Browser",F:{wB:1483228800}},R:{A:{xB:0},B:"webkit",C:["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","xB","","",""],E:"Baidu Browser",F:{xB:1491004800}}}; | |
},{}],7:[function(require,module,exports){ | |
module.exports={"0":"31","1":"54","2":"55","3":"56","4":"57","5":"58","6":"59","7":"12.1","8":"61","9":"62",A:"10",B:"11",C:"12",D:"7",E:"9",F:"4",G:"8",H:"6",I:"18",J:"15",K:"5",L:"16",M:"46",N:"17",O:"19",P:"20",Q:"21",R:"22",S:"23",T:"24",U:"25",V:"26",W:"27",X:"28",Y:"29",Z:"30",a:"67",b:"32",c:"33",d:"34",e:"35",f:"36",g:"37",h:"38",i:"39",j:"40",k:"41",l:"42",m:"43",n:"44",o:"45",p:"13",q:"47",r:"48",s:"49",t:"50",u:"51",v:"52",w:"53",x:"14",y:"60",z:"11.1",AB:"63",BB:"11.5",CB:"3",DB:"3.2",EB:"4.2-4.3",FB:"5.5",GB:"66",HB:"68",IB:"69",JB:"70",KB:"3.1",LB:"64",MB:"5.1",NB:"6.1",OB:"7.1",PB:"9.1",QB:"10.1",RB:"3.6",SB:"TP",TB:"9.5-9.6",UB:"10.0-10.1",VB:"10.5",WB:"10.6",XB:"3.5",YB:"11.6",ZB:"2",aB:"4.0-4.1",bB:"65",cB:"5.0-5.1",dB:"6.0-6.1",eB:"7.0-7.1",fB:"8.1-8.4",gB:"9.0-9.2",hB:"9.3",iB:"10.0-10.2",jB:"10.3",kB:"11.0-11.2",lB:"11.3-11.4",mB:"all",nB:"2.1",oB:"2.2",pB:"2.3",qB:"4.1",rB:"4.4",sB:"4.4.3-4.4.4",tB:"11.8",uB:"6.2",vB:"7.2",wB:"1.2",xB:"7.12"}; | |
},{}],8:[function(require,module,exports){ | |
module.exports={A:"ie",B:"edge",C:"firefox",D:"chrome",E:"safari",F:"opera",G:"ios_saf",H:"op_mini",I:"android",J:"bb",K:"op_mob",L:"and_chr",M:"and_ff",N:"ie_mob",O:"and_uc",P:"samsung",Q:"and_qq",R:"baidu"}; | |
},{}],9:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.agents = undefined; | |
var _browsers = require('./browsers'); | |
var _browserVersions = require('./browserVersions'); | |
var agentsData = require('../../data/agents'); | |
function unpackBrowserVersions(versionsData) { | |
return Object.keys(versionsData).reduce(function (usage, version) { | |
usage[_browserVersions.browserVersions[version]] = versionsData[version]; | |
return usage; | |
}, {}); | |
} | |
var agents = exports.agents = Object.keys(agentsData).reduce(function (map, key) { | |
var versionsData = agentsData[key]; | |
map[_browsers.browsers[key]] = Object.keys(versionsData).reduce(function (data, entry) { | |
if (entry === 'A') { | |
data.usage_global = unpackBrowserVersions(versionsData[entry]); | |
} else if (entry === 'C') { | |
data.versions = versionsData[entry].reduce(function (list, version) { | |
if (version === '') { | |
list.push(null); | |
} else { | |
list.push(_browserVersions.browserVersions[version]); | |
} | |
return list; | |
}, []); | |
} else if (entry === 'D') { | |
data.prefix_exceptions = unpackBrowserVersions(versionsData[entry]); | |
} else if (entry === 'E') { | |
data.browser = versionsData[entry]; | |
} else if (entry === 'F') { | |
data.release_date = Object.keys(versionsData[entry]).reduce(function (map, key) { | |
map[_browserVersions.browserVersions[key]] = versionsData[entry][key]; | |
return map; | |
}, {}); | |
} else { | |
// entry is B | |
data.prefix = versionsData[entry]; | |
} | |
return data; | |
}, {}); | |
return map; | |
}, {}); | |
},{"../../data/agents":6,"./browserVersions":10,"./browsers":11}],10:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var browserVersions = exports.browserVersions = require('../../data/browserVersions'); | |
},{"../../data/browserVersions":7}],11:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var browsers = exports.browsers = require('../../data/browsers'); | |
},{"../../data/browsers":8}],12:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _container = require('./container'); | |
var _container2 = _interopRequireDefault(_container); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
/** | |
* Represents an at-rule. | |
* | |
* If it’s followed in the CSS by a {} block, this node will have | |
* a nodes property representing its children. | |
* | |
* @extends Container | |
* | |
* @example | |
* const root = postcss.parse('@charset "UTF-8"; @media print {}'); | |
* | |
* const charset = root.first; | |
* charset.type //=> 'atrule' | |
* charset.nodes //=> undefined | |
* | |
* const media = root.last; | |
* media.nodes //=> [] | |
*/ | |
var AtRule = function (_Container) { | |
_inherits(AtRule, _Container); | |
function AtRule(defaults) { | |
_classCallCheck(this, AtRule); | |
var _this = _possibleConstructorReturn(this, _Container.call(this, defaults)); | |
_this.type = 'atrule'; | |
return _this; | |
} | |
AtRule.prototype.append = function append() { | |
var _Container$prototype$; | |
if (!this.nodes) this.nodes = []; | |
for (var _len = arguments.length, children = Array(_len), _key = 0; _key < _len; _key++) { | |
children[_key] = arguments[_key]; | |
} | |
return (_Container$prototype$ = _Container.prototype.append).call.apply(_Container$prototype$, [this].concat(children)); | |
}; | |
AtRule.prototype.prepend = function prepend() { | |
var _Container$prototype$2; | |
if (!this.nodes) this.nodes = []; | |
for (var _len2 = arguments.length, children = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | |
children[_key2] = arguments[_key2]; | |
} | |
return (_Container$prototype$2 = _Container.prototype.prepend).call.apply(_Container$prototype$2, [this].concat(children)); | |
}; | |
/** | |
* @memberof AtRule# | |
* @member {string} name - the at-rule’s name immediately follows the `@` | |
* | |
* @example | |
* const root = postcss.parse('@media print {}'); | |
* media.name //=> 'media' | |
* const media = root.first; | |
*/ | |
/** | |
* @memberof AtRule# | |
* @member {string} params - the at-rule’s parameters, the values | |
* that follow the at-rule’s name but precede | |
* any {} block | |
* | |
* @example | |
* const root = postcss.parse('@media print, screen {}'); | |
* const media = root.first; | |
* media.params //=> 'print, screen' | |
*/ | |
/** | |
* @memberof AtRule# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `before`: the space symbols before the node. It also stores `*` | |
* and `_` symbols before the declaration (IE hack). | |
* * `after`: the space symbols after the last child of the node | |
* to the end of the node. | |
* * `between`: the symbols between the property and value | |
* for declarations, selector and `{` for rules, or last parameter | |
* and `{` for at-rules. | |
* * `semicolon`: contains true if the last child has | |
* an (optional) semicolon. | |
* * `afterName`: the space between the at-rule name and its parameters. | |
* | |
* PostCSS cleans at-rule parameters from comments and extra spaces, | |
* but it stores origin content in raws properties. | |
* As such, if you don’t change a declaration’s value, | |
* PostCSS will use the raw value with comments. | |
* | |
* @example | |
* const root = postcss.parse(' @media\nprint {\n}') | |
* root.first.first.raws //=> { before: ' ', | |
* // between: ' ', | |
* // afterName: '\n', | |
* // after: '\n' } | |
*/ | |
return AtRule; | |
}(_container2.default); | |
exports.default = AtRule; | |
module.exports = exports['default']; | |
},{"./container":14}],13:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _node = require('./node'); | |
var _node2 = _interopRequireDefault(_node); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
/** | |
* Represents a comment between declarations or statements (rule and at-rules). | |
* | |
* Comments inside selectors, at-rule parameters, or declaration values | |
* will be stored in the `raws` properties explained above. | |
* | |
* @extends Node | |
*/ | |
var Comment = function (_Node) { | |
_inherits(Comment, _Node); | |
function Comment(defaults) { | |
_classCallCheck(this, Comment); | |
var _this = _possibleConstructorReturn(this, _Node.call(this, defaults)); | |
_this.type = 'comment'; | |
return _this; | |
} | |
/** | |
* @memberof Comment# | |
* @member {string} text - the comment’s text | |
*/ | |
/** | |
* @memberof Comment# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `before`: the space symbols before the node. | |
* * `left`: the space symbols between `/*` and the comment’s text. | |
* * `right`: the space symbols between the comment’s text. | |
*/ | |
return Comment; | |
}(_node2.default); | |
exports.default = Comment; | |
module.exports = exports['default']; | |
},{"./node":21}],14:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _declaration = require('./declaration'); | |
var _declaration2 = _interopRequireDefault(_declaration); | |
var _comment = require('./comment'); | |
var _comment2 = _interopRequireDefault(_comment); | |
var _node = require('./node'); | |
var _node2 = _interopRequireDefault(_node); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
function cleanSource(nodes) { | |
return nodes.map(function (i) { | |
if (i.nodes) i.nodes = cleanSource(i.nodes); | |
delete i.source; | |
return i; | |
}); | |
} | |
/** | |
* The {@link Root}, {@link AtRule}, and {@link Rule} container nodes | |
* inherit some common methods to help work with their children. | |
* | |
* Note that all containers can store any content. If you write a rule inside | |
* a rule, PostCSS will parse it. | |
* | |
* @extends Node | |
* @abstract | |
*/ | |
var Container = function (_Node) { | |
_inherits(Container, _Node); | |
function Container() { | |
_classCallCheck(this, Container); | |
return _possibleConstructorReturn(this, _Node.apply(this, arguments)); | |
} | |
Container.prototype.push = function push(child) { | |
child.parent = this; | |
this.nodes.push(child); | |
return this; | |
}; | |
/** | |
* Iterates through the container’s immediate children, | |
* calling `callback` for each child. | |
* | |
* Returning `false` in the callback will break iteration. | |
* | |
* This method only iterates through the container’s immediate children. | |
* If you need to recursively iterate through all the container’s descendant | |
* nodes, use {@link Container#walk}. | |
* | |
* Unlike the for `{}`-cycle or `Array#forEach` this iterator is safe | |
* if you are mutating the array of child nodes during iteration. | |
* PostCSS will adjust the current index to match the mutations. | |
* | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* const root = postcss.parse('a { color: black; z-index: 1 }'); | |
* const rule = root.first; | |
* | |
* for ( let decl of rule.nodes ) { | |
* decl.cloneBefore({ prop: '-webkit-' + decl.prop }); | |
* // Cycle will be infinite, because cloneBefore moves the current node | |
* // to the next index | |
* } | |
* | |
* rule.each(decl => { | |
* decl.cloneBefore({ prop: '-webkit-' + decl.prop }); | |
* // Will be executed only for color and z-index | |
* }); | |
*/ | |
Container.prototype.each = function each(callback) { | |
if (!this.lastEach) this.lastEach = 0; | |
if (!this.indexes) this.indexes = {}; | |
this.lastEach += 1; | |
var id = this.lastEach; | |
this.indexes[id] = 0; | |
if (!this.nodes) return undefined; | |
var index = void 0, | |
result = void 0; | |
while (this.indexes[id] < this.nodes.length) { | |
index = this.indexes[id]; | |
result = callback(this.nodes[index], index); | |
if (result === false) break; | |
this.indexes[id] += 1; | |
} | |
delete this.indexes[id]; | |
return result; | |
}; | |
/** | |
* Traverses the container’s descendant nodes, calling callback | |
* for each node. | |
* | |
* Like container.each(), this method is safe to use | |
* if you are mutating arrays during iteration. | |
* | |
* If you only need to iterate through the container’s immediate children, | |
* use {@link Container#each}. | |
* | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* root.walk(node => { | |
* // Traverses all descendant nodes. | |
* }); | |
*/ | |
Container.prototype.walk = function walk(callback) { | |
return this.each(function (child, i) { | |
var result = callback(child, i); | |
if (result !== false && child.walk) { | |
result = child.walk(callback); | |
} | |
return result; | |
}); | |
}; | |
/** | |
* Traverses the container’s descendant nodes, calling callback | |
* for each declaration node. | |
* | |
* If you pass a filter, iteration will only happen over declarations | |
* with matching properties. | |
* | |
* Like {@link Container#each}, this method is safe | |
* to use if you are mutating arrays during iteration. | |
* | |
* @param {string|RegExp} [prop] - string or regular expression | |
* to filter declarations by property name | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* root.walkDecls(decl => { | |
* checkPropertySupport(decl.prop); | |
* }); | |
* | |
* root.walkDecls('border-radius', decl => { | |
* decl.remove(); | |
* }); | |
* | |
* root.walkDecls(/^background/, decl => { | |
* decl.value = takeFirstColorFromGradient(decl.value); | |
* }); | |
*/ | |
Container.prototype.walkDecls = function walkDecls(prop, callback) { | |
if (!callback) { | |
callback = prop; | |
return this.walk(function (child, i) { | |
if (child.type === 'decl') { | |
return callback(child, i); | |
} | |
}); | |
} else if (prop instanceof RegExp) { | |
return this.walk(function (child, i) { | |
if (child.type === 'decl' && prop.test(child.prop)) { | |
return callback(child, i); | |
} | |
}); | |
} else { | |
return this.walk(function (child, i) { | |
if (child.type === 'decl' && child.prop === prop) { | |
return callback(child, i); | |
} | |
}); | |
} | |
}; | |
/** | |
* Traverses the container’s descendant nodes, calling callback | |
* for each rule node. | |
* | |
* If you pass a filter, iteration will only happen over rules | |
* with matching selectors. | |
* | |
* Like {@link Container#each}, this method is safe | |
* to use if you are mutating arrays during iteration. | |
* | |
* @param {string|RegExp} [selector] - string or regular expression | |
* to filter rules by selector | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* const selectors = []; | |
* root.walkRules(rule => { | |
* selectors.push(rule.selector); | |
* }); | |
* console.log(`Your CSS uses ${selectors.length} selectors`); | |
*/ | |
Container.prototype.walkRules = function walkRules(selector, callback) { | |
if (!callback) { | |
callback = selector; | |
return this.walk(function (child, i) { | |
if (child.type === 'rule') { | |
return callback(child, i); | |
} | |
}); | |
} else if (selector instanceof RegExp) { | |
return this.walk(function (child, i) { | |
if (child.type === 'rule' && selector.test(child.selector)) { | |
return callback(child, i); | |
} | |
}); | |
} else { | |
return this.walk(function (child, i) { | |
if (child.type === 'rule' && child.selector === selector) { | |
return callback(child, i); | |
} | |
}); | |
} | |
}; | |
/** | |
* Traverses the container’s descendant nodes, calling callback | |
* for each at-rule node. | |
* | |
* If you pass a filter, iteration will only happen over at-rules | |
* that have matching names. | |
* | |
* Like {@link Container#each}, this method is safe | |
* to use if you are mutating arrays during iteration. | |
* | |
* @param {string|RegExp} [name] - string or regular expression | |
* to filter at-rules by name | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* root.walkAtRules(rule => { | |
* if ( isOld(rule.name) ) rule.remove(); | |
* }); | |
* | |
* let first = false; | |
* root.walkAtRules('charset', rule => { | |
* if ( !first ) { | |
* first = true; | |
* } else { | |
* rule.remove(); | |
* } | |
* }); | |
*/ | |
Container.prototype.walkAtRules = function walkAtRules(name, callback) { | |
if (!callback) { | |
callback = name; | |
return this.walk(function (child, i) { | |
if (child.type === 'atrule') { | |
return callback(child, i); | |
} | |
}); | |
} else if (name instanceof RegExp) { | |
return this.walk(function (child, i) { | |
if (child.type === 'atrule' && name.test(child.name)) { | |
return callback(child, i); | |
} | |
}); | |
} else { | |
return this.walk(function (child, i) { | |
if (child.type === 'atrule' && child.name === name) { | |
return callback(child, i); | |
} | |
}); | |
} | |
}; | |
/** | |
* Traverses the container’s descendant nodes, calling callback | |
* for each comment node. | |
* | |
* Like {@link Container#each}, this method is safe | |
* to use if you are mutating arrays during iteration. | |
* | |
* @param {childIterator} callback - iterator receives each node and index | |
* | |
* @return {false|undefined} returns `false` if iteration was broke | |
* | |
* @example | |
* root.walkComments(comment => { | |
* comment.remove(); | |
* }); | |
*/ | |
Container.prototype.walkComments = function walkComments(callback) { | |
return this.walk(function (child, i) { | |
if (child.type === 'comment') { | |
return callback(child, i); | |
} | |
}); | |
}; | |
/** | |
* Inserts new nodes to the end of the container. | |
* | |
* @param {...(Node|object|string|Node[])} children - new nodes | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* const decl1 = postcss.decl({ prop: 'color', value: 'black' }); | |
* const decl2 = postcss.decl({ prop: 'background-color', value: 'white' }); | |
* rule.append(decl1, decl2); | |
* | |
* root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule | |
* root.append({ selector: 'a' }); // rule | |
* rule.append({ prop: 'color', value: 'black' }); // declaration | |
* rule.append({ text: 'Comment' }) // comment | |
* | |
* root.append('a {}'); | |
* root.first.append('color: black; z-index: 1'); | |
*/ | |
Container.prototype.append = function append() { | |
for (var _len = arguments.length, children = Array(_len), _key = 0; _key < _len; _key++) { | |
children[_key] = arguments[_key]; | |
} | |
for (var _iterator = children, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var child = _ref; | |
var nodes = this.normalize(child, this.last); | |
for (var _iterator2 = nodes, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | |
var _ref2; | |
if (_isArray2) { | |
if (_i2 >= _iterator2.length) break; | |
_ref2 = _iterator2[_i2++]; | |
} else { | |
_i2 = _iterator2.next(); | |
if (_i2.done) break; | |
_ref2 = _i2.value; | |
} | |
var node = _ref2; | |
this.nodes.push(node); | |
} | |
} | |
return this; | |
}; | |
/** | |
* Inserts new nodes to the start of the container. | |
* | |
* @param {...(Node|object|string|Node[])} children - new nodes | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* const decl1 = postcss.decl({ prop: 'color', value: 'black' }); | |
* const decl2 = postcss.decl({ prop: 'background-color', value: 'white' }); | |
* rule.prepend(decl1, decl2); | |
* | |
* root.append({ name: 'charset', params: '"UTF-8"' }); // at-rule | |
* root.append({ selector: 'a' }); // rule | |
* rule.append({ prop: 'color', value: 'black' }); // declaration | |
* rule.append({ text: 'Comment' }) // comment | |
* | |
* root.append('a {}'); | |
* root.first.append('color: black; z-index: 1'); | |
*/ | |
Container.prototype.prepend = function prepend() { | |
for (var _len2 = arguments.length, children = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | |
children[_key2] = arguments[_key2]; | |
} | |
children = children.reverse(); | |
for (var _iterator3 = children, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | |
var _ref3; | |
if (_isArray3) { | |
if (_i3 >= _iterator3.length) break; | |
_ref3 = _iterator3[_i3++]; | |
} else { | |
_i3 = _iterator3.next(); | |
if (_i3.done) break; | |
_ref3 = _i3.value; | |
} | |
var child = _ref3; | |
var nodes = this.normalize(child, this.first, 'prepend').reverse(); | |
for (var _iterator4 = nodes, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | |
var _ref4; | |
if (_isArray4) { | |
if (_i4 >= _iterator4.length) break; | |
_ref4 = _iterator4[_i4++]; | |
} else { | |
_i4 = _iterator4.next(); | |
if (_i4.done) break; | |
_ref4 = _i4.value; | |
} | |
var node = _ref4; | |
this.nodes.unshift(node); | |
}for (var id in this.indexes) { | |
this.indexes[id] = this.indexes[id] + nodes.length; | |
} | |
} | |
return this; | |
}; | |
Container.prototype.cleanRaws = function cleanRaws(keepBetween) { | |
_Node.prototype.cleanRaws.call(this, keepBetween); | |
if (this.nodes) { | |
for (var _iterator5 = this.nodes, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { | |
var _ref5; | |
if (_isArray5) { | |
if (_i5 >= _iterator5.length) break; | |
_ref5 = _iterator5[_i5++]; | |
} else { | |
_i5 = _iterator5.next(); | |
if (_i5.done) break; | |
_ref5 = _i5.value; | |
} | |
var node = _ref5; | |
node.cleanRaws(keepBetween); | |
} | |
} | |
}; | |
/** | |
* Insert new node before old node within the container. | |
* | |
* @param {Node|number} exist - child or child’s index. | |
* @param {Node|object|string|Node[]} add - new node | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* rule.insertBefore(decl, decl.clone({ prop: '-webkit-' + decl.prop })); | |
*/ | |
Container.prototype.insertBefore = function insertBefore(exist, add) { | |
exist = this.index(exist); | |
var type = exist === 0 ? 'prepend' : false; | |
var nodes = this.normalize(add, this.nodes[exist], type).reverse(); | |
for (var _iterator6 = nodes, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { | |
var _ref6; | |
if (_isArray6) { | |
if (_i6 >= _iterator6.length) break; | |
_ref6 = _iterator6[_i6++]; | |
} else { | |
_i6 = _iterator6.next(); | |
if (_i6.done) break; | |
_ref6 = _i6.value; | |
} | |
var node = _ref6; | |
this.nodes.splice(exist, 0, node); | |
}var index = void 0; | |
for (var id in this.indexes) { | |
index = this.indexes[id]; | |
if (exist <= index) { | |
this.indexes[id] = index + nodes.length; | |
} | |
} | |
return this; | |
}; | |
/** | |
* Insert new node after old node within the container. | |
* | |
* @param {Node|number} exist - child or child’s index | |
* @param {Node|object|string|Node[]} add - new node | |
* | |
* @return {Node} this node for methods chain | |
*/ | |
Container.prototype.insertAfter = function insertAfter(exist, add) { | |
exist = this.index(exist); | |
var nodes = this.normalize(add, this.nodes[exist]).reverse(); | |
for (var _iterator7 = nodes, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { | |
var _ref7; | |
if (_isArray7) { | |
if (_i7 >= _iterator7.length) break; | |
_ref7 = _iterator7[_i7++]; | |
} else { | |
_i7 = _iterator7.next(); | |
if (_i7.done) break; | |
_ref7 = _i7.value; | |
} | |
var node = _ref7; | |
this.nodes.splice(exist + 1, 0, node); | |
}var index = void 0; | |
for (var id in this.indexes) { | |
index = this.indexes[id]; | |
if (exist < index) { | |
this.indexes[id] = index + nodes.length; | |
} | |
} | |
return this; | |
}; | |
/** | |
* Removes node from the container and cleans the parent properties | |
* from the node and its children. | |
* | |
* @param {Node|number} child - child or child’s index | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* rule.nodes.length //=> 5 | |
* rule.removeChild(decl); | |
* rule.nodes.length //=> 4 | |
* decl.parent //=> undefined | |
*/ | |
Container.prototype.removeChild = function removeChild(child) { | |
child = this.index(child); | |
this.nodes[child].parent = undefined; | |
this.nodes.splice(child, 1); | |
var index = void 0; | |
for (var id in this.indexes) { | |
index = this.indexes[id]; | |
if (index >= child) { | |
this.indexes[id] = index - 1; | |
} | |
} | |
return this; | |
}; | |
/** | |
* Removes all children from the container | |
* and cleans their parent properties. | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* rule.removeAll(); | |
* rule.nodes.length //=> 0 | |
*/ | |
Container.prototype.removeAll = function removeAll() { | |
for (var _iterator8 = this.nodes, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { | |
var _ref8; | |
if (_isArray8) { | |
if (_i8 >= _iterator8.length) break; | |
_ref8 = _iterator8[_i8++]; | |
} else { | |
_i8 = _iterator8.next(); | |
if (_i8.done) break; | |
_ref8 = _i8.value; | |
} | |
var node = _ref8; | |
node.parent = undefined; | |
}this.nodes = []; | |
return this; | |
}; | |
/** | |
* Passes all declaration values within the container that match pattern | |
* through callback, replacing those values with the returned result | |
* of callback. | |
* | |
* This method is useful if you are using a custom unit or function | |
* and need to iterate through all values. | |
* | |
* @param {string|RegExp} pattern - replace pattern | |
* @param {object} opts - options to speed up the search | |
* @param {string|string[]} opts.props - an array of property names | |
* @param {string} opts.fast - string that’s used | |
* to narrow down values and speed up | |
the regexp search | |
* @param {function|string} callback - string to replace pattern | |
* or callback that returns a new | |
* value. | |
* The callback will receive | |
* the same arguments as those | |
* passed to a function parameter | |
* of `String#replace`. | |
* | |
* @return {Node} this node for methods chain | |
* | |
* @example | |
* root.replaceValues(/\d+rem/, { fast: 'rem' }, string => { | |
* return 15 * parseInt(string) + 'px'; | |
* }); | |
*/ | |
Container.prototype.replaceValues = function replaceValues(pattern, opts, callback) { | |
if (!callback) { | |
callback = opts; | |
opts = {}; | |
} | |
this.walkDecls(function (decl) { | |
if (opts.props && opts.props.indexOf(decl.prop) === -1) return; | |
if (opts.fast && decl.value.indexOf(opts.fast) === -1) return; | |
decl.value = decl.value.replace(pattern, callback); | |
}); | |
return this; | |
}; | |
/** | |
* Returns `true` if callback returns `true` | |
* for all of the container’s children. | |
* | |
* @param {childCondition} condition - iterator returns true or false. | |
* | |
* @return {boolean} is every child pass condition | |
* | |
* @example | |
* const noPrefixes = rule.every(i => i.prop[0] !== '-'); | |
*/ | |
Container.prototype.every = function every(condition) { | |
return this.nodes.every(condition); | |
}; | |
/** | |
* Returns `true` if callback returns `true` for (at least) one | |
* of the container’s children. | |
* | |
* @param {childCondition} condition - iterator returns true or false. | |
* | |
* @return {boolean} is some child pass condition | |
* | |
* @example | |
* const hasPrefix = rule.some(i => i.prop[0] === '-'); | |
*/ | |
Container.prototype.some = function some(condition) { | |
return this.nodes.some(condition); | |
}; | |
/** | |
* Returns a `child`’s index within the {@link Container#nodes} array. | |
* | |
* @param {Node} child - child of the current container. | |
* | |
* @return {number} child index | |
* | |
* @example | |
* rule.index( rule.nodes[2] ) //=> 2 | |
*/ | |
Container.prototype.index = function index(child) { | |
if (typeof child === 'number') { | |
return child; | |
} else { | |
return this.nodes.indexOf(child); | |
} | |
}; | |
/** | |
* The container’s first child. | |
* | |
* @type {Node} | |
* | |
* @example | |
* rule.first == rules.nodes[0]; | |
*/ | |
Container.prototype.normalize = function normalize(nodes, sample) { | |
var _this2 = this; | |
if (typeof nodes === 'string') { | |
var parse = require('./parse'); | |
nodes = cleanSource(parse(nodes).nodes); | |
} else if (Array.isArray(nodes)) { | |
nodes = nodes.slice(0); | |
for (var _iterator9 = nodes, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { | |
var _ref9; | |
if (_isArray9) { | |
if (_i9 >= _iterator9.length) break; | |
_ref9 = _iterator9[_i9++]; | |
} else { | |
_i9 = _iterator9.next(); | |
if (_i9.done) break; | |
_ref9 = _i9.value; | |
} | |
var i = _ref9; | |
if (i.parent) i.parent.removeChild(i, 'ignore'); | |
} | |
} else if (nodes.type === 'root') { | |
nodes = nodes.nodes.slice(0); | |
for (var _iterator10 = nodes, _isArray10 = Array.isArray(_iterator10), _i11 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { | |
var _ref10; | |
if (_isArray10) { | |
if (_i11 >= _iterator10.length) break; | |
_ref10 = _iterator10[_i11++]; | |
} else { | |
_i11 = _iterator10.next(); | |
if (_i11.done) break; | |
_ref10 = _i11.value; | |
} | |
var _i10 = _ref10; | |
if (_i10.parent) _i10.parent.removeChild(_i10, 'ignore'); | |
} | |
} else if (nodes.type) { | |
nodes = [nodes]; | |
} else if (nodes.prop) { | |
if (typeof nodes.value === 'undefined') { | |
throw new Error('Value field is missed in node creation'); | |
} else if (typeof nodes.value !== 'string') { | |
nodes.value = String(nodes.value); | |
} | |
nodes = [new _declaration2.default(nodes)]; | |
} else if (nodes.selector) { | |
var Rule = require('./rule'); | |
nodes = [new Rule(nodes)]; | |
} else if (nodes.name) { | |
var AtRule = require('./at-rule'); | |
nodes = [new AtRule(nodes)]; | |
} else if (nodes.text) { | |
nodes = [new _comment2.default(nodes)]; | |
} else { | |
throw new Error('Unknown node type in node creation'); | |
} | |
var processed = nodes.map(function (i) { | |
if (typeof i.before !== 'function') i = _this2.rebuild(i); | |
if (i.parent) i.parent.removeChild(i); | |
if (typeof i.raws.before === 'undefined') { | |
if (sample && typeof sample.raws.before !== 'undefined') { | |
i.raws.before = sample.raws.before.replace(/[^\s]/g, ''); | |
} | |
} | |
i.parent = _this2; | |
return i; | |
}); | |
return processed; | |
}; | |
Container.prototype.rebuild = function rebuild(node, parent) { | |
var _this3 = this; | |
var fix = void 0; | |
if (node.type === 'root') { | |
var Root = require('./root'); | |
fix = new Root(); | |
} else if (node.type === 'atrule') { | |
var AtRule = require('./at-rule'); | |
fix = new AtRule(); | |
} else if (node.type === 'rule') { | |
var Rule = require('./rule'); | |
fix = new Rule(); | |
} else if (node.type === 'decl') { | |
fix = new _declaration2.default(); | |
} else if (node.type === 'comment') { | |
fix = new _comment2.default(); | |
} | |
for (var i in node) { | |
if (i === 'nodes') { | |
fix.nodes = node.nodes.map(function (j) { | |
return _this3.rebuild(j, fix); | |
}); | |
} else if (i === 'parent' && parent) { | |
fix.parent = parent; | |
} else if (node.hasOwnProperty(i)) { | |
fix[i] = node[i]; | |
} | |
} | |
return fix; | |
}; | |
/** | |
* @memberof Container# | |
* @member {Node[]} nodes - an array containing the container’s children | |
* | |
* @example | |
* const root = postcss.parse('a { color: black }'); | |
* root.nodes.length //=> 1 | |
* root.nodes[0].selector //=> 'a' | |
* root.nodes[0].nodes[0].prop //=> 'color' | |
*/ | |
_createClass(Container, [{ | |
key: 'first', | |
get: function get() { | |
if (!this.nodes) return undefined; | |
return this.nodes[0]; | |
} | |
/** | |
* The container’s last child. | |
* | |
* @type {Node} | |
* | |
* @example | |
* rule.last == rule.nodes[rule.nodes.length - 1]; | |
*/ | |
}, { | |
key: 'last', | |
get: function get() { | |
if (!this.nodes) return undefined; | |
return this.nodes[this.nodes.length - 1]; | |
} | |
}]); | |
return Container; | |
}(_node2.default); | |
exports.default = Container; | |
/** | |
* @callback childCondition | |
* @param {Node} node - container child | |
* @param {number} index - child index | |
* @param {Node[]} nodes - all container children | |
* @return {boolean} | |
*/ | |
/** | |
* @callback childIterator | |
* @param {Node} node - container child | |
* @param {number} index - child index | |
* @return {false|undefined} returning `false` will break iteration | |
*/ | |
module.exports = exports['default']; | |
},{"./at-rule":12,"./comment":13,"./declaration":16,"./node":21,"./parse":22,"./root":28,"./rule":29}],15:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _supportsColor = require('supports-color'); | |
var _supportsColor2 = _interopRequireDefault(_supportsColor); | |
var _chalk = require('chalk'); | |
var _chalk2 = _interopRequireDefault(_chalk); | |
var _terminalHighlight = require('./terminal-highlight'); | |
var _terminalHighlight2 = _interopRequireDefault(_terminalHighlight); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
/** | |
* The CSS parser throws this error for broken CSS. | |
* | |
* Custom parsers can throw this error for broken custom syntax using | |
* the {@link Node#error} method. | |
* | |
* PostCSS will use the input source map to detect the original error location. | |
* If you wrote a Sass file, compiled it to CSS and then parsed it with PostCSS, | |
* PostCSS will show the original position in the Sass file. | |
* | |
* If you need the position in the PostCSS input | |
* (e.g., to debug the previous compiler), use `error.input.file`. | |
* | |
* @example | |
* // Catching and checking syntax error | |
* try { | |
* postcss.parse('a{') | |
* } catch (error) { | |
* if ( error.name === 'CssSyntaxError' ) { | |
* error //=> CssSyntaxError | |
* } | |
* } | |
* | |
* @example | |
* // Raising error from plugin | |
* throw node.error('Unknown variable', { plugin: 'postcss-vars' }); | |
*/ | |
var CssSyntaxError = function () { | |
/** | |
* @param {string} message - error message | |
* @param {number} [line] - source line of the error | |
* @param {number} [column] - source column of the error | |
* @param {string} [source] - source code of the broken file | |
* @param {string} [file] - absolute path to the broken file | |
* @param {string} [plugin] - PostCSS plugin name, if error came from plugin | |
*/ | |
function CssSyntaxError(message, line, column, source, file, plugin) { | |
_classCallCheck(this, CssSyntaxError); | |
/** | |
* @member {string} - Always equal to `'CssSyntaxError'`. You should | |
* always check error type | |
* by `error.name === 'CssSyntaxError'` instead of | |
* `error instanceof CssSyntaxError`, because | |
* npm could have several PostCSS versions. | |
* | |
* @example | |
* if ( error.name === 'CssSyntaxError' ) { | |
* error //=> CssSyntaxError | |
* } | |
*/ | |
this.name = 'CssSyntaxError'; | |
/** | |
* @member {string} - Error message. | |
* | |
* @example | |
* error.message //=> 'Unclosed block' | |
*/ | |
this.reason = message; | |
if (file) { | |
/** | |
* @member {string} - Absolute path to the broken file. | |
* | |
* @example | |
* error.file //=> 'a.sass' | |
* error.input.file //=> 'a.css' | |
*/ | |
this.file = file; | |
} | |
if (source) { | |
/** | |
* @member {string} - Source code of the broken file. | |
* | |
* @example | |
* error.source //=> 'a { b {} }' | |
* error.input.column //=> 'a b { }' | |
*/ | |
this.source = source; | |
} | |
if (plugin) { | |
/** | |
* @member {string} - Plugin name, if error came from plugin. | |
* | |
* @example | |
* error.plugin //=> 'postcss-vars' | |
*/ | |
this.plugin = plugin; | |
} | |
if (typeof line !== 'undefined' && typeof column !== 'undefined') { | |
/** | |
* @member {number} - Source line of the error. | |
* | |
* @example | |
* error.line //=> 2 | |
* error.input.line //=> 4 | |
*/ | |
this.line = line; | |
/** | |
* @member {number} - Source column of the error. | |
* | |
* @example | |
* error.column //=> 1 | |
* error.input.column //=> 4 | |
*/ | |
this.column = column; | |
} | |
this.setMessage(); | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, CssSyntaxError); | |
} | |
} | |
CssSyntaxError.prototype.setMessage = function setMessage() { | |
/** | |
* @member {string} - Full error text in the GNU error format | |
* with plugin, file, line and column. | |
* | |
* @example | |
* error.message //=> 'a.css:1:1: Unclosed block' | |
*/ | |
this.message = this.plugin ? this.plugin + ': ' : ''; | |
this.message += this.file ? this.file : '<css input>'; | |
if (typeof this.line !== 'undefined') { | |
this.message += ':' + this.line + ':' + this.column; | |
} | |
this.message += ': ' + this.reason; | |
}; | |
/** | |
* Returns a few lines of CSS source that caused the error. | |
* | |
* If the CSS has an input source map without `sourceContent`, | |
* this method will return an empty string. | |
* | |
* @param {boolean} [color] whether arrow will be colored red by terminal | |
* color codes. By default, PostCSS will detect | |
* color support by `process.stdout.isTTY` | |
* and `process.env.NODE_DISABLE_COLORS`. | |
* | |
* @example | |
* error.showSourceCode() //=> " 4 | } | |
* // 5 | a { | |
* // > 6 | bad | |
* // | ^ | |
* // 7 | } | |
* // 8 | b {" | |
* | |
* @return {string} few lines of CSS source that caused the error | |
*/ | |
CssSyntaxError.prototype.showSourceCode = function showSourceCode(color) { | |
var _this = this; | |
if (!this.source) return ''; | |
var css = this.source; | |
if (typeof color === 'undefined') color = _supportsColor2.default.stdout; | |
if (color) css = (0, _terminalHighlight2.default)(css); | |
var lines = css.split(/\r?\n/); | |
var start = Math.max(this.line - 3, 0); | |
var end = Math.min(this.line + 2, lines.length); | |
var maxWidth = String(end).length; | |
function mark(text) { | |
if (color && _chalk2.default.red) { | |
return _chalk2.default.red.bold(text); | |
} else { | |
return text; | |
} | |
} | |
function aside(text) { | |
if (color && _chalk2.default.gray) { | |
return _chalk2.default.gray(text); | |
} else { | |
return text; | |
} | |
} | |
return lines.slice(start, end).map(function (line, index) { | |
var number = start + 1 + index; | |
var gutter = ' ' + (' ' + number).slice(-maxWidth) + ' | '; | |
if (number === _this.line) { | |
var spacing = aside(gutter.replace(/\d/g, ' ')) + line.slice(0, _this.column - 1).replace(/[^\t]/g, ' '); | |
return mark('>') + aside(gutter) + line + '\n ' + spacing + mark('^'); | |
} else { | |
return ' ' + aside(gutter) + line; | |
} | |
}).join('\n'); | |
}; | |
/** | |
* Returns error position, message and source code of the broken part. | |
* | |
* @example | |
* error.toString() //=> "CssSyntaxError: app.css:1:1: Unclosed block | |
* // > 1 | a { | |
* // | ^" | |
* | |
* @return {string} error position, message and source code | |
*/ | |
CssSyntaxError.prototype.toString = function toString() { | |
var code = this.showSourceCode(); | |
if (code) { | |
code = '\n\n' + code + '\n'; | |
} | |
return this.name + ': ' + this.message + code; | |
}; | |
/** | |
* @memberof CssSyntaxError# | |
* @member {Input} input - Input object with PostCSS internal information | |
* about input file. If input has source map | |
* from previous tool, PostCSS will use origin | |
* (for example, Sass) source. You can use this | |
* object to get PostCSS input source. | |
* | |
* @example | |
* error.input.file //=> 'a.css' | |
* error.file //=> 'a.sass' | |
*/ | |
return CssSyntaxError; | |
}(); | |
exports.default = CssSyntaxError; | |
module.exports = exports['default']; | |
},{"./terminal-highlight":32,"chalk":393,"supports-color":393}],16:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _node = require('./node'); | |
var _node2 = _interopRequireDefault(_node); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
/** | |
* Represents a CSS declaration. | |
* | |
* @extends Node | |
* | |
* @example | |
* const root = postcss.parse('a { color: black }'); | |
* const decl = root.first.first; | |
* decl.type //=> 'decl' | |
* decl.toString() //=> ' color: black' | |
*/ | |
var Declaration = function (_Node) { | |
_inherits(Declaration, _Node); | |
function Declaration(defaults) { | |
_classCallCheck(this, Declaration); | |
var _this = _possibleConstructorReturn(this, _Node.call(this, defaults)); | |
_this.type = 'decl'; | |
return _this; | |
} | |
/** | |
* @memberof Declaration# | |
* @member {string} prop - the declaration’s property name | |
* | |
* @example | |
* const root = postcss.parse('a { color: black }'); | |
* const decl = root.first.first; | |
* decl.prop //=> 'color' | |
*/ | |
/** | |
* @memberof Declaration# | |
* @member {string} value - the declaration’s value | |
* | |
* @example | |
* const root = postcss.parse('a { color: black }'); | |
* const decl = root.first.first; | |
* decl.value //=> 'black' | |
*/ | |
/** | |
* @memberof Declaration# | |
* @member {boolean} important - `true` if the declaration | |
* has an !important annotation. | |
* | |
* @example | |
* const root = postcss.parse('a { color: black !important; color: red }'); | |
* root.first.first.important //=> true | |
* root.first.last.important //=> undefined | |
*/ | |
/** | |
* @memberof Declaration# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `before`: the space symbols before the node. It also stores `*` | |
* and `_` symbols before the declaration (IE hack). | |
* * `between`: the symbols between the property and value | |
* for declarations. | |
* * `important`: the content of the important statement, | |
* if it is not just `!important`. | |
* | |
* PostCSS cleans declaration from comments and extra spaces, | |
* but it stores origin content in raws properties. | |
* As such, if you don’t change a declaration’s value, | |
* PostCSS will use the raw value with comments. | |
* | |
* @example | |
* const root = postcss.parse('a {\n color:black\n}') | |
* root.first.first.raws //=> { before: '\n ', between: ':' } | |
*/ | |
return Declaration; | |
}(_node2.default); | |
exports.default = Declaration; | |
module.exports = exports['default']; | |
},{"./node":21}],17:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _cssSyntaxError = require('./css-syntax-error'); | |
var _cssSyntaxError2 = _interopRequireDefault(_cssSyntaxError); | |
var _previousMap = require('./previous-map'); | |
var _previousMap2 = _interopRequireDefault(_previousMap); | |
var _path = require('path'); | |
var _path2 = _interopRequireDefault(_path); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var sequence = 0; | |
/** | |
* Represents the source CSS. | |
* | |
* @example | |
* const root = postcss.parse(css, { from: file }); | |
* const input = root.source.input; | |
*/ | |
var Input = function () { | |
/** | |
* @param {string} css - input CSS source | |
* @param {object} [opts] - {@link Processor#process} options | |
*/ | |
function Input(css) { | |
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
_classCallCheck(this, Input); | |
if (css === null || (typeof css === 'undefined' ? 'undefined' : _typeof(css)) === 'object' && !css.toString) { | |
throw new Error('PostCSS received ' + css + ' instead of CSS string'); | |
} | |
/** | |
* @member {string} - input CSS source | |
* | |
* @example | |
* const input = postcss.parse('a{}', { from: file }).input; | |
* input.css //=> "a{}"; | |
*/ | |
this.css = css.toString(); | |
if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') { | |
this.css = this.css.slice(1); | |
} | |
if (opts.from) { | |
if (/^\w+:\/\//.test(opts.from)) { | |
/** | |
* @member {string} - The absolute path to the CSS source file | |
* defined with the `from` option. | |
* | |
* @example | |
* const root = postcss.parse(css, { from: 'a.css' }); | |
* root.source.input.file //=> '/home/ai/a.css' | |
*/ | |
this.file = opts.from; | |
} else { | |
this.file = _path2.default.resolve(opts.from); | |
} | |
} | |
var map = new _previousMap2.default(this.css, opts); | |
if (map.text) { | |
/** | |
* @member {PreviousMap} - The input source map passed from | |
* a compilation step before PostCSS | |
* (for example, from Sass compiler). | |
* | |
* @example | |
* root.source.input.map.consumer().sources //=> ['a.sass'] | |
*/ | |
this.map = map; | |
var file = map.consumer().file; | |
if (!this.file && file) this.file = this.mapResolve(file); | |
} | |
if (!this.file) { | |
sequence += 1; | |
/** | |
* @member {string} - The unique ID of the CSS source. It will be | |
* created if `from` option is not provided | |
* (because PostCSS does not know the file path). | |
* | |
* @example | |
* const root = postcss.parse(css); | |
* root.source.input.file //=> undefined | |
* root.source.input.id //=> "<input css 1>" | |
*/ | |
this.id = '<input css ' + sequence + '>'; | |
} | |
if (this.map) this.map.file = this.from; | |
} | |
Input.prototype.error = function error(message, line, column) { | |
var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | |
var result = void 0; | |
var origin = this.origin(line, column); | |
if (origin) { | |
result = new _cssSyntaxError2.default(message, origin.line, origin.column, origin.source, origin.file, opts.plugin); | |
} else { | |
result = new _cssSyntaxError2.default(message, line, column, this.css, this.file, opts.plugin); | |
} | |
result.input = { line: line, column: column, source: this.css }; | |
if (this.file) result.input.file = this.file; | |
return result; | |
}; | |
/** | |
* Reads the input source map and returns a symbol position | |
* in the input source (e.g., in a Sass file that was compiled | |
* to CSS before being passed to PostCSS). | |
* | |
* @param {number} line - line in input CSS | |
* @param {number} column - column in input CSS | |
* | |
* @return {filePosition} position in input source | |
* | |
* @example | |
* root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } | |
*/ | |
Input.prototype.origin = function origin(line, column) { | |
if (!this.map) return false; | |
var consumer = this.map.consumer(); | |
var from = consumer.originalPositionFor({ line: line, column: column }); | |
if (!from.source) return false; | |
var result = { | |
file: this.mapResolve(from.source), | |
line: from.line, | |
column: from.column | |
}; | |
var source = consumer.sourceContentFor(from.source); | |
if (source) result.source = source; | |
return result; | |
}; | |
Input.prototype.mapResolve = function mapResolve(file) { | |
if (/^\w+:\/\//.test(file)) { | |
return file; | |
} else { | |
return _path2.default.resolve(this.map.consumer().sourceRoot || '.', file); | |
} | |
}; | |
/** | |
* The CSS source identifier. Contains {@link Input#file} if the user | |
* set the `from` option, or {@link Input#id} if they did not. | |
* @type {string} | |
* | |
* @example | |
* const root = postcss.parse(css, { from: 'a.css' }); | |
* root.source.input.from //=> "/home/ai/a.css" | |
* | |
* const root = postcss.parse(css); | |
* root.source.input.from //=> "<input css 1>" | |
*/ | |
_createClass(Input, [{ | |
key: 'from', | |
get: function get() { | |
return this.file || this.id; | |
} | |
}]); | |
return Input; | |
}(); | |
exports.default = Input; | |
/** | |
* @typedef {object} filePosition | |
* @property {string} file - path to file | |
* @property {number} line - source line in file | |
* @property {number} column - source column in file | |
*/ | |
module.exports = exports['default']; | |
},{"./css-syntax-error":15,"./previous-map":25,"path":397}],18:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _mapGenerator = require('./map-generator'); | |
var _mapGenerator2 = _interopRequireDefault(_mapGenerator); | |
var _stringify2 = require('./stringify'); | |
var _stringify3 = _interopRequireDefault(_stringify2); | |
var _warnOnce = require('./warn-once'); | |
var _warnOnce2 = _interopRequireDefault(_warnOnce); | |
var _result = require('./result'); | |
var _result2 = _interopRequireDefault(_result); | |
var _parse = require('./parse'); | |
var _parse2 = _interopRequireDefault(_parse); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function isPromise(obj) { | |
return (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.then === 'function'; | |
} | |
/** | |
* A Promise proxy for the result of PostCSS transformations. | |
* | |
* A `LazyResult` instance is returned by {@link Processor#process}. | |
* | |
* @example | |
* const lazy = postcss([cssnext]).process(css); | |
*/ | |
var LazyResult = function () { | |
function LazyResult(processor, css, opts) { | |
_classCallCheck(this, LazyResult); | |
this.stringified = false; | |
this.processed = false; | |
var root = void 0; | |
if ((typeof css === 'undefined' ? 'undefined' : _typeof(css)) === 'object' && css !== null && css.type === 'root') { | |
root = css; | |
} else if (css instanceof LazyResult || css instanceof _result2.default) { | |
root = css.root; | |
if (css.map) { | |
if (typeof opts.map === 'undefined') opts.map = {}; | |
if (!opts.map.inline) opts.map.inline = false; | |
opts.map.prev = css.map; | |
} | |
} else { | |
var parser = _parse2.default; | |
if (opts.syntax) parser = opts.syntax.parse; | |
if (opts.parser) parser = opts.parser; | |
if (parser.parse) parser = parser.parse; | |
try { | |
root = parser(css, opts); | |
} catch (error) { | |
this.error = error; | |
} | |
} | |
this.result = new _result2.default(processor, root, opts); | |
} | |
/** | |
* Returns a {@link Processor} instance, which will be used | |
* for CSS transformations. | |
* @type {Processor} | |
*/ | |
/** | |
* Processes input CSS through synchronous plugins | |
* and calls {@link Result#warnings()}. | |
* | |
* @return {Warning[]} warnings from plugins | |
*/ | |
LazyResult.prototype.warnings = function warnings() { | |
return this.sync().warnings(); | |
}; | |
/** | |
* Alias for the {@link LazyResult#css} property. | |
* | |
* @example | |
* lazy + '' === lazy.css; | |
* | |
* @return {string} output CSS | |
*/ | |
LazyResult.prototype.toString = function toString() { | |
return this.css; | |
}; | |
/** | |
* Processes input CSS through synchronous and asynchronous plugins | |
* and calls `onFulfilled` with a Result instance. If a plugin throws | |
* an error, the `onRejected` callback will be executed. | |
* | |
* It implements standard Promise API. | |
* | |
* @param {onFulfilled} onFulfilled - callback will be executed | |
* when all plugins will finish work | |
* @param {onRejected} onRejected - callback will be executed on any error | |
* | |
* @return {Promise} Promise API to make queue | |
* | |
* @example | |
* postcss([cssnext]).process(css, { from: cssPath }).then(result => { | |
* console.log(result.css); | |
* }); | |
*/ | |
LazyResult.prototype.then = function then(onFulfilled, onRejected) { | |
if (!('from' in this.opts)) { | |
(0, _warnOnce2.default)('Without `from` option PostCSS could generate wrong ' + 'source map and will not find Browserslist config. ' + 'Set it to CSS file path or to `undefined` to prevent ' + 'this warning.'); | |
} | |
return this.async().then(onFulfilled, onRejected); | |
}; | |
/** | |
* Processes input CSS through synchronous and asynchronous plugins | |
* and calls onRejected for each error thrown in any plugin. | |
* | |
* It implements standard Promise API. | |
* | |
* @param {onRejected} onRejected - callback will be executed on any error | |
* | |
* @return {Promise} Promise API to make queue | |
* | |
* @example | |
* postcss([cssnext]).process(css).then(result => { | |
* console.log(result.css); | |
* }).catch(error => { | |
* console.error(error); | |
* }); | |
*/ | |
LazyResult.prototype.catch = function _catch(onRejected) { | |
return this.async().catch(onRejected); | |
}; | |
LazyResult.prototype.handleError = function handleError(error, plugin) { | |
try { | |
this.error = error; | |
if (error.name === 'CssSyntaxError' && !error.plugin) { | |
error.plugin = plugin.postcssPlugin; | |
error.setMessage(); | |
} else if (plugin.postcssVersion) { | |
var pluginName = plugin.postcssPlugin; | |
var pluginVer = plugin.postcssVersion; | |
var runtimeVer = this.result.processor.version; | |
var a = pluginVer.split('.'); | |
var b = runtimeVer.split('.'); | |
if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) { | |
console.error('Unknown error from PostCSS plugin. ' + 'Your current PostCSS version ' + 'is ' + runtimeVer + ', but ' + pluginName + ' ' + 'uses ' + pluginVer + '. Perhaps this is ' + 'the source of the error below.'); | |
} | |
} | |
} catch (err) { | |
if (console && console.error) console.error(err); | |
} | |
}; | |
LazyResult.prototype.asyncTick = function asyncTick(resolve, reject) { | |
var _this = this; | |
if (this.plugin >= this.processor.plugins.length) { | |
this.processed = true; | |
return resolve(); | |
} | |
try { | |
var plugin = this.processor.plugins[this.plugin]; | |
var promise = this.run(plugin); | |
this.plugin += 1; | |
if (isPromise(promise)) { | |
promise.then(function () { | |
_this.asyncTick(resolve, reject); | |
}).catch(function (error) { | |
_this.handleError(error, plugin); | |
_this.processed = true; | |
reject(error); | |
}); | |
} else { | |
this.asyncTick(resolve, reject); | |
} | |
} catch (error) { | |
this.processed = true; | |
reject(error); | |
} | |
}; | |
LazyResult.prototype.async = function async() { | |
var _this2 = this; | |
if (this.processed) { | |
return new Promise(function (resolve, reject) { | |
if (_this2.error) { | |
reject(_this2.error); | |
} else { | |
resolve(_this2.stringify()); | |
} | |
}); | |
} | |
if (this.processing) { | |
return this.processing; | |
} | |
this.processing = new Promise(function (resolve, reject) { | |
if (_this2.error) return reject(_this2.error); | |
_this2.plugin = 0; | |
_this2.asyncTick(resolve, reject); | |
}).then(function () { | |
_this2.processed = true; | |
return _this2.stringify(); | |
}); | |
return this.processing; | |
}; | |
LazyResult.prototype.sync = function sync() { | |
if (this.processed) return this.result; | |
this.processed = true; | |
if (this.processing) { | |
throw new Error('Use process(css).then(cb) to work with async plugins'); | |
} | |
if (this.error) throw this.error; | |
for (var _iterator = this.result.processor.plugins, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var plugin = _ref; | |
var promise = this.run(plugin); | |
if (isPromise(promise)) { | |
throw new Error('Use process(css).then(cb) to work with async plugins'); | |
} | |
} | |
return this.result; | |
}; | |
LazyResult.prototype.run = function run(plugin) { | |
this.result.lastPlugin = plugin; | |
try { | |
return plugin(this.result.root, this.result); | |
} catch (error) { | |
this.handleError(error, plugin); | |
throw error; | |
} | |
}; | |
LazyResult.prototype.stringify = function stringify() { | |
if (this.stringified) return this.result; | |
this.stringified = true; | |
this.sync(); | |
var opts = this.result.opts; | |
var str = _stringify3.default; | |
if (opts.syntax) str = opts.syntax.stringify; | |
if (opts.stringifier) str = opts.stringifier; | |
if (str.stringify) str = str.stringify; | |
var map = new _mapGenerator2.default(str, this.result.root, this.result.opts); | |
var data = map.generate(); | |
this.result.css = data[0]; | |
this.result.map = data[1]; | |
return this.result; | |
}; | |
_createClass(LazyResult, [{ | |
key: 'processor', | |
get: function get() { | |
return this.result.processor; | |
} | |
/** | |
* Options from the {@link Processor#process} call. | |
* @type {processOptions} | |
*/ | |
}, { | |
key: 'opts', | |
get: function get() { | |
return this.result.opts; | |
} | |
/** | |
* Processes input CSS through synchronous plugins, converts `Root` | |
* to a CSS string and returns {@link Result#css}. | |
* | |
* This property will only work with synchronous plugins. | |
* If the processor contains any asynchronous plugins | |
* it will throw an error. This is why this method is only | |
* for debug purpose, you should always use {@link LazyResult#then}. | |
* | |
* @type {string} | |
* @see Result#css | |
*/ | |
}, { | |
key: 'css', | |
get: function get() { | |
return this.stringify().css; | |
} | |
/** | |
* An alias for the `css` property. Use it with syntaxes | |
* that generate non-CSS output. | |
* | |
* This property will only work with synchronous plugins. | |
* If the processor contains any asynchronous plugins | |
* it will throw an error. This is why this method is only | |
* for debug purpose, you should always use {@link LazyResult#then}. | |
* | |
* @type {string} | |
* @see Result#content | |
*/ | |
}, { | |
key: 'content', | |
get: function get() { | |
return this.stringify().content; | |
} | |
/** | |
* Processes input CSS through synchronous plugins | |
* and returns {@link Result#map}. | |
* | |
* This property will only work with synchronous plugins. | |
* If the processor contains any asynchronous plugins | |
* it will throw an error. This is why this method is only | |
* for debug purpose, you should always use {@link LazyResult#then}. | |
* | |
* @type {SourceMapGenerator} | |
* @see Result#map | |
*/ | |
}, { | |
key: 'map', | |
get: function get() { | |
return this.stringify().map; | |
} | |
/** | |
* Processes input CSS through synchronous plugins | |
* and returns {@link Result#root}. | |
* | |
* This property will only work with synchronous plugins. If the processor | |
* contains any asynchronous plugins it will throw an error. | |
* | |
* This is why this method is only for debug purpose, | |
* you should always use {@link LazyResult#then}. | |
* | |
* @type {Root} | |
* @see Result#root | |
*/ | |
}, { | |
key: 'root', | |
get: function get() { | |
return this.sync().root; | |
} | |
/** | |
* Processes input CSS through synchronous plugins | |
* and returns {@link Result#messages}. | |
* | |
* This property will only work with synchronous plugins. If the processor | |
* contains any asynchronous plugins it will throw an error. | |
* | |
* This is why this method is only for debug purpose, | |
* you should always use {@link LazyResult#then}. | |
* | |
* @type {Message[]} | |
* @see Result#messages | |
*/ | |
}, { | |
key: 'messages', | |
get: function get() { | |
return this.sync().messages; | |
} | |
}]); | |
return LazyResult; | |
}(); | |
exports.default = LazyResult; | |
/** | |
* @callback onFulfilled | |
* @param {Result} result | |
*/ | |
/** | |
* @callback onRejected | |
* @param {Error} error | |
*/ | |
module.exports = exports['default']; | |
},{"./map-generator":20,"./parse":22,"./result":27,"./stringify":31,"./warn-once":35}],19:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
/** | |
* Contains helpers for safely splitting lists of CSS values, | |
* preserving parentheses and quotes. | |
* | |
* @example | |
* const list = postcss.list; | |
* | |
* @namespace list | |
*/ | |
var list = { | |
split: function split(string, separators, last) { | |
var array = []; | |
var current = ''; | |
var split = false; | |
var func = 0; | |
var quote = false; | |
var escape = false; | |
for (var i = 0; i < string.length; i++) { | |
var letter = string[i]; | |
if (quote) { | |
if (escape) { | |
escape = false; | |
} else if (letter === '\\') { | |
escape = true; | |
} else if (letter === quote) { | |
quote = false; | |
} | |
} else if (letter === '"' || letter === '\'') { | |
quote = letter; | |
} else if (letter === '(') { | |
func += 1; | |
} else if (letter === ')') { | |
if (func > 0) func -= 1; | |
} else if (func === 0) { | |
if (separators.indexOf(letter) !== -1) split = true; | |
} | |
if (split) { | |
if (current !== '') array.push(current.trim()); | |
current = ''; | |
split = false; | |
} else { | |
current += letter; | |
} | |
} | |
if (last || current !== '') array.push(current.trim()); | |
return array; | |
}, | |
/** | |
* Safely splits space-separated values (such as those for `background`, | |
* `border-radius`, and other shorthand properties). | |
* | |
* @param {string} string - space-separated values | |
* | |
* @return {string[]} split values | |
* | |
* @example | |
* postcss.list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)'] | |
*/ | |
space: function space(string) { | |
var spaces = [' ', '\n', '\t']; | |
return list.split(string, spaces); | |
}, | |
/** | |
* Safely splits comma-separated values (such as those for `transition-*` | |
* and `background` properties). | |
* | |
* @param {string} string - comma-separated values | |
* | |
* @return {string[]} split values | |
* | |
* @example | |
* postcss.list.comma('black, linear-gradient(white, black)') | |
* //=> ['black', 'linear-gradient(white, black)'] | |
*/ | |
comma: function comma(string) { | |
var comma = ','; | |
return list.split(string, [comma], true); | |
} | |
}; | |
exports.default = list; | |
module.exports = exports['default']; | |
},{}],20:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
exports.__esModule = true; | |
var _sourceMap = require('source-map'); | |
var _sourceMap2 = _interopRequireDefault(_sourceMap); | |
var _path = require('path'); | |
var _path2 = _interopRequireDefault(_path); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var MapGenerator = function () { | |
function MapGenerator(stringify, root, opts) { | |
_classCallCheck(this, MapGenerator); | |
this.stringify = stringify; | |
this.mapOpts = opts.map || {}; | |
this.root = root; | |
this.opts = opts; | |
} | |
MapGenerator.prototype.isMap = function isMap() { | |
if (typeof this.opts.map !== 'undefined') { | |
return !!this.opts.map; | |
} else { | |
return this.previous().length > 0; | |
} | |
}; | |
MapGenerator.prototype.previous = function previous() { | |
var _this = this; | |
if (!this.previousMaps) { | |
this.previousMaps = []; | |
this.root.walk(function (node) { | |
if (node.source && node.source.input.map) { | |
var map = node.source.input.map; | |
if (_this.previousMaps.indexOf(map) === -1) { | |
_this.previousMaps.push(map); | |
} | |
} | |
}); | |
} | |
return this.previousMaps; | |
}; | |
MapGenerator.prototype.isInline = function isInline() { | |
if (typeof this.mapOpts.inline !== 'undefined') { | |
return this.mapOpts.inline; | |
} | |
var annotation = this.mapOpts.annotation; | |
if (typeof annotation !== 'undefined' && annotation !== true) { | |
return false; | |
} | |
if (this.previous().length) { | |
return this.previous().some(function (i) { | |
return i.inline; | |
}); | |
} else { | |
return true; | |
} | |
}; | |
MapGenerator.prototype.isSourcesContent = function isSourcesContent() { | |
if (typeof this.mapOpts.sourcesContent !== 'undefined') { | |
return this.mapOpts.sourcesContent; | |
} | |
if (this.previous().length) { | |
return this.previous().some(function (i) { | |
return i.withContent(); | |
}); | |
} else { | |
return true; | |
} | |
}; | |
MapGenerator.prototype.clearAnnotation = function clearAnnotation() { | |
if (this.mapOpts.annotation === false) return; | |
var node = void 0; | |
for (var i = this.root.nodes.length - 1; i >= 0; i--) { | |
node = this.root.nodes[i]; | |
if (node.type !== 'comment') continue; | |
if (node.text.indexOf('# sourceMappingURL=') === 0) { | |
this.root.removeChild(i); | |
} | |
} | |
}; | |
MapGenerator.prototype.setSourcesContent = function setSourcesContent() { | |
var _this2 = this; | |
var already = {}; | |
this.root.walk(function (node) { | |
if (node.source) { | |
var from = node.source.input.from; | |
if (from && !already[from]) { | |
already[from] = true; | |
var relative = _this2.relative(from); | |
_this2.map.setSourceContent(relative, node.source.input.css); | |
} | |
} | |
}); | |
}; | |
MapGenerator.prototype.applyPrevMaps = function applyPrevMaps() { | |
for (var _iterator = this.previous(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var prev = _ref; | |
var from = this.relative(prev.file); | |
var root = prev.root || _path2.default.dirname(prev.file); | |
var map = void 0; | |
if (this.mapOpts.sourcesContent === false) { | |
map = new _sourceMap2.default.SourceMapConsumer(prev.text); | |
if (map.sourcesContent) { | |
map.sourcesContent = map.sourcesContent.map(function () { | |
return null; | |
}); | |
} | |
} else { | |
map = prev.consumer(); | |
} | |
this.map.applySourceMap(map, from, this.relative(root)); | |
} | |
}; | |
MapGenerator.prototype.isAnnotation = function isAnnotation() { | |
if (this.isInline()) { | |
return true; | |
} else if (typeof this.mapOpts.annotation !== 'undefined') { | |
return this.mapOpts.annotation; | |
} else if (this.previous().length) { | |
return this.previous().some(function (i) { | |
return i.annotation; | |
}); | |
} else { | |
return true; | |
} | |
}; | |
MapGenerator.prototype.toBase64 = function toBase64(str) { | |
if (Buffer) { | |
if (Buffer.from && Buffer.from !== Uint8Array.from) { | |
return Buffer.from(str).toString('base64'); | |
} else { | |
return new Buffer(str).toString('base64'); | |
} | |
} else { | |
return window.btoa(unescape(encodeURIComponent(str))); | |
} | |
}; | |
MapGenerator.prototype.addAnnotation = function addAnnotation() { | |
var content = void 0; | |
if (this.isInline()) { | |
content = 'data:application/json;base64,' + this.toBase64(this.map.toString()); | |
} else if (typeof this.mapOpts.annotation === 'string') { | |
content = this.mapOpts.annotation; | |
} else { | |
content = this.outputFile() + '.map'; | |
} | |
var eol = '\n'; | |
if (this.css.indexOf('\r\n') !== -1) eol = '\r\n'; | |
this.css += eol + '/*# sourceMappingURL=' + content + ' */'; | |
}; | |
MapGenerator.prototype.outputFile = function outputFile() { | |
if (this.opts.to) { | |
return this.relative(this.opts.to); | |
} else if (this.opts.from) { | |
return this.relative(this.opts.from); | |
} else { | |
return 'to.css'; | |
} | |
}; | |
MapGenerator.prototype.generateMap = function generateMap() { | |
this.generateString(); | |
if (this.isSourcesContent()) this.setSourcesContent(); | |
if (this.previous().length > 0) this.applyPrevMaps(); | |
if (this.isAnnotation()) this.addAnnotation(); | |
if (this.isInline()) { | |
return [this.css]; | |
} else { | |
return [this.css, this.map]; | |
} | |
}; | |
MapGenerator.prototype.relative = function relative(file) { | |
if (file.indexOf('<') === 0) return file; | |
if (/^\w+:\/\//.test(file)) return file; | |
var from = this.opts.to ? _path2.default.dirname(this.opts.to) : '.'; | |
if (typeof this.mapOpts.annotation === 'string') { | |
from = _path2.default.dirname(_path2.default.resolve(from, this.mapOpts.annotation)); | |
} | |
file = _path2.default.relative(from, file); | |
if (_path2.default.sep === '\\') { | |
return file.replace(/\\/g, '/'); | |
} else { | |
return file; | |
} | |
}; | |
MapGenerator.prototype.sourcePath = function sourcePath(node) { | |
if (this.mapOpts.from) { | |
return this.mapOpts.from; | |
} else { | |
return this.relative(node.source.input.from); | |
} | |
}; | |
MapGenerator.prototype.generateString = function generateString() { | |
var _this3 = this; | |
this.css = ''; | |
this.map = new _sourceMap2.default.SourceMapGenerator({ file: this.outputFile() }); | |
var line = 1; | |
var column = 1; | |
var lines = void 0, | |
last = void 0; | |
this.stringify(this.root, function (str, node, type) { | |
_this3.css += str; | |
if (node && type !== 'end') { | |
if (node.source && node.source.start) { | |
_this3.map.addMapping({ | |
source: _this3.sourcePath(node), | |
generated: { line: line, column: column - 1 }, | |
original: { | |
line: node.source.start.line, | |
column: node.source.start.column - 1 | |
} | |
}); | |
} else { | |
_this3.map.addMapping({ | |
source: '<no source>', | |
original: { line: 1, column: 0 }, | |
generated: { line: line, column: column - 1 } | |
}); | |
} | |
} | |
lines = str.match(/\n/g); | |
if (lines) { | |
line += lines.length; | |
last = str.lastIndexOf('\n'); | |
column = str.length - last; | |
} else { | |
column += str.length; | |
} | |
if (node && type !== 'start') { | |
if (node.source && node.source.end) { | |
_this3.map.addMapping({ | |
source: _this3.sourcePath(node), | |
generated: { line: line, column: column - 1 }, | |
original: { | |
line: node.source.end.line, | |
column: node.source.end.column | |
} | |
}); | |
} else { | |
_this3.map.addMapping({ | |
source: '<no source>', | |
original: { line: 1, column: 0 }, | |
generated: { line: line, column: column - 1 } | |
}); | |
} | |
} | |
}); | |
}; | |
MapGenerator.prototype.generate = function generate() { | |
this.clearAnnotation(); | |
if (this.isMap()) { | |
return this.generateMap(); | |
} else { | |
var result = ''; | |
this.stringify(this.root, function (i) { | |
result += i; | |
}); | |
return [result]; | |
} | |
}; | |
return MapGenerator; | |
}(); | |
exports.default = MapGenerator; | |
module.exports = exports['default']; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":395,"path":397,"source-map":340}],21:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _cssSyntaxError = require('./css-syntax-error'); | |
var _cssSyntaxError2 = _interopRequireDefault(_cssSyntaxError); | |
var _stringifier = require('./stringifier'); | |
var _stringifier2 = _interopRequireDefault(_stringifier); | |
var _stringify = require('./stringify'); | |
var _stringify2 = _interopRequireDefault(_stringify); | |
var _warnOnce = require('./warn-once'); | |
var _warnOnce2 = _interopRequireDefault(_warnOnce); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var cloneNode = function cloneNode(obj, parent) { | |
var cloned = new obj.constructor(); | |
for (var i in obj) { | |
if (!obj.hasOwnProperty(i)) continue; | |
var value = obj[i]; | |
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value); | |
if (i === 'parent' && type === 'object') { | |
if (parent) cloned[i] = parent; | |
} else if (i === 'source') { | |
cloned[i] = value; | |
} else if (value instanceof Array) { | |
cloned[i] = value.map(function (j) { | |
return cloneNode(j, cloned); | |
}); | |
} else { | |
if (type === 'object' && value !== null) value = cloneNode(value); | |
cloned[i] = value; | |
} | |
} | |
return cloned; | |
}; | |
/** | |
* All node classes inherit the following common methods. | |
* | |
* @abstract | |
*/ | |
var Node = function () { | |
/** | |
* @param {object} [defaults] - value for node properties | |
*/ | |
function Node() { | |
var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | |
_classCallCheck(this, Node); | |
this.raws = {}; | |
if ((typeof defaults === 'undefined' ? 'undefined' : _typeof(defaults)) !== 'object' && typeof defaults !== 'undefined') { | |
throw new Error('PostCSS nodes constructor accepts object, not ' + JSON.stringify(defaults)); | |
} | |
for (var name in defaults) { | |
this[name] = defaults[name]; | |
} | |
} | |
/** | |
* Returns a CssSyntaxError instance containing the original position | |
* of the node in the source, showing line and column numbers and also | |
* a small excerpt to facilitate debugging. | |
* | |
* If present, an input source map will be used to get the original position | |
* of the source, even from a previous compilation step | |
* (e.g., from Sass compilation). | |
* | |
* This method produces very useful error messages. | |
* | |
* @param {string} message - error description | |
* @param {object} [opts] - options | |
* @param {string} opts.plugin - plugin name that created this error. | |
* PostCSS will set it automatically. | |
* @param {string} opts.word - a word inside a node’s string that should | |
* be highlighted as the source of the error | |
* @param {number} opts.index - an index inside a node’s string that should | |
* be highlighted as the source of the error | |
* | |
* @return {CssSyntaxError} error object to throw it | |
* | |
* @example | |
* if ( !variables[name] ) { | |
* throw decl.error('Unknown variable ' + name, { word: name }); | |
* // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black | |
* // color: $black | |
* // a | |
* // ^ | |
* // background: white | |
* } | |
*/ | |
Node.prototype.error = function error(message) { | |
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
if (this.source) { | |
var pos = this.positionBy(opts); | |
return this.source.input.error(message, pos.line, pos.column, opts); | |
} else { | |
return new _cssSyntaxError2.default(message); | |
} | |
}; | |
/** | |
* This method is provided as a convenience wrapper for {@link Result#warn}. | |
* | |
* @param {Result} result - the {@link Result} instance | |
* that will receive the warning | |
* @param {string} text - warning message | |
* @param {object} [opts] - options | |
* @param {string} opts.plugin - plugin name that created this warning. | |
* PostCSS will set it automatically. | |
* @param {string} opts.word - a word inside a node’s string that should | |
* be highlighted as the source of the warning | |
* @param {number} opts.index - an index inside a node’s string that should | |
* be highlighted as the source of the warning | |
* | |
* @return {Warning} created warning object | |
* | |
* @example | |
* const plugin = postcss.plugin('postcss-deprecated', () => { | |
* return (root, result) => { | |
* root.walkDecls('bad', decl => { | |
* decl.warn(result, 'Deprecated property bad'); | |
* }); | |
* }; | |
* }); | |
*/ | |
Node.prototype.warn = function warn(result, text, opts) { | |
var data = { node: this }; | |
for (var i in opts) { | |
data[i] = opts[i]; | |
}return result.warn(text, data); | |
}; | |
/** | |
* Removes the node from its parent and cleans the parent properties | |
* from the node and its children. | |
* | |
* @example | |
* if ( decl.prop.match(/^-webkit-/) ) { | |
* decl.remove(); | |
* } | |
* | |
* @return {Node} node to make calls chain | |
*/ | |
Node.prototype.remove = function remove() { | |
if (this.parent) { | |
this.parent.removeChild(this); | |
} | |
this.parent = undefined; | |
return this; | |
}; | |
/** | |
* Returns a CSS string representing the node. | |
* | |
* @param {stringifier|syntax} [stringifier] - a syntax to use | |
* in string generation | |
* | |
* @return {string} CSS string of this node | |
* | |
* @example | |
* postcss.rule({ selector: 'a' }).toString() //=> "a {}" | |
*/ | |
Node.prototype.toString = function toString() { | |
var stringifier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _stringify2.default; | |
if (stringifier.stringify) stringifier = stringifier.stringify; | |
var result = ''; | |
stringifier(this, function (i) { | |
result += i; | |
}); | |
return result; | |
}; | |
/** | |
* Returns a clone of the node. | |
* | |
* The resulting cloned node and its (cloned) children will have | |
* a clean parent and code style properties. | |
* | |
* @param {object} [overrides] - new properties to override in the clone. | |
* | |
* @example | |
* const cloned = decl.clone({ prop: '-moz-' + decl.prop }); | |
* cloned.raws.before //=> undefined | |
* cloned.parent //=> undefined | |
* cloned.toString() //=> -moz-transform: scale(0) | |
* | |
* @return {Node} clone of the node | |
*/ | |
Node.prototype.clone = function clone() { | |
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | |
var cloned = cloneNode(this); | |
for (var name in overrides) { | |
cloned[name] = overrides[name]; | |
} | |
return cloned; | |
}; | |
/** | |
* Shortcut to clone the node and insert the resulting cloned node | |
* before the current node. | |
* | |
* @param {object} [overrides] - new properties to override in the clone. | |
* | |
* @example | |
* decl.cloneBefore({ prop: '-moz-' + decl.prop }); | |
* | |
* @return {Node} - new node | |
*/ | |
Node.prototype.cloneBefore = function cloneBefore() { | |
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | |
var cloned = this.clone(overrides); | |
this.parent.insertBefore(this, cloned); | |
return cloned; | |
}; | |
/** | |
* Shortcut to clone the node and insert the resulting cloned node | |
* after the current node. | |
* | |
* @param {object} [overrides] - new properties to override in the clone. | |
* | |
* @return {Node} - new node | |
*/ | |
Node.prototype.cloneAfter = function cloneAfter() { | |
var overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | |
var cloned = this.clone(overrides); | |
this.parent.insertAfter(this, cloned); | |
return cloned; | |
}; | |
/** | |
* Inserts node(s) before the current node and removes the current node. | |
* | |
* @param {...Node} nodes - node(s) to replace current one | |
* | |
* @example | |
* if ( atrule.name == 'mixin' ) { | |
* atrule.replaceWith(mixinRules[atrule.params]); | |
* } | |
* | |
* @return {Node} current node to methods chain | |
*/ | |
Node.prototype.replaceWith = function replaceWith() { | |
if (this.parent) { | |
for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) { | |
nodes[_key] = arguments[_key]; | |
} | |
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var node = _ref; | |
this.parent.insertBefore(this, node); | |
} | |
this.remove(); | |
} | |
return this; | |
}; | |
Node.prototype.moveTo = function moveTo(newParent) { | |
(0, _warnOnce2.default)('Node#moveTo was deprecated. Use Container#append.'); | |
this.cleanRaws(this.root() === newParent.root()); | |
this.remove(); | |
newParent.append(this); | |
return this; | |
}; | |
Node.prototype.moveBefore = function moveBefore(otherNode) { | |
(0, _warnOnce2.default)('Node#moveBefore was deprecated. Use Node#before.'); | |
this.cleanRaws(this.root() === otherNode.root()); | |
this.remove(); | |
otherNode.parent.insertBefore(otherNode, this); | |
return this; | |
}; | |
Node.prototype.moveAfter = function moveAfter(otherNode) { | |
(0, _warnOnce2.default)('Node#moveAfter was deprecated. Use Node#after.'); | |
this.cleanRaws(this.root() === otherNode.root()); | |
this.remove(); | |
otherNode.parent.insertAfter(otherNode, this); | |
return this; | |
}; | |
/** | |
* Returns the next child of the node’s parent. | |
* Returns `undefined` if the current node is the last child. | |
* | |
* @return {Node|undefined} next node | |
* | |
* @example | |
* if ( comment.text === 'delete next' ) { | |
* const next = comment.next(); | |
* if ( next ) { | |
* next.remove(); | |
* } | |
* } | |
*/ | |
Node.prototype.next = function next() { | |
if (!this.parent) return undefined; | |
var index = this.parent.index(this); | |
return this.parent.nodes[index + 1]; | |
}; | |
/** | |
* Returns the previous child of the node’s parent. | |
* Returns `undefined` if the current node is the first child. | |
* | |
* @return {Node|undefined} previous node | |
* | |
* @example | |
* const annotation = decl.prev(); | |
* if ( annotation.type == 'comment' ) { | |
* readAnnotation(annotation.text); | |
* } | |
*/ | |
Node.prototype.prev = function prev() { | |
if (!this.parent) return undefined; | |
var index = this.parent.index(this); | |
return this.parent.nodes[index - 1]; | |
}; | |
/** | |
* Insert new node before current node to current node’s parent. | |
* | |
* Just alias for `node.parent.insertBefore(node, add)`. | |
* | |
* @param {Node|object|string|Node[]} add - new node | |
* | |
* @return {Node} this node for methods chain. | |
* | |
* @example | |
* decl.before('content: ""'); | |
*/ | |
Node.prototype.before = function before(add) { | |
this.parent.insertBefore(this, add); | |
return this; | |
}; | |
/** | |
* Insert new node after current node to current node’s parent. | |
* | |
* Just alias for `node.parent.insertAfter(node, add)`. | |
* | |
* @param {Node|object|string|Node[]} add - new node | |
* | |
* @return {Node} this node for methods chain. | |
* | |
* @example | |
* decl.after('color: black'); | |
*/ | |
Node.prototype.after = function after(add) { | |
this.parent.insertAfter(this, add); | |
return this; | |
}; | |
Node.prototype.toJSON = function toJSON() { | |
var fixed = {}; | |
for (var name in this) { | |
if (!this.hasOwnProperty(name)) continue; | |
if (name === 'parent') continue; | |
var value = this[name]; | |
if (value instanceof Array) { | |
fixed[name] = value.map(function (i) { | |
if ((typeof i === 'undefined' ? 'undefined' : _typeof(i)) === 'object' && i.toJSON) { | |
return i.toJSON(); | |
} else { | |
return i; | |
} | |
}); | |
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.toJSON) { | |
fixed[name] = value.toJSON(); | |
} else { | |
fixed[name] = value; | |
} | |
} | |
return fixed; | |
}; | |
/** | |
* Returns a {@link Node#raws} value. If the node is missing | |
* the code style property (because the node was manually built or cloned), | |
* PostCSS will try to autodetect the code style property by looking | |
* at other nodes in the tree. | |
* | |
* @param {string} prop - name of code style property | |
* @param {string} [defaultType] - name of default value, it can be missed | |
* if the value is the same as prop | |
* | |
* @example | |
* const root = postcss.parse('a { background: white }'); | |
* root.nodes[0].append({ prop: 'color', value: 'black' }); | |
* root.nodes[0].nodes[1].raws.before //=> undefined | |
* root.nodes[0].nodes[1].raw('before') //=> ' ' | |
* | |
* @return {string} code style value | |
*/ | |
Node.prototype.raw = function raw(prop, defaultType) { | |
var str = new _stringifier2.default(); | |
return str.raw(this, prop, defaultType); | |
}; | |
/** | |
* Finds the Root instance of the node’s tree. | |
* | |
* @example | |
* root.nodes[0].nodes[0].root() === root | |
* | |
* @return {Root} root parent | |
*/ | |
Node.prototype.root = function root() { | |
var result = this; | |
while (result.parent) { | |
result = result.parent; | |
}return result; | |
}; | |
Node.prototype.cleanRaws = function cleanRaws(keepBetween) { | |
delete this.raws.before; | |
delete this.raws.after; | |
if (!keepBetween) delete this.raws.between; | |
}; | |
Node.prototype.positionInside = function positionInside(index) { | |
var string = this.toString(); | |
var column = this.source.start.column; | |
var line = this.source.start.line; | |
for (var i = 0; i < index; i++) { | |
if (string[i] === '\n') { | |
column = 1; | |
line += 1; | |
} else { | |
column += 1; | |
} | |
} | |
return { line: line, column: column }; | |
}; | |
Node.prototype.positionBy = function positionBy(opts) { | |
var pos = this.source.start; | |
if (opts.index) { | |
pos = this.positionInside(opts.index); | |
} else if (opts.word) { | |
var index = this.toString().indexOf(opts.word); | |
if (index !== -1) pos = this.positionInside(index); | |
} | |
return pos; | |
}; | |
/** | |
* @memberof Node# | |
* @member {string} type - String representing the node’s type. | |
* Possible values are `root`, `atrule`, `rule`, | |
* `decl`, or `comment`. | |
* | |
* @example | |
* postcss.decl({ prop: 'color', value: 'black' }).type //=> 'decl' | |
*/ | |
/** | |
* @memberof Node# | |
* @member {Container} parent - the node’s parent node. | |
* | |
* @example | |
* root.nodes[0].parent == root; | |
*/ | |
/** | |
* @memberof Node# | |
* @member {source} source - the input source of the node | |
* | |
* The property is used in source map generation. | |
* | |
* If you create a node manually (e.g., with `postcss.decl()`), | |
* that node will not have a `source` property and will be absent | |
* from the source map. For this reason, the plugin developer should | |
* consider cloning nodes to create new ones (in which case the new node’s | |
* source will reference the original, cloned node) or setting | |
* the `source` property manually. | |
* | |
* ```js | |
* // Bad | |
* const prefixed = postcss.decl({ | |
* prop: '-moz-' + decl.prop, | |
* value: decl.value | |
* }); | |
* | |
* // Good | |
* const prefixed = decl.clone({ prop: '-moz-' + decl.prop }); | |
* ``` | |
* | |
* ```js | |
* if ( atrule.name == 'add-link' ) { | |
* const rule = postcss.rule({ selector: 'a', source: atrule.source }); | |
* atrule.parent.insertBefore(atrule, rule); | |
* } | |
* ``` | |
* | |
* @example | |
* decl.source.input.from //=> '/home/ai/a.sass' | |
* decl.source.start //=> { line: 10, column: 2 } | |
* decl.source.end //=> { line: 10, column: 12 } | |
*/ | |
/** | |
* @memberof Node# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `before`: the space symbols before the node. It also stores `*` | |
* and `_` symbols before the declaration (IE hack). | |
* * `after`: the space symbols after the last child of the node | |
* to the end of the node. | |
* * `between`: the symbols between the property and value | |
* for declarations, selector and `{` for rules, or last parameter | |
* and `{` for at-rules. | |
* * `semicolon`: contains true if the last child has | |
* an (optional) semicolon. | |
* * `afterName`: the space between the at-rule name and its parameters. | |
* * `left`: the space symbols between `/*` and the comment’s text. | |
* * `right`: the space symbols between the comment’s text | |
* and <code>*/</code>. | |
* * `important`: the content of the important statement, | |
* if it is not just `!important`. | |
* | |
* PostCSS cleans selectors, declaration values and at-rule parameters | |
* from comments and extra spaces, but it stores origin content in raws | |
* properties. As such, if you don’t change a declaration’s value, | |
* PostCSS will use the raw value with comments. | |
* | |
* @example | |
* const root = postcss.parse('a {\n color:black\n}') | |
* root.first.first.raws //=> { before: '\n ', between: ':' } | |
*/ | |
return Node; | |
}(); | |
exports.default = Node; | |
/** | |
* @typedef {object} position | |
* @property {number} line - source line in file | |
* @property {number} column - source column in file | |
*/ | |
/** | |
* @typedef {object} source | |
* @property {Input} input - {@link Input} with input file | |
* @property {position} start - The starting position of the node’s source | |
* @property {position} end - The ending position of the node’s source | |
*/ | |
module.exports = exports['default']; | |
},{"./css-syntax-error":15,"./stringifier":30,"./stringify":31,"./warn-once":35}],22:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
exports.default = parse; | |
var _parser = require('./parser'); | |
var _parser2 = _interopRequireDefault(_parser); | |
var _input = require('./input'); | |
var _input2 = _interopRequireDefault(_input); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function parse(css, opts) { | |
if (opts && opts.safe) { | |
throw new Error('Option safe was removed. ' + 'Use parser: require("postcss-safe-parser")'); | |
} | |
var input = new _input2.default(css, opts); | |
var parser = new _parser2.default(input); | |
try { | |
parser.parse(); | |
} catch (e) { | |
if (e.name === 'CssSyntaxError' && opts && opts.from) { | |
if (/\.scss$/i.test(opts.from)) { | |
e.message += '\nYou tried to parse SCSS with ' + 'the standard CSS parser; ' + 'try again with the postcss-scss parser'; | |
} else if (/\.sass/i.test(opts.from)) { | |
e.message += '\nYou tried to parse Sass with ' + 'the standard CSS parser; ' + 'try again with the postcss-sass parser'; | |
} else if (/\.less$/i.test(opts.from)) { | |
e.message += '\nYou tried to parse Less with ' + 'the standard CSS parser; ' + 'try again with the postcss-less parser'; | |
} | |
} | |
throw e; | |
} | |
return parser.root; | |
} | |
module.exports = exports['default']; | |
},{"./input":17,"./parser":23}],23:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _declaration = require('./declaration'); | |
var _declaration2 = _interopRequireDefault(_declaration); | |
var _tokenize = require('./tokenize'); | |
var _tokenize2 = _interopRequireDefault(_tokenize); | |
var _comment = require('./comment'); | |
var _comment2 = _interopRequireDefault(_comment); | |
var _atRule = require('./at-rule'); | |
var _atRule2 = _interopRequireDefault(_atRule); | |
var _root = require('./root'); | |
var _root2 = _interopRequireDefault(_root); | |
var _rule = require('./rule'); | |
var _rule2 = _interopRequireDefault(_rule); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var Parser = function () { | |
function Parser(input) { | |
_classCallCheck(this, Parser); | |
this.input = input; | |
this.root = new _root2.default(); | |
this.current = this.root; | |
this.spaces = ''; | |
this.semicolon = false; | |
this.createTokenizer(); | |
this.root.source = { input: input, start: { line: 1, column: 1 } }; | |
} | |
Parser.prototype.createTokenizer = function createTokenizer() { | |
this.tokenizer = (0, _tokenize2.default)(this.input); | |
}; | |
Parser.prototype.parse = function parse() { | |
var token = void 0; | |
while (!this.tokenizer.endOfFile()) { | |
token = this.tokenizer.nextToken(); | |
switch (token[0]) { | |
case 'space': | |
this.spaces += token[1]; | |
break; | |
case ';': | |
this.freeSemicolon(token); | |
break; | |
case '}': | |
this.end(token); | |
break; | |
case 'comment': | |
this.comment(token); | |
break; | |
case 'at-word': | |
this.atrule(token); | |
break; | |
case '{': | |
this.emptyRule(token); | |
break; | |
default: | |
this.other(token); | |
break; | |
} | |
} | |
this.endFile(); | |
}; | |
Parser.prototype.comment = function comment(token) { | |
var node = new _comment2.default(); | |
this.init(node, token[2], token[3]); | |
node.source.end = { line: token[4], column: token[5] }; | |
var text = token[1].slice(2, -2); | |
if (/^\s*$/.test(text)) { | |
node.text = ''; | |
node.raws.left = text; | |
node.raws.right = ''; | |
} else { | |
var match = text.match(/^(\s*)([^]*[^\s])(\s*)$/); | |
node.text = match[2]; | |
node.raws.left = match[1]; | |
node.raws.right = match[3]; | |
} | |
}; | |
Parser.prototype.emptyRule = function emptyRule(token) { | |
var node = new _rule2.default(); | |
this.init(node, token[2], token[3]); | |
node.selector = ''; | |
node.raws.between = ''; | |
this.current = node; | |
}; | |
Parser.prototype.other = function other(start) { | |
var end = false; | |
var type = null; | |
var colon = false; | |
var bracket = null; | |
var brackets = []; | |
var tokens = []; | |
var token = start; | |
while (token) { | |
type = token[0]; | |
tokens.push(token); | |
if (type === '(' || type === '[') { | |
if (!bracket) bracket = token; | |
brackets.push(type === '(' ? ')' : ']'); | |
} else if (brackets.length === 0) { | |
if (type === ';') { | |
if (colon) { | |
this.decl(tokens); | |
return; | |
} else { | |
break; | |
} | |
} else if (type === '{') { | |
this.rule(tokens); | |
return; | |
} else if (type === '}') { | |
this.tokenizer.back(tokens.pop()); | |
end = true; | |
break; | |
} else if (type === ':') { | |
colon = true; | |
} | |
} else if (type === brackets[brackets.length - 1]) { | |
brackets.pop(); | |
if (brackets.length === 0) bracket = null; | |
} | |
token = this.tokenizer.nextToken(); | |
} | |
if (this.tokenizer.endOfFile()) end = true; | |
if (brackets.length > 0) this.unclosedBracket(bracket); | |
if (end && colon) { | |
while (tokens.length) { | |
token = tokens[tokens.length - 1][0]; | |
if (token !== 'space' && token !== 'comment') break; | |
this.tokenizer.back(tokens.pop()); | |
} | |
this.decl(tokens); | |
return; | |
} else { | |
this.unknownWord(tokens); | |
} | |
}; | |
Parser.prototype.rule = function rule(tokens) { | |
tokens.pop(); | |
var node = new _rule2.default(); | |
this.init(node, tokens[0][2], tokens[0][3]); | |
node.raws.between = this.spacesAndCommentsFromEnd(tokens); | |
this.raw(node, 'selector', tokens); | |
this.current = node; | |
}; | |
Parser.prototype.decl = function decl(tokens) { | |
var node = new _declaration2.default(); | |
this.init(node); | |
var last = tokens[tokens.length - 1]; | |
if (last[0] === ';') { | |
this.semicolon = true; | |
tokens.pop(); | |
} | |
if (last[4]) { | |
node.source.end = { line: last[4], column: last[5] }; | |
} else { | |
node.source.end = { line: last[2], column: last[3] }; | |
} | |
while (tokens[0][0] !== 'word') { | |
if (tokens.length === 1) this.unknownWord(tokens); | |
node.raws.before += tokens.shift()[1]; | |
} | |
node.source.start = { line: tokens[0][2], column: tokens[0][3] }; | |
node.prop = ''; | |
while (tokens.length) { | |
var type = tokens[0][0]; | |
if (type === ':' || type === 'space' || type === 'comment') { | |
break; | |
} | |
node.prop += tokens.shift()[1]; | |
} | |
node.raws.between = ''; | |
var token = void 0; | |
while (tokens.length) { | |
token = tokens.shift(); | |
if (token[0] === ':') { | |
node.raws.between += token[1]; | |
break; | |
} else { | |
node.raws.between += token[1]; | |
} | |
} | |
if (node.prop[0] === '_' || node.prop[0] === '*') { | |
node.raws.before += node.prop[0]; | |
node.prop = node.prop.slice(1); | |
} | |
node.raws.between += this.spacesAndCommentsFromStart(tokens); | |
this.precheckMissedSemicolon(tokens); | |
for (var i = tokens.length - 1; i > 0; i--) { | |
token = tokens[i]; | |
if (token[1].toLowerCase() === '!important') { | |
node.important = true; | |
var string = this.stringFrom(tokens, i); | |
string = this.spacesFromEnd(tokens) + string; | |
if (string !== ' !important') node.raws.important = string; | |
break; | |
} else if (token[1].toLowerCase() === 'important') { | |
var cache = tokens.slice(0); | |
var str = ''; | |
for (var j = i; j > 0; j--) { | |
var _type = cache[j][0]; | |
if (str.trim().indexOf('!') === 0 && _type !== 'space') { | |
break; | |
} | |
str = cache.pop()[1] + str; | |
} | |
if (str.trim().indexOf('!') === 0) { | |
node.important = true; | |
node.raws.important = str; | |
tokens = cache; | |
} | |
} | |
if (token[0] !== 'space' && token[0] !== 'comment') { | |
break; | |
} | |
} | |
this.raw(node, 'value', tokens); | |
if (node.value.indexOf(':') !== -1) this.checkMissedSemicolon(tokens); | |
}; | |
Parser.prototype.atrule = function atrule(token) { | |
var node = new _atRule2.default(); | |
node.name = token[1].slice(1); | |
if (node.name === '') { | |
this.unnamedAtrule(node, token); | |
} | |
this.init(node, token[2], token[3]); | |
var prev = void 0; | |
var shift = void 0; | |
var last = false; | |
var open = false; | |
var params = []; | |
while (!this.tokenizer.endOfFile()) { | |
token = this.tokenizer.nextToken(); | |
if (token[0] === ';') { | |
node.source.end = { line: token[2], column: token[3] }; | |
this.semicolon = true; | |
break; | |
} else if (token[0] === '{') { | |
open = true; | |
break; | |
} else if (token[0] === '}') { | |
if (params.length > 0) { | |
shift = params.length - 1; | |
prev = params[shift]; | |
while (prev && prev[0] === 'space') { | |
prev = params[--shift]; | |
} | |
if (prev) { | |
node.source.end = { line: prev[4], column: prev[5] }; | |
} | |
} | |
this.end(token); | |
break; | |
} else { | |
params.push(token); | |
} | |
if (this.tokenizer.endOfFile()) { | |
last = true; | |
break; | |
} | |
} | |
node.raws.between = this.spacesAndCommentsFromEnd(params); | |
if (params.length) { | |
node.raws.afterName = this.spacesAndCommentsFromStart(params); | |
this.raw(node, 'params', params); | |
if (last) { | |
token = params[params.length - 1]; | |
node.source.end = { line: token[4], column: token[5] }; | |
this.spaces = node.raws.between; | |
node.raws.between = ''; | |
} | |
} else { | |
node.raws.afterName = ''; | |
node.params = ''; | |
} | |
if (open) { | |
node.nodes = []; | |
this.current = node; | |
} | |
}; | |
Parser.prototype.end = function end(token) { | |
if (this.current.nodes && this.current.nodes.length) { | |
this.current.raws.semicolon = this.semicolon; | |
} | |
this.semicolon = false; | |
this.current.raws.after = (this.current.raws.after || '') + this.spaces; | |
this.spaces = ''; | |
if (this.current.parent) { | |
this.current.source.end = { line: token[2], column: token[3] }; | |
this.current = this.current.parent; | |
} else { | |
this.unexpectedClose(token); | |
} | |
}; | |
Parser.prototype.endFile = function endFile() { | |
if (this.current.parent) this.unclosedBlock(); | |
if (this.current.nodes && this.current.nodes.length) { | |
this.current.raws.semicolon = this.semicolon; | |
} | |
this.current.raws.after = (this.current.raws.after || '') + this.spaces; | |
}; | |
Parser.prototype.freeSemicolon = function freeSemicolon(token) { | |
this.spaces += token[1]; | |
if (this.current.nodes) { | |
var prev = this.current.nodes[this.current.nodes.length - 1]; | |
if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) { | |
prev.raws.ownSemicolon = this.spaces; | |
this.spaces = ''; | |
} | |
} | |
}; | |
// Helpers | |
Parser.prototype.init = function init(node, line, column) { | |
this.current.push(node); | |
node.source = { start: { line: line, column: column }, input: this.input }; | |
node.raws.before = this.spaces; | |
this.spaces = ''; | |
if (node.type !== 'comment') this.semicolon = false; | |
}; | |
Parser.prototype.raw = function raw(node, prop, tokens) { | |
var token = void 0, | |
type = void 0; | |
var length = tokens.length; | |
var value = ''; | |
var clean = true; | |
var next = void 0, | |
prev = void 0; | |
var pattern = /^([.|#])?([\w])+/i; | |
for (var i = 0; i < length; i += 1) { | |
token = tokens[i]; | |
type = token[0]; | |
if (type === 'comment' && node.type === 'rule') { | |
prev = tokens[i - 1]; | |
next = tokens[i + 1]; | |
if (prev[0] !== 'space' && next[0] !== 'space' && pattern.test(prev[1]) && pattern.test(next[1])) { | |
value += token[1]; | |
} else { | |
clean = false; | |
} | |
continue; | |
} | |
if (type === 'comment' || type === 'space' && i === length - 1) { | |
clean = false; | |
} else { | |
value += token[1]; | |
} | |
} | |
if (!clean) { | |
var raw = tokens.reduce(function (all, i) { | |
return all + i[1]; | |
}, ''); | |
node.raws[prop] = { value: value, raw: raw }; | |
} | |
node[prop] = value; | |
}; | |
Parser.prototype.spacesAndCommentsFromEnd = function spacesAndCommentsFromEnd(tokens) { | |
var lastTokenType = void 0; | |
var spaces = ''; | |
while (tokens.length) { | |
lastTokenType = tokens[tokens.length - 1][0]; | |
if (lastTokenType !== 'space' && lastTokenType !== 'comment') break; | |
spaces = tokens.pop()[1] + spaces; | |
} | |
return spaces; | |
}; | |
Parser.prototype.spacesAndCommentsFromStart = function spacesAndCommentsFromStart(tokens) { | |
var next = void 0; | |
var spaces = ''; | |
while (tokens.length) { | |
next = tokens[0][0]; | |
if (next !== 'space' && next !== 'comment') break; | |
spaces += tokens.shift()[1]; | |
} | |
return spaces; | |
}; | |
Parser.prototype.spacesFromEnd = function spacesFromEnd(tokens) { | |
var lastTokenType = void 0; | |
var spaces = ''; | |
while (tokens.length) { | |
lastTokenType = tokens[tokens.length - 1][0]; | |
if (lastTokenType !== 'space') break; | |
spaces = tokens.pop()[1] + spaces; | |
} | |
return spaces; | |
}; | |
Parser.prototype.stringFrom = function stringFrom(tokens, from) { | |
var result = ''; | |
for (var i = from; i < tokens.length; i++) { | |
result += tokens[i][1]; | |
} | |
tokens.splice(from, tokens.length - from); | |
return result; | |
}; | |
Parser.prototype.colon = function colon(tokens) { | |
var brackets = 0; | |
var token = void 0, | |
type = void 0, | |
prev = void 0; | |
for (var i = 0; i < tokens.length; i++) { | |
token = tokens[i]; | |
type = token[0]; | |
if (type === '(') { | |
brackets += 1; | |
} else if (type === ')') { | |
brackets -= 1; | |
} else if (brackets === 0 && type === ':') { | |
if (!prev) { | |
this.doubleColon(token); | |
} else if (prev[0] === 'word' && prev[1] === 'progid') { | |
continue; | |
} else { | |
return i; | |
} | |
} | |
prev = token; | |
} | |
return false; | |
}; | |
// Errors | |
Parser.prototype.unclosedBracket = function unclosedBracket(bracket) { | |
throw this.input.error('Unclosed bracket', bracket[2], bracket[3]); | |
}; | |
Parser.prototype.unknownWord = function unknownWord(tokens) { | |
throw this.input.error('Unknown word', tokens[0][2], tokens[0][3]); | |
}; | |
Parser.prototype.unexpectedClose = function unexpectedClose(token) { | |
throw this.input.error('Unexpected }', token[2], token[3]); | |
}; | |
Parser.prototype.unclosedBlock = function unclosedBlock() { | |
var pos = this.current.source.start; | |
throw this.input.error('Unclosed block', pos.line, pos.column); | |
}; | |
Parser.prototype.doubleColon = function doubleColon(token) { | |
throw this.input.error('Double colon', token[2], token[3]); | |
}; | |
Parser.prototype.unnamedAtrule = function unnamedAtrule(node, token) { | |
throw this.input.error('At-rule without name', token[2], token[3]); | |
}; | |
Parser.prototype.precheckMissedSemicolon = function precheckMissedSemicolon(tokens) { | |
// Hook for Safe Parser | |
tokens; | |
}; | |
Parser.prototype.checkMissedSemicolon = function checkMissedSemicolon(tokens) { | |
var colon = this.colon(tokens); | |
if (colon === false) return; | |
var founded = 0; | |
var token = void 0; | |
for (var j = colon - 1; j >= 0; j--) { | |
token = tokens[j]; | |
if (token[0] !== 'space') { | |
founded += 1; | |
if (founded === 2) break; | |
} | |
} | |
throw this.input.error('Missed semicolon', token[2], token[3]); | |
}; | |
return Parser; | |
}(); | |
exports.default = Parser; | |
module.exports = exports['default']; | |
},{"./at-rule":12,"./comment":13,"./declaration":16,"./root":28,"./rule":29,"./tokenize":33}],24:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _declaration = require('./declaration'); | |
var _declaration2 = _interopRequireDefault(_declaration); | |
var _processor = require('./processor'); | |
var _processor2 = _interopRequireDefault(_processor); | |
var _stringify = require('./stringify'); | |
var _stringify2 = _interopRequireDefault(_stringify); | |
var _comment = require('./comment'); | |
var _comment2 = _interopRequireDefault(_comment); | |
var _atRule = require('./at-rule'); | |
var _atRule2 = _interopRequireDefault(_atRule); | |
var _vendor = require('./vendor'); | |
var _vendor2 = _interopRequireDefault(_vendor); | |
var _parse = require('./parse'); | |
var _parse2 = _interopRequireDefault(_parse); | |
var _list = require('./list'); | |
var _list2 = _interopRequireDefault(_list); | |
var _rule = require('./rule'); | |
var _rule2 = _interopRequireDefault(_rule); | |
var _root = require('./root'); | |
var _root2 = _interopRequireDefault(_root); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
/** | |
* Create a new {@link Processor} instance that will apply `plugins` | |
* as CSS processors. | |
* | |
* @param {Array.<Plugin|pluginFunction>|Processor} plugins - PostCSS | |
* plugins. See {@link Processor#use} for plugin format. | |
* | |
* @return {Processor} Processor to process multiple CSS | |
* | |
* @example | |
* import postcss from 'postcss'; | |
* | |
* postcss(plugins).process(css, { from, to }).then(result => { | |
* console.log(result.css); | |
* }); | |
* | |
* @namespace postcss | |
*/ | |
function postcss() { | |
for (var _len = arguments.length, plugins = Array(_len), _key = 0; _key < _len; _key++) { | |
plugins[_key] = arguments[_key]; | |
} | |
if (plugins.length === 1 && Array.isArray(plugins[0])) { | |
plugins = plugins[0]; | |
} | |
return new _processor2.default(plugins); | |
} | |
/** | |
* Creates a PostCSS plugin with a standard API. | |
* | |
* The newly-wrapped function will provide both the name and PostCSS | |
* version of the plugin. | |
* | |
* ```js | |
* const processor = postcss([replace]); | |
* processor.plugins[0].postcssPlugin //=> 'postcss-replace' | |
* processor.plugins[0].postcssVersion //=> '5.1.0' | |
* ``` | |
* | |
* The plugin function receives 2 arguments: {@link Root} | |
* and {@link Result} instance. The function should mutate the provided | |
* `Root` node. Alternatively, you can create a new `Root` node | |
* and override the `result.root` property. | |
* | |
* ```js | |
* const cleaner = postcss.plugin('postcss-cleaner', () => { | |
* return (root, result) => { | |
* result.root = postcss.root(); | |
* }; | |
* }); | |
* ``` | |
* | |
* As a convenience, plugins also expose a `process` method so that you can use | |
* them as standalone tools. | |
* | |
* ```js | |
* cleaner.process(css, processOpts, pluginOpts); | |
* // This is equivalent to: | |
* postcss([ cleaner(pluginOpts) ]).process(css, processOpts); | |
* ``` | |
* | |
* Asynchronous plugins should return a `Promise` instance. | |
* | |
* ```js | |
* postcss.plugin('postcss-import', () => { | |
* return (root, result) => { | |
* return new Promise( (resolve, reject) => { | |
* fs.readFile('base.css', (base) => { | |
* root.prepend(base); | |
* resolve(); | |
* }); | |
* }); | |
* }; | |
* }); | |
* ``` | |
* | |
* Add warnings using the {@link Node#warn} method. | |
* Send data to other plugins using the {@link Result#messages} array. | |
* | |
* ```js | |
* postcss.plugin('postcss-caniuse-test', () => { | |
* return (root, result) => { | |
* root.walkDecls(decl => { | |
* if ( !caniuse.support(decl.prop) ) { | |
* decl.warn(result, 'Some browsers do not support ' + decl.prop); | |
* } | |
* }); | |
* }; | |
* }); | |
* ``` | |
* | |
* @param {string} name - PostCSS plugin name. Same as in `name` | |
* property in `package.json`. It will be saved | |
* in `plugin.postcssPlugin` property. | |
* @param {function} initializer - will receive plugin options | |
* and should return {@link pluginFunction} | |
* | |
* @return {Plugin} PostCSS plugin | |
*/ | |
postcss.plugin = function plugin(name, initializer) { | |
var creator = function creator() { | |
var transformer = initializer.apply(undefined, arguments); | |
transformer.postcssPlugin = name; | |
transformer.postcssVersion = new _processor2.default().version; | |
return transformer; | |
}; | |
var cache = void 0; | |
Object.defineProperty(creator, 'postcss', { | |
get: function get() { | |
if (!cache) cache = creator(); | |
return cache; | |
} | |
}); | |
creator.process = function (css, processOpts, pluginOpts) { | |
return postcss([creator(pluginOpts)]).process(css, processOpts); | |
}; | |
return creator; | |
}; | |
/** | |
* Default function to convert a node tree into a CSS string. | |
* | |
* @param {Node} node - start node for stringifing. Usually {@link Root}. | |
* @param {builder} builder - function to concatenate CSS from node’s parts | |
* or generate string and source map | |
* | |
* @return {void} | |
* | |
* @function | |
*/ | |
postcss.stringify = _stringify2.default; | |
/** | |
* Parses source css and returns a new {@link Root} node, | |
* which contains the source CSS nodes. | |
* | |
* @param {string|toString} css - string with input CSS or any object | |
* with toString() method, like a Buffer | |
* @param {processOptions} [opts] - options with only `from` and `map` keys | |
* | |
* @return {Root} PostCSS AST | |
* | |
* @example | |
* // Simple CSS concatenation with source map support | |
* const root1 = postcss.parse(css1, { from: file1 }); | |
* const root2 = postcss.parse(css2, { from: file2 }); | |
* root1.append(root2).toResult().css; | |
* | |
* @function | |
*/ | |
postcss.parse = _parse2.default; | |
/** | |
* @member {vendor} - Contains the {@link vendor} module. | |
* | |
* @example | |
* postcss.vendor.unprefixed('-moz-tab') //=> ['tab'] | |
*/ | |
postcss.vendor = _vendor2.default; | |
/** | |
* @member {list} - Contains the {@link list} module. | |
* | |
* @example | |
* postcss.list.space('5px calc(10% + 5px)') //=> ['5px', 'calc(10% + 5px)'] | |
*/ | |
postcss.list = _list2.default; | |
/** | |
* Creates a new {@link Comment} node. | |
* | |
* @param {object} [defaults] - properties for the new node. | |
* | |
* @return {Comment} new Comment node | |
* | |
* @example | |
* postcss.comment({ text: 'test' }) | |
*/ | |
postcss.comment = function (defaults) { | |
return new _comment2.default(defaults); | |
}; | |
/** | |
* Creates a new {@link AtRule} node. | |
* | |
* @param {object} [defaults] - properties for the new node. | |
* | |
* @return {AtRule} new AtRule node | |
* | |
* @example | |
* postcss.atRule({ name: 'charset' }).toString() //=> "@charset" | |
*/ | |
postcss.atRule = function (defaults) { | |
return new _atRule2.default(defaults); | |
}; | |
/** | |
* Creates a new {@link Declaration} node. | |
* | |
* @param {object} [defaults] - properties for the new node. | |
* | |
* @return {Declaration} new Declaration node | |
* | |
* @example | |
* postcss.decl({ prop: 'color', value: 'red' }).toString() //=> "color: red" | |
*/ | |
postcss.decl = function (defaults) { | |
return new _declaration2.default(defaults); | |
}; | |
/** | |
* Creates a new {@link Rule} node. | |
* | |
* @param {object} [defaults] - properties for the new node. | |
* | |
* @return {Rule} new Rule node | |
* | |
* @example | |
* postcss.rule({ selector: 'a' }).toString() //=> "a {\n}" | |
*/ | |
postcss.rule = function (defaults) { | |
return new _rule2.default(defaults); | |
}; | |
/** | |
* Creates a new {@link Root} node. | |
* | |
* @param {object} [defaults] - properties for the new node. | |
* | |
* @return {Root} new Root node | |
* | |
* @example | |
* postcss.root({ after: '\n' }).toString() //=> "\n" | |
*/ | |
postcss.root = function (defaults) { | |
return new _root2.default(defaults); | |
}; | |
exports.default = postcss; | |
module.exports = exports['default']; | |
},{"./at-rule":12,"./comment":13,"./declaration":16,"./list":19,"./parse":22,"./processor":26,"./root":28,"./rule":29,"./stringify":31,"./vendor":34}],25:[function(require,module,exports){ | |
(function (Buffer){ | |
'use strict'; | |
exports.__esModule = true; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _sourceMap = require('source-map'); | |
var _sourceMap2 = _interopRequireDefault(_sourceMap); | |
var _path = require('path'); | |
var _path2 = _interopRequireDefault(_path); | |
var _fs = require('fs'); | |
var _fs2 = _interopRequireDefault(_fs); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function fromBase64(str) { | |
if (Buffer) { | |
if (Buffer.from && Buffer.from !== Uint8Array.from) { | |
return Buffer.from(str, 'base64').toString(); | |
} else { | |
return new Buffer(str, 'base64').toString(); | |
} | |
} else { | |
return window.atob(str); | |
} | |
} | |
/** | |
* Source map information from input CSS. | |
* For example, source map after Sass compiler. | |
* | |
* This class will automatically find source map in input CSS or in file system | |
* near input file (according `from` option). | |
* | |
* @example | |
* const root = postcss.parse(css, { from: 'a.sass.css' }); | |
* root.input.map //=> PreviousMap | |
*/ | |
var PreviousMap = function () { | |
/** | |
* @param {string} css - input CSS source | |
* @param {processOptions} [opts] - {@link Processor#process} options | |
*/ | |
function PreviousMap(css, opts) { | |
_classCallCheck(this, PreviousMap); | |
this.loadAnnotation(css); | |
/** | |
* @member {boolean} - Was source map inlined by data-uri to input CSS. | |
*/ | |
this.inline = this.startWith(this.annotation, 'data:'); | |
var prev = opts.map ? opts.map.prev : undefined; | |
var text = this.loadMap(opts.from, prev); | |
if (text) this.text = text; | |
} | |
/** | |
* Create a instance of `SourceMapGenerator` class | |
* from the `source-map` library to work with source map information. | |
* | |
* It is lazy method, so it will create object only on first call | |
* and then it will use cache. | |
* | |
* @return {SourceMapGenerator} object with source map information | |
*/ | |
PreviousMap.prototype.consumer = function consumer() { | |
if (!this.consumerCache) { | |
this.consumerCache = new _sourceMap2.default.SourceMapConsumer(this.text); | |
} | |
return this.consumerCache; | |
}; | |
/** | |
* Does source map contains `sourcesContent` with input source text. | |
* | |
* @return {boolean} Is `sourcesContent` present | |
*/ | |
PreviousMap.prototype.withContent = function withContent() { | |
return !!(this.consumer().sourcesContent && this.consumer().sourcesContent.length > 0); | |
}; | |
PreviousMap.prototype.startWith = function startWith(string, start) { | |
if (!string) return false; | |
return string.substr(0, start.length) === start; | |
}; | |
PreviousMap.prototype.loadAnnotation = function loadAnnotation(css) { | |
var match = css.match(/\/\*\s*# sourceMappingURL=(.*)\s*\*\//); | |
if (match) this.annotation = match[1].trim(); | |
}; | |
PreviousMap.prototype.decodeInline = function decodeInline(text) { | |
// data:application/json;charset=utf-8;base64, | |
// data:application/json;charset=utf8;base64, | |
// data:application/json;base64, | |
var baseUri = /^data:application\/json;(?:charset=utf-?8;)?base64,/; | |
var uri = 'data:application/json,'; | |
if (this.startWith(text, uri)) { | |
return decodeURIComponent(text.substr(uri.length)); | |
} else if (baseUri.test(text)) { | |
return fromBase64(text.substr(RegExp.lastMatch.length)); | |
} else { | |
var encoding = text.match(/data:application\/json;([^,]+),/)[1]; | |
throw new Error('Unsupported source map encoding ' + encoding); | |
} | |
}; | |
PreviousMap.prototype.loadMap = function loadMap(file, prev) { | |
if (prev === false) return false; | |
if (prev) { | |
if (typeof prev === 'string') { | |
return prev; | |
} else if (typeof prev === 'function') { | |
var prevPath = prev(file); | |
if (prevPath && _fs2.default.existsSync && _fs2.default.existsSync(prevPath)) { | |
return _fs2.default.readFileSync(prevPath, 'utf-8').toString().trim(); | |
} else { | |
throw new Error('Unable to load previous source map: ' + prevPath.toString()); | |
} | |
} else if (prev instanceof _sourceMap2.default.SourceMapConsumer) { | |
return _sourceMap2.default.SourceMapGenerator.fromSourceMap(prev).toString(); | |
} else if (prev instanceof _sourceMap2.default.SourceMapGenerator) { | |
return prev.toString(); | |
} else if (this.isMap(prev)) { | |
return JSON.stringify(prev); | |
} else { | |
throw new Error('Unsupported previous source map format: ' + prev.toString()); | |
} | |
} else if (this.inline) { | |
return this.decodeInline(this.annotation); | |
} else if (this.annotation) { | |
var map = this.annotation; | |
if (file) map = _path2.default.join(_path2.default.dirname(file), map); | |
this.root = _path2.default.dirname(map); | |
if (_fs2.default.existsSync && _fs2.default.existsSync(map)) { | |
return _fs2.default.readFileSync(map, 'utf-8').toString().trim(); | |
} else { | |
return false; | |
} | |
} | |
}; | |
PreviousMap.prototype.isMap = function isMap(map) { | |
if ((typeof map === 'undefined' ? 'undefined' : _typeof(map)) !== 'object') return false; | |
return typeof map.mappings === 'string' || typeof map._mappings === 'string'; | |
}; | |
return PreviousMap; | |
}(); | |
exports.default = PreviousMap; | |
module.exports = exports['default']; | |
}).call(this,require("buffer").Buffer) | |
},{"buffer":395,"fs":393,"path":397,"source-map":340}],26:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _lazyResult = require('./lazy-result'); | |
var _lazyResult2 = _interopRequireDefault(_lazyResult); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
/** | |
* Contains plugins to process CSS. Create one `Processor` instance, | |
* initialize its plugins, and then use that instance on numerous CSS files. | |
* | |
* @example | |
* const processor = postcss([autoprefixer, precss]); | |
* processor.process(css1).then(result => console.log(result.css)); | |
* processor.process(css2).then(result => console.log(result.css)); | |
*/ | |
var Processor = function () { | |
/** | |
* @param {Array.<Plugin|pluginFunction>|Processor} plugins - PostCSS | |
* plugins. See {@link Processor#use} for plugin format. | |
*/ | |
function Processor() { | |
var plugins = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; | |
_classCallCheck(this, Processor); | |
/** | |
* @member {string} - Current PostCSS version. | |
* | |
* @example | |
* if ( result.processor.version.split('.')[0] !== '6' ) { | |
* throw new Error('This plugin works only with PostCSS 6'); | |
* } | |
*/ | |
this.version = '6.0.23'; | |
/** | |
* @member {pluginFunction[]} - Plugins added to this processor. | |
* | |
* @example | |
* const processor = postcss([autoprefixer, precss]); | |
* processor.plugins.length //=> 2 | |
*/ | |
this.plugins = this.normalize(plugins); | |
} | |
/** | |
* Adds a plugin to be used as a CSS processor. | |
* | |
* PostCSS plugin can be in 4 formats: | |
* * A plugin created by {@link postcss.plugin} method. | |
* * A function. PostCSS will pass the function a @{link Root} | |
* as the first argument and current {@link Result} instance | |
* as the second. | |
* * An object with a `postcss` method. PostCSS will use that method | |
* as described in #2. | |
* * Another {@link Processor} instance. PostCSS will copy plugins | |
* from that instance into this one. | |
* | |
* Plugins can also be added by passing them as arguments when creating | |
* a `postcss` instance (see [`postcss(plugins)`]). | |
* | |
* Asynchronous plugins should return a `Promise` instance. | |
* | |
* @param {Plugin|pluginFunction|Processor} plugin - PostCSS plugin | |
* or {@link Processor} | |
* with plugins | |
* | |
* @example | |
* const processor = postcss() | |
* .use(autoprefixer) | |
* .use(precss); | |
* | |
* @return {Processes} current processor to make methods chain | |
*/ | |
Processor.prototype.use = function use(plugin) { | |
this.plugins = this.plugins.concat(this.normalize([plugin])); | |
return this; | |
}; | |
/** | |
* Parses source CSS and returns a {@link LazyResult} Promise proxy. | |
* Because some plugins can be asynchronous it doesn’t make | |
* any transformations. Transformations will be applied | |
* in the {@link LazyResult} methods. | |
* | |
* @param {string|toString|Result} css - String with input CSS or | |
* any object with a `toString()` | |
* method, like a Buffer. | |
* Optionally, send a {@link Result} | |
* instance and the processor will | |
* take the {@link Root} from it. | |
* @param {processOptions} [opts] - options | |
* | |
* @return {LazyResult} Promise proxy | |
* | |
* @example | |
* processor.process(css, { from: 'a.css', to: 'a.out.css' }) | |
* .then(result => { | |
* console.log(result.css); | |
* }); | |
*/ | |
Processor.prototype.process = function process(css) { | |
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
return new _lazyResult2.default(this, css, opts); | |
}; | |
Processor.prototype.normalize = function normalize(plugins) { | |
var normalized = []; | |
for (var _iterator = plugins, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var i = _ref; | |
if (i.postcss) i = i.postcss; | |
if ((typeof i === 'undefined' ? 'undefined' : _typeof(i)) === 'object' && Array.isArray(i.plugins)) { | |
normalized = normalized.concat(i.plugins); | |
} else if (typeof i === 'function') { | |
normalized.push(i); | |
} else if ((typeof i === 'undefined' ? 'undefined' : _typeof(i)) === 'object' && (i.parse || i.stringify)) { | |
throw new Error('PostCSS syntaxes cannot be used as plugins. ' + 'Instead, please use one of the ' + 'syntax/parser/stringifier options as ' + 'outlined in your PostCSS ' + 'runner documentation.'); | |
} else { | |
throw new Error(i + ' is not a PostCSS plugin'); | |
} | |
} | |
return normalized; | |
}; | |
return Processor; | |
}(); | |
exports.default = Processor; | |
/** | |
* @callback builder | |
* @param {string} part - part of generated CSS connected to this node | |
* @param {Node} node - AST node | |
* @param {"start"|"end"} [type] - node’s part type | |
*/ | |
/** | |
* @callback parser | |
* | |
* @param {string|toString} css - string with input CSS or any object | |
* with toString() method, like a Buffer | |
* @param {processOptions} [opts] - options with only `from` and `map` keys | |
* | |
* @return {Root} PostCSS AST | |
*/ | |
/** | |
* @callback stringifier | |
* | |
* @param {Node} node - start node for stringifing. Usually {@link Root}. | |
* @param {builder} builder - function to concatenate CSS from node’s parts | |
* or generate string and source map | |
* | |
* @return {void} | |
*/ | |
/** | |
* @typedef {object} syntax | |
* @property {parser} parse - function to generate AST by string | |
* @property {stringifier} stringify - function to generate string by AST | |
*/ | |
/** | |
* @typedef {object} toString | |
* @property {function} toString | |
*/ | |
/** | |
* @callback pluginFunction | |
* @param {Root} root - parsed input CSS | |
* @param {Result} result - result to set warnings or check other plugins | |
*/ | |
/** | |
* @typedef {object} Plugin | |
* @property {function} postcss - PostCSS plugin function | |
*/ | |
/** | |
* @typedef {object} processOptions | |
* @property {string} from - the path of the CSS source file. | |
* You should always set `from`, | |
* because it is used in source map | |
* generation and syntax error messages. | |
* @property {string} to - the path where you’ll put the output | |
* CSS file. You should always set `to` | |
* to generate correct source maps. | |
* @property {parser} parser - function to generate AST by string | |
* @property {stringifier} stringifier - class to generate string by AST | |
* @property {syntax} syntax - object with `parse` and `stringify` | |
* @property {object} map - source map options | |
* @property {boolean} map.inline - does source map should | |
* be embedded in the output | |
* CSS as a base64-encoded | |
* comment | |
* @property {string|object|false|function} map.prev - source map content | |
* from a previous | |
* processing step | |
* (for example, Sass). | |
* PostCSS will try to find | |
* previous map | |
* automatically, so you | |
* could disable it by | |
* `false` value. | |
* @property {boolean} map.sourcesContent - does PostCSS should set | |
* the origin content to map | |
* @property {string|false} map.annotation - does PostCSS should set | |
* annotation comment to map | |
* @property {string} map.from - override `from` in map’s | |
* `sources` | |
*/ | |
module.exports = exports['default']; | |
},{"./lazy-result":18}],27:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _warning = require('./warning'); | |
var _warning2 = _interopRequireDefault(_warning); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
/** | |
* Provides the result of the PostCSS transformations. | |
* | |
* A Result instance is returned by {@link LazyResult#then} | |
* or {@link Root#toResult} methods. | |
* | |
* @example | |
* postcss([cssnext]).process(css).then(function (result) { | |
* console.log(result.css); | |
* }); | |
* | |
* @example | |
* var result2 = postcss.parse(css).toResult(); | |
*/ | |
var Result = function () { | |
/** | |
* @param {Processor} processor - processor used for this transformation. | |
* @param {Root} root - Root node after all transformations. | |
* @param {processOptions} opts - options from the {@link Processor#process} | |
* or {@link Root#toResult} | |
*/ | |
function Result(processor, root, opts) { | |
_classCallCheck(this, Result); | |
/** | |
* @member {Processor} - The Processor instance used | |
* for this transformation. | |
* | |
* @example | |
* for ( let plugin of result.processor.plugins) { | |
* if ( plugin.postcssPlugin === 'postcss-bad' ) { | |
* throw 'postcss-good is incompatible with postcss-bad'; | |
* } | |
* }); | |
*/ | |
this.processor = processor; | |
/** | |
* @member {Message[]} - Contains messages from plugins | |
* (e.g., warnings or custom messages). | |
* Each message should have type | |
* and plugin properties. | |
* | |
* @example | |
* postcss.plugin('postcss-min-browser', () => { | |
* return (root, result) => { | |
* var browsers = detectMinBrowsersByCanIUse(root); | |
* result.messages.push({ | |
* type: 'min-browser', | |
* plugin: 'postcss-min-browser', | |
* browsers: browsers | |
* }); | |
* }; | |
* }); | |
*/ | |
this.messages = []; | |
/** | |
* @member {Root} - Root node after all transformations. | |
* | |
* @example | |
* root.toResult().root == root; | |
*/ | |
this.root = root; | |
/** | |
* @member {processOptions} - Options from the {@link Processor#process} | |
* or {@link Root#toResult} call | |
* that produced this Result instance. | |
* | |
* @example | |
* root.toResult(opts).opts == opts; | |
*/ | |
this.opts = opts; | |
/** | |
* @member {string} - A CSS string representing of {@link Result#root}. | |
* | |
* @example | |
* postcss.parse('a{}').toResult().css //=> "a{}" | |
*/ | |
this.css = undefined; | |
/** | |
* @member {SourceMapGenerator} - An instance of `SourceMapGenerator` | |
* class from the `source-map` library, | |
* representing changes | |
* to the {@link Result#root} instance. | |
* | |
* @example | |
* result.map.toJSON() //=> { version: 3, file: 'a.css', … } | |
* | |
* @example | |
* if ( result.map ) { | |
* fs.writeFileSync(result.opts.to + '.map', result.map.toString()); | |
* } | |
*/ | |
this.map = undefined; | |
} | |
/** | |
* Returns for @{link Result#css} content. | |
* | |
* @example | |
* result + '' === result.css | |
* | |
* @return {string} string representing of {@link Result#root} | |
*/ | |
Result.prototype.toString = function toString() { | |
return this.css; | |
}; | |
/** | |
* Creates an instance of {@link Warning} and adds it | |
* to {@link Result#messages}. | |
* | |
* @param {string} text - warning message | |
* @param {Object} [opts] - warning options | |
* @param {Node} opts.node - CSS node that caused the warning | |
* @param {string} opts.word - word in CSS source that caused the warning | |
* @param {number} opts.index - index in CSS node string that caused | |
* the warning | |
* @param {string} opts.plugin - name of the plugin that created | |
* this warning. {@link Result#warn} fills | |
* this property automatically. | |
* | |
* @return {Warning} created warning | |
*/ | |
Result.prototype.warn = function warn(text) { | |
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
if (!opts.plugin) { | |
if (this.lastPlugin && this.lastPlugin.postcssPlugin) { | |
opts.plugin = this.lastPlugin.postcssPlugin; | |
} | |
} | |
var warning = new _warning2.default(text, opts); | |
this.messages.push(warning); | |
return warning; | |
}; | |
/** | |
* Returns warnings from plugins. Filters {@link Warning} instances | |
* from {@link Result#messages}. | |
* | |
* @example | |
* result.warnings().forEach(warn => { | |
* console.warn(warn.toString()); | |
* }); | |
* | |
* @return {Warning[]} warnings from plugins | |
*/ | |
Result.prototype.warnings = function warnings() { | |
return this.messages.filter(function (i) { | |
return i.type === 'warning'; | |
}); | |
}; | |
/** | |
* An alias for the {@link Result#css} property. | |
* Use it with syntaxes that generate non-CSS output. | |
* @type {string} | |
* | |
* @example | |
* result.css === result.content; | |
*/ | |
_createClass(Result, [{ | |
key: 'content', | |
get: function get() { | |
return this.css; | |
} | |
}]); | |
return Result; | |
}(); | |
exports.default = Result; | |
/** | |
* @typedef {object} Message | |
* @property {string} type - message type | |
* @property {string} plugin - source PostCSS plugin name | |
*/ | |
module.exports = exports['default']; | |
},{"./warning":36}],28:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _container = require('./container'); | |
var _container2 = _interopRequireDefault(_container); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
/** | |
* Represents a CSS file and contains all its parsed nodes. | |
* | |
* @extends Container | |
* | |
* @example | |
* const root = postcss.parse('a{color:black} b{z-index:2}'); | |
* root.type //=> 'root' | |
* root.nodes.length //=> 2 | |
*/ | |
var Root = function (_Container) { | |
_inherits(Root, _Container); | |
function Root(defaults) { | |
_classCallCheck(this, Root); | |
var _this = _possibleConstructorReturn(this, _Container.call(this, defaults)); | |
_this.type = 'root'; | |
if (!_this.nodes) _this.nodes = []; | |
return _this; | |
} | |
Root.prototype.removeChild = function removeChild(child, ignore) { | |
var index = this.index(child); | |
if (!ignore && index === 0 && this.nodes.length > 1) { | |
this.nodes[1].raws.before = this.nodes[index].raws.before; | |
} | |
return _Container.prototype.removeChild.call(this, child); | |
}; | |
Root.prototype.normalize = function normalize(child, sample, type) { | |
var nodes = _Container.prototype.normalize.call(this, child); | |
if (sample) { | |
if (type === 'prepend') { | |
if (this.nodes.length > 1) { | |
sample.raws.before = this.nodes[1].raws.before; | |
} else { | |
delete sample.raws.before; | |
} | |
} else if (this.first !== sample) { | |
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | |
var _ref; | |
if (_isArray) { | |
if (_i >= _iterator.length) break; | |
_ref = _iterator[_i++]; | |
} else { | |
_i = _iterator.next(); | |
if (_i.done) break; | |
_ref = _i.value; | |
} | |
var node = _ref; | |
node.raws.before = sample.raws.before; | |
} | |
} | |
} | |
return nodes; | |
}; | |
/** | |
* Returns a {@link Result} instance representing the root’s CSS. | |
* | |
* @param {processOptions} [opts] - options with only `to` and `map` keys | |
* | |
* @return {Result} result with current root’s CSS | |
* | |
* @example | |
* const root1 = postcss.parse(css1, { from: 'a.css' }); | |
* const root2 = postcss.parse(css2, { from: 'b.css' }); | |
* root1.append(root2); | |
* const result = root1.toResult({ to: 'all.css', map: true }); | |
*/ | |
Root.prototype.toResult = function toResult() { | |
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | |
var LazyResult = require('./lazy-result'); | |
var Processor = require('./processor'); | |
var lazy = new LazyResult(new Processor(), this, opts); | |
return lazy.stringify(); | |
}; | |
/** | |
* @memberof Root# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `after`: the space symbols after the last child to the end of file. | |
* * `semicolon`: is the last child has an (optional) semicolon. | |
* | |
* @example | |
* postcss.parse('a {}\n').raws //=> { after: '\n' } | |
* postcss.parse('a {}').raws //=> { after: '' } | |
*/ | |
return Root; | |
}(_container2.default); | |
exports.default = Root; | |
module.exports = exports['default']; | |
},{"./container":14,"./lazy-result":18,"./processor":26}],29:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _container = require('./container'); | |
var _container2 = _interopRequireDefault(_container); | |
var _list = require('./list'); | |
var _list2 = _interopRequireDefault(_list); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | |
/** | |
* Represents a CSS rule: a selector followed by a declaration block. | |
* | |
* @extends Container | |
* | |
* @example | |
* const root = postcss.parse('a{}'); | |
* const rule = root.first; | |
* rule.type //=> 'rule' | |
* rule.toString() //=> 'a{}' | |
*/ | |
var Rule = function (_Container) { | |
_inherits(Rule, _Container); | |
function Rule(defaults) { | |
_classCallCheck(this, Rule); | |
var _this = _possibleConstructorReturn(this, _Container.call(this, defaults)); | |
_this.type = 'rule'; | |
if (!_this.nodes) _this.nodes = []; | |
return _this; | |
} | |
/** | |
* An array containing the rule’s individual selectors. | |
* Groups of selectors are split at commas. | |
* | |
* @type {string[]} | |
* | |
* @example | |
* const root = postcss.parse('a, b { }'); | |
* const rule = root.first; | |
* | |
* rule.selector //=> 'a, b' | |
* rule.selectors //=> ['a', 'b'] | |
* | |
* rule.selectors = ['a', 'strong']; | |
* rule.selector //=> 'a, strong' | |
*/ | |
_createClass(Rule, [{ | |
key: 'selectors', | |
get: function get() { | |
return _list2.default.comma(this.selector); | |
}, | |
set: function set(values) { | |
var match = this.selector ? this.selector.match(/,\s*/) : null; | |
var sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen'); | |
this.selector = values.join(sep); | |
} | |
/** | |
* @memberof Rule# | |
* @member {string} selector - the rule’s full selector represented | |
* as a string | |
* | |
* @example | |
* const root = postcss.parse('a, b { }'); | |
* const rule = root.first; | |
* rule.selector //=> 'a, b' | |
*/ | |
/** | |
* @memberof Rule# | |
* @member {object} raws - Information to generate byte-to-byte equal | |
* node string as it was in the origin input. | |
* | |
* Every parser saves its own properties, | |
* but the default CSS parser uses: | |
* | |
* * `before`: the space symbols before the node. It also stores `*` | |
* and `_` symbols before the declaration (IE hack). | |
* * `after`: the space symbols after the last child of the node | |
* to the end of the node. | |
* * `between`: the symbols between the property and value | |
* for declarations, selector and `{` for rules, or last parameter | |
* and `{` for at-rules. | |
* * `semicolon`: contains `true` if the last child has | |
* an (optional) semicolon. | |
* * `ownSemicolon`: contains `true` if there is semicolon after rule. | |
* | |
* PostCSS cleans selectors from comments and extra spaces, | |
* but it stores origin content in raws properties. | |
* As such, if you don’t change a declaration’s value, | |
* PostCSS will use the raw value with comments. | |
* | |
* @example | |
* const root = postcss.parse('a {\n color:black\n}') | |
* root.first.first.raws //=> { before: '', between: ' ', after: '\n' } | |
*/ | |
}]); | |
return Rule; | |
}(_container2.default); | |
exports.default = Rule; | |
module.exports = exports['default']; | |
},{"./container":14,"./list":19}],30:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var defaultRaw = { | |
colon: ': ', | |
indent: ' ', | |
beforeDecl: '\n', | |
beforeRule: '\n', | |
beforeOpen: ' ', | |
beforeClose: '\n', | |
beforeComment: '\n', | |
after: '\n', | |
emptyBody: '', | |
commentLeft: ' ', | |
commentRight: ' ' | |
}; | |
function capitalize(str) { | |
return str[0].toUpperCase() + str.slice(1); | |
} | |
var Stringifier = function () { | |
function Stringifier(builder) { | |
_classCallCheck(this, Stringifier); | |
this.builder = builder; | |
} | |
Stringifier.prototype.stringify = function stringify(node, semicolon) { | |
this[node.type](node, semicolon); | |
}; | |
Stringifier.prototype.root = function root(node) { | |
this.body(node); | |
if (node.raws.after) this.builder(node.raws.after); | |
}; | |
Stringifier.prototype.comment = function comment(node) { | |
var left = this.raw(node, 'left', 'commentLeft'); | |
var right = this.raw(node, 'right', 'commentRight'); | |
this.builder('/*' + left + node.text + right + '*/', node); | |
}; | |
Stringifier.prototype.decl = function decl(node, semicolon) { | |
var between = this.raw(node, 'between', 'colon'); | |
var string = node.prop + between + this.rawValue(node, 'value'); | |
if (node.important) { | |
string += node.raws.important || ' !important'; | |
} | |
if (semicolon) string += ';'; | |
this.builder(string, node); | |
}; | |
Stringifier.prototype.rule = function rule(node) { | |
this.block(node, this.rawValue(node, 'selector')); | |
if (node.raws.ownSemicolon) { | |
this.builder(node.raws.ownSemicolon, node, 'end'); | |
} | |
}; | |
Stringifier.prototype.atrule = function atrule(node, semicolon) { | |
var name = '@' + node.name; | |
var params = node.params ? this.rawValue(node, 'params') : ''; | |
if (typeof node.raws.afterName !== 'undefined') { | |
name += node.raws.afterName; | |
} else if (params) { | |
name += ' '; | |
} | |
if (node.nodes) { | |
this.block(node, name + params); | |
} else { | |
var end = (node.raws.between || '') + (semicolon ? ';' : ''); | |
this.builder(name + params + end, node); | |
} | |
}; | |
Stringifier.prototype.body = function body(node) { | |
var last = node.nodes.length - 1; | |
while (last > 0) { | |
if (node.nodes[last].type !== 'comment') break; | |
last -= 1; | |
} | |
var semicolon = this.raw(node, 'semicolon'); | |
for (var i = 0; i < node.nodes.length; i++) { | |
var child = node.nodes[i]; | |
var before = this.raw(child, 'before'); | |
if (before) this.builder(before); | |
this.stringify(child, last !== i || semicolon); | |
} | |
}; | |
Stringifier.prototype.block = function block(node, start) { | |
var between = this.raw(node, 'between', 'beforeOpen'); | |
this.builder(start + between + '{', node, 'start'); | |
var after = void 0; | |
if (node.nodes && node.nodes.length) { | |
this.body(node); | |
after = this.raw(node, 'after'); | |
} else { | |
after = this.raw(node, 'after', 'emptyBody'); | |
} | |
if (after) this.builder(after); | |
this.builder('}', node, 'end'); | |
}; | |
Stringifier.prototype.raw = function raw(node, own, detect) { | |
var value = void 0; | |
if (!detect) detect = own; | |
// Already had | |
if (own) { | |
value = node.raws[own]; | |
if (typeof value !== 'undefined') return value; | |
} | |
var parent = node.parent; | |
// Hack for first rule in CSS | |
if (detect === 'before') { | |
if (!parent || parent.type === 'root' && parent.first === node) { | |
return ''; | |
} | |
} | |
// Floating child without parent | |
if (!parent) return defaultRaw[detect]; | |
// Detect style by other nodes | |
var root = node.root(); | |
if (!root.rawCache) root.rawCache = {}; | |
if (typeof root.rawCache[detect] !== 'undefined') { | |
return root.rawCache[detect]; | |
} | |
if (detect === 'before' || detect === 'after') { | |
return this.beforeAfter(node, detect); | |
} else { | |
var method = 'raw' + capitalize(detect); | |
if (this[method]) { | |
value = this[method](root, node); | |
} else { | |
root.walk(function (i) { | |
value = i.raws[own]; | |
if (typeof value !== 'undefined') return false; | |
}); | |
} | |
} | |
if (typeof value === 'undefined') value = defaultRaw[detect]; | |
root.rawCache[detect] = value; | |
return value; | |
}; | |
Stringifier.prototype.rawSemicolon = function rawSemicolon(root) { | |
var value = void 0; | |
root.walk(function (i) { | |
if (i.nodes && i.nodes.length && i.last.type === 'decl') { | |
value = i.raws.semicolon; | |
if (typeof value !== 'undefined') return false; | |
} | |
}); | |
return value; | |
}; | |
Stringifier.prototype.rawEmptyBody = function rawEmptyBody(root) { | |
var value = void 0; | |
root.walk(function (i) { | |
if (i.nodes && i.nodes.length === 0) { | |
value = i.raws.after; | |
if (typeof value !== 'undefined') return false; | |
} | |
}); | |
return value; | |
}; | |
Stringifier.prototype.rawIndent = function rawIndent(root) { | |
if (root.raws.indent) return root.raws.indent; | |
var value = void 0; | |
root.walk(function (i) { | |
var p = i.parent; | |
if (p && p !== root && p.parent && p.parent === root) { | |
if (typeof i.raws.before !== 'undefined') { | |
var parts = i.raws.before.split('\n'); | |
value = parts[parts.length - 1]; | |
value = value.replace(/[^\s]/g, ''); | |
return false; | |
} | |
} | |
}); | |
return value; | |
}; | |
Stringifier.prototype.rawBeforeComment = function rawBeforeComment(root, node) { | |
var value = void 0; | |
root.walkComments(function (i) { | |
if (typeof i.raws.before !== 'undefined') { | |
value = i.raws.before; | |
if (value.indexOf('\n') !== -1) { | |
value = value.replace(/[^\n]+$/, ''); | |
} | |
return false; | |
} | |
}); | |
if (typeof value === 'undefined') { | |
value = this.raw(node, null, 'beforeDecl'); | |
} else if (value) { | |
value = value.replace(/[^\s]/g, ''); | |
} | |
return value; | |
}; | |
Stringifier.prototype.rawBeforeDecl = function rawBeforeDecl(root, node) { | |
var value = void 0; | |
root.walkDecls(function (i) { | |
if (typeof i.raws.before !== 'undefined') { | |
value = i.raws.before; | |
if (value.indexOf('\n') !== -1) { | |
value = value.replace(/[^\n]+$/, ''); | |
} | |
return false; | |
} | |
}); | |
if (typeof value === 'undefined') { | |
value = this.raw(node, null, 'beforeRule'); | |
} else if (value) { | |
value = value.replace(/[^\s]/g, ''); | |
} | |
return value; | |
}; | |
Stringifier.prototype.rawBeforeRule = function rawBeforeRule(root) { | |
var value = void 0; | |
root.walk(function (i) { | |
if (i.nodes && (i.parent !== root || root.first !== i)) { | |
if (typeof i.raws.before !== 'undefined') { | |
value = i.raws.before; | |
if (value.indexOf('\n') !== -1) { | |
value = value.replace(/[^\n]+$/, ''); | |
} | |
return false; | |
} | |
} | |
}); | |
if (value) value = value.replace(/[^\s]/g, ''); | |
return value; | |
}; | |
Stringifier.prototype.rawBeforeClose = function rawBeforeClose(root) { | |
var value = void 0; | |
root.walk(function (i) { | |
if (i.nodes && i.nodes.length > 0) { | |
if (typeof i.raws.after !== 'undefined') { | |
value = i.raws.after; | |
if (value.indexOf('\n') !== -1) { | |
value = value.replace(/[^\n]+$/, ''); | |
} | |
return false; | |
} | |
} | |
}); | |
if (value) value = value.replace(/[^\s]/g, ''); | |
return value; | |
}; | |
Stringifier.prototype.rawBeforeOpen = function rawBeforeOpen(root) { | |
var value = void 0; | |
root.walk(function (i) { | |
if (i.type !== 'decl') { | |
value = i.raws.between; | |
if (typeof value !== 'undefined') return false; | |
} | |
}); | |
return value; | |
}; | |
Stringifier.prototype.rawColon = function rawColon(root) { | |
var value = void 0; | |
root.walkDecls(function (i) { | |
if (typeof i.raws.between !== 'undefined') { | |
value = i.raws.between.replace(/[^\s:]/g, ''); | |
return false; | |
} | |
}); | |
return value; | |
}; | |
Stringifier.prototype.beforeAfter = function beforeAfter(node, detect) { | |
var value = void 0; | |
if (node.type === 'decl') { | |
value = this.raw(node, null, 'beforeDecl'); | |
} else if (node.type === 'comment') { | |
value = this.raw(node, null, 'beforeComment'); | |
} else if (detect === 'before') { | |
value = this.raw(node, null, 'beforeRule'); | |
} else { | |
value = this.raw(node, null, 'beforeClose'); | |
} | |
var buf = node.parent; | |
var depth = 0; | |
while (buf && buf.type !== 'root') { | |
depth += 1; | |
buf = buf.parent; | |
} | |
if (value.indexOf('\n') !== -1) { | |
var indent = this.raw(node, null, 'indent'); | |
if (indent.length) { | |
for (var step = 0; step < depth; step++) { | |
value += indent; | |
} | |
} | |
} | |
return value; | |
}; | |
Stringifier.prototype.rawValue = function rawValue(node, prop) { | |
var value = node[prop]; | |
var raw = node.raws[prop]; | |
if (raw && raw.value === value) { | |
return raw.raw; | |
} else { | |
return value; | |
} | |
}; | |
return Stringifier; | |
}(); | |
exports.default = Stringifier; | |
module.exports = exports['default']; | |
},{}],31:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
exports.default = stringify; | |
var _stringifier = require('./stringifier'); | |
var _stringifier2 = _interopRequireDefault(_stringifier); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function stringify(node, builder) { | |
var str = new _stringifier2.default(builder); | |
str.stringify(node); | |
} | |
module.exports = exports['default']; | |
},{"./stringifier":30}],32:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _chalk = require('chalk'); | |
var _chalk2 = _interopRequireDefault(_chalk); | |
var _tokenize = require('./tokenize'); | |
var _tokenize2 = _interopRequireDefault(_tokenize); | |
var _input = require('./input'); | |
var _input2 = _interopRequireDefault(_input); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
var HIGHLIGHT_THEME = { | |
'brackets': _chalk2.default.cyan, | |
'at-word': _chalk2.default.cyan, | |
'call': _chalk2.default.cyan, | |
'comment': _chalk2.default.gray, | |
'string': _chalk2.default.green, | |
'class': _chalk2.default.yellow, | |
'hash': _chalk2.default.magenta, | |
'(': _chalk2.default.cyan, | |
')': _chalk2.default.cyan, | |
'{': _chalk2.default.yellow, | |
'}': _chalk2.default.yellow, | |
'[': _chalk2.default.yellow, | |
']': _chalk2.default.yellow, | |
':': _chalk2.default.yellow, | |
';': _chalk2.default.yellow | |
}; | |
function getTokenType(_ref, processor) { | |
var type = _ref[0], | |
value = _ref[1]; | |
if (type === 'word') { | |
if (value[0] === '.') { | |
return 'class'; | |
} | |
if (value[0] === '#') { | |
return 'hash'; | |
} | |
} | |
if (!processor.endOfFile()) { | |
var next = processor.nextToken(); | |
processor.back(next); | |
if (next[0] === 'brackets' || next[0] === '(') return 'call'; | |
} | |
return type; | |
} | |
function terminalHighlight(css) { | |
var processor = (0, _tokenize2.default)(new _input2.default(css), { ignoreErrors: true }); | |
var result = ''; | |
var _loop = function _loop() { | |
var token = processor.nextToken(); | |
var color = HIGHLIGHT_THEME[getTokenType(token, processor)]; | |
if (color) { | |
result += token[1].split(/\r?\n/).map(function (i) { | |
return color(i); | |
}).join('\n'); | |
} else { | |
result += token[1]; | |
} | |
}; | |
while (!processor.endOfFile()) { | |
_loop(); | |
} | |
return result; | |
} | |
exports.default = terminalHighlight; | |
module.exports = exports['default']; | |
},{"./input":17,"./tokenize":33,"chalk":393}],33:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
exports.default = tokenizer; | |
var SINGLE_QUOTE = 39; | |
var DOUBLE_QUOTE = 34; | |
var BACKSLASH = 92; | |
var SLASH = 47; | |
var NEWLINE = 10; | |
var SPACE = 32; | |
var FEED = 12; | |
var TAB = 9; | |
var CR = 13; | |
var OPEN_SQUARE = 91; | |
var CLOSE_SQUARE = 93; | |
var OPEN_PARENTHESES = 40; | |
var CLOSE_PARENTHESES = 41; | |
var OPEN_CURLY = 123; | |
var CLOSE_CURLY = 125; | |
var SEMICOLON = 59; | |
var ASTERISK = 42; | |
var COLON = 58; | |
var AT = 64; | |
var RE_AT_END = /[ \n\t\r\f\{\}\(\)'"\\;/\[\]#]/g; | |
var RE_WORD_END = /[ \n\t\r\f\(\)\{\}:;@!'"\\\]\[#]|\/(?=\*)/g; | |
var RE_BAD_BRACKET = /.[\\\/\("'\n]/; | |
var RE_HEX_ESCAPE = /[a-f0-9]/i; | |
function tokenizer(input) { | |
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
var css = input.css.valueOf(); | |
var ignore = options.ignoreErrors; | |
var code = void 0, | |
next = void 0, | |
quote = void 0, | |
lines = void 0, | |
last = void 0, | |
content = void 0, | |
escape = void 0, | |
nextLine = void 0, | |
nextOffset = void 0, | |
escaped = void 0, | |
escapePos = void 0, | |
prev = void 0, | |
n = void 0, | |
currentToken = void 0; | |
var length = css.length; | |
var offset = -1; | |
var line = 1; | |
var pos = 0; | |
var buffer = []; | |
var returned = []; | |
function unclosed(what) { | |
throw input.error('Unclosed ' + what, line, pos - offset); | |
} | |
function endOfFile() { | |
return returned.length === 0 && pos >= length; | |
} | |
function nextToken() { | |
if (returned.length) return returned.pop(); | |
if (pos >= length) return; | |
code = css.charCodeAt(pos); | |
if (code === NEWLINE || code === FEED || code === CR && css.charCodeAt(pos + 1) !== NEWLINE) { | |
offset = pos; | |
line += 1; | |
} | |
switch (code) { | |
case NEWLINE: | |
case SPACE: | |
case TAB: | |
case CR: | |
case FEED: | |
next = pos; | |
do { | |
next += 1; | |
code = css.charCodeAt(next); | |
if (code === NEWLINE) { | |
offset = next; | |
line += 1; | |
} | |
} while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED); | |
currentToken = ['space', css.slice(pos, next)]; | |
pos = next - 1; | |
break; | |
case OPEN_SQUARE: | |
currentToken = ['[', '[', line, pos - offset]; | |
break; | |
case CLOSE_SQUARE: | |
currentToken = [']', ']', line, pos - offset]; | |
break; | |
case OPEN_CURLY: | |
currentToken = ['{', '{', line, pos - offset]; | |
break; | |
case CLOSE_CURLY: | |
currentToken = ['}', '}', line, pos - offset]; | |
break; | |
case COLON: | |
currentToken = [':', ':', line, pos - offset]; | |
break; | |
case SEMICOLON: | |
currentToken = [';', ';', line, pos - offset]; | |
break; | |
case OPEN_PARENTHESES: | |
prev = buffer.length ? buffer.pop()[1] : ''; | |
n = css.charCodeAt(pos + 1); | |
if (prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE && n !== SPACE && n !== NEWLINE && n !== TAB && n !== FEED && n !== CR) { | |
next = pos; | |
do { | |
escaped = false; | |
next = css.indexOf(')', next + 1); | |
if (next === -1) { | |
if (ignore) { | |
next = pos; | |
break; | |
} else { | |
unclosed('bracket'); | |
} | |
} | |
escapePos = next; | |
while (css.charCodeAt(escapePos - 1) === BACKSLASH) { | |
escapePos -= 1; | |
escaped = !escaped; | |
} | |
} while (escaped); | |
currentToken = ['brackets', css.slice(pos, next + 1), line, pos - offset, line, next - offset]; | |
pos = next; | |
} else { | |
next = css.indexOf(')', pos + 1); | |
content = css.slice(pos, next + 1); | |
if (next === -1 || RE_BAD_BRACKET.test(content)) { | |
currentToken = ['(', '(', line, pos - offset]; | |
} else { | |
currentToken = ['brackets', content, line, pos - offset, line, next - offset]; | |
pos = next; | |
} | |
} | |
break; | |
case CLOSE_PARENTHESES: | |
currentToken = [')', ')', line, pos - offset]; | |
break; | |
case SINGLE_QUOTE: | |
case DOUBLE_QUOTE: | |
quote = code === SINGLE_QUOTE ? '\'' : '"'; | |
next = pos; | |
do { | |
escaped = false; | |
next = css.indexOf(quote, next + 1); | |
if (next === -1) { | |
if (ignore) { | |
next = pos + 1; | |
break; | |
} else { | |
unclosed('string'); | |
} | |
} | |
escapePos = next; | |
while (css.charCodeAt(escapePos - 1) === BACKSLASH) { | |
escapePos -= 1; | |
escaped = !escaped; | |
} | |
} while (escaped); | |
content = css.slice(pos, next + 1); | |
lines = content.split('\n'); | |
last = lines.length - 1; | |
if (last > 0) { | |
nextLine = line + last; | |
nextOffset = next - lines[last].length; | |
} else { | |
nextLine = line; | |
nextOffset = offset; | |
} | |
currentToken = ['string', css.slice(pos, next + 1), line, pos - offset, nextLine, next - nextOffset]; | |
offset = nextOffset; | |
line = nextLine; | |
pos = next; | |
break; | |
case AT: | |
RE_AT_END.lastIndex = pos + 1; | |
RE_AT_END.test(css); | |
if (RE_AT_END.lastIndex === 0) { | |
next = css.length - 1; | |
} else { | |
next = RE_AT_END.lastIndex - 2; | |
} | |
currentToken = ['at-word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]; | |
pos = next; | |
break; | |
case BACKSLASH: | |
next = pos; | |
escape = true; | |
while (css.charCodeAt(next + 1) === BACKSLASH) { | |
next += 1; | |
escape = !escape; | |
} | |
code = css.charCodeAt(next + 1); | |
if (escape && code !== SLASH && code !== SPACE && code !== NEWLINE && code !== TAB && code !== CR && code !== FEED) { | |
next += 1; | |
if (RE_HEX_ESCAPE.test(css.charAt(next))) { | |
while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) { | |
next += 1; | |
} | |
if (css.charCodeAt(next + 1) === SPACE) { | |
next += 1; | |
} | |
} | |
} | |
currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]; | |
pos = next; | |
break; | |
default: | |
if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) { | |
next = css.indexOf('*/', pos + 2) + 1; | |
if (next === 0) { | |
if (ignore) { | |
next = css.length; | |
} else { | |
unclosed('comment'); | |
} | |
} | |
content = css.slice(pos, next + 1); | |
lines = content.split('\n'); | |
last = lines.length - 1; | |
if (last > 0) { | |
nextLine = line + last; | |
nextOffset = next - lines[last].length; | |
} else { | |
nextLine = line; | |
nextOffset = offset; | |
} | |
currentToken = ['comment', content, line, pos - offset, nextLine, next - nextOffset]; | |
offset = nextOffset; | |
line = nextLine; | |
pos = next; | |
} else { | |
RE_WORD_END.lastIndex = pos + 1; | |
RE_WORD_END.test(css); | |
if (RE_WORD_END.lastIndex === 0) { | |
next = css.length - 1; | |
} else { | |
next = RE_WORD_END.lastIndex - 2; | |
} | |
currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]; | |
buffer.push(currentToken); | |
pos = next; | |
} | |
break; | |
} | |
pos++; | |
return currentToken; | |
} | |
function back(token) { | |
returned.push(token); | |
} | |
return { | |
back: back, | |
nextToken: nextToken, | |
endOfFile: endOfFile | |
}; | |
} | |
module.exports = exports['default']; | |
},{}],34:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
/** | |
* Contains helpers for working with vendor prefixes. | |
* | |
* @example | |
* const vendor = postcss.vendor; | |
* | |
* @namespace vendor | |
*/ | |
var vendor = { | |
/** | |
* Returns the vendor prefix extracted from an input string. | |
* | |
* @param {string} prop - string with or without vendor prefix | |
* | |
* @return {string} vendor prefix or empty string | |
* | |
* @example | |
* postcss.vendor.prefix('-moz-tab-size') //=> '-moz-' | |
* postcss.vendor.prefix('tab-size') //=> '' | |
*/ | |
prefix: function prefix(prop) { | |
var match = prop.match(/^(-\w+-)/); | |
if (match) { | |
return match[0]; | |
} else { | |
return ''; | |
} | |
}, | |
/** | |
* Returns the input string stripped of its vendor prefix. | |
* | |
* @param {string} prop - string with or without vendor prefix | |
* | |
* @return {string} string name without vendor prefixes | |
* | |
* @example | |
* postcss.vendor.unprefixed('-moz-tab-size') //=> 'tab-size' | |
*/ | |
unprefixed: function unprefixed(prop) { | |
return prop.replace(/^-\w+-/, ''); | |
} | |
}; | |
exports.default = vendor; | |
module.exports = exports['default']; | |
},{}],35:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
exports.default = warnOnce; | |
var printed = {}; | |
function warnOnce(message) { | |
if (printed[message]) return; | |
printed[message] = true; | |
if (typeof console !== 'undefined' && console.warn) console.warn(message); | |
} | |
module.exports = exports['default']; | |
},{}],36:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
/** | |
* Represents a plugin’s warning. It can be created using {@link Node#warn}. | |
* | |
* @example | |
* if ( decl.important ) { | |
* decl.warn(result, 'Avoid !important', { word: '!important' }); | |
* } | |
*/ | |
var Warning = function () { | |
/** | |
* @param {string} text - warning message | |
* @param {Object} [opts] - warning options | |
* @param {Node} opts.node - CSS node that caused the warning | |
* @param {string} opts.word - word in CSS source that caused the warning | |
* @param {number} opts.index - index in CSS node string that caused | |
* the warning | |
* @param {string} opts.plugin - name of the plugin that created | |
* this warning. {@link Result#warn} fills | |
* this property automatically. | |
*/ | |
function Warning(text) { | |
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
_classCallCheck(this, Warning); | |
/** | |
* @member {string} - Type to filter warnings from | |
* {@link Result#messages}. Always equal | |
* to `"warning"`. | |
* | |
* @example | |
* const nonWarning = result.messages.filter(i => i.type !== 'warning') | |
*/ | |
this.type = 'warning'; | |
/** | |
* @member {string} - The warning message. | |
* | |
* @example | |
* warning.text //=> 'Try to avoid !important' | |
*/ | |
this.text = text; | |
if (opts.node && opts.node.source) { | |
var pos = opts.node.positionBy(opts); | |
/** | |
* @member {number} - Line in the input file | |
* with this warning’s source | |
* | |
* @example | |
* warning.line //=> 5 | |
*/ | |
this.line = pos.line; | |
/** | |
* @member {number} - Column in the input file | |
* with this warning’s source. | |
* | |
* @example | |
* warning.column //=> 6 | |
*/ | |
this.column = pos.column; | |
} | |
for (var opt in opts) { | |
this[opt] = opts[opt]; | |
} | |
} | |
/** | |
* Returns a warning position and message. | |
* | |
* @example | |
* warning.toString() //=> 'postcss-lint:a.css:10:14: Avoid !important' | |
* | |
* @return {string} warning position and message | |
*/ | |
Warning.prototype.toString = function toString() { | |
if (this.node) { | |
return this.node.error(this.text, { | |
plugin: this.plugin, | |
index: this.index, | |
word: this.word | |
}).message; | |
} else if (this.plugin) { | |
return this.plugin + ': ' + this.text; | |
} else { | |
return this.text; | |
} | |
}; | |
/** | |
* @memberof Warning# | |
* @member {string} plugin - The name of the plugin that created | |
* it will fill this property automatically. | |
* this warning. When you call {@link Node#warn} | |
* | |
* @example | |
* warning.plugin //=> 'postcss-important' | |
*/ | |
/** | |
* @memberof Warning# | |
* @member {Node} node - Contains the CSS node that caused the warning. | |
* | |
* @example | |
* warning.node.toString() //=> 'color: white !important' | |
*/ | |
return Warning; | |
}(); | |
exports.default = Warning; | |
module.exports = exports['default']; | |
},{}],37:[function(require,module,exports){ | |
(function (__dirname){ | |
'use strict'; | |
const fs = require('fs'); | |
const path = require('path'); | |
const postcss = require('postcss'); | |
const timsort = require('timsort').sort; | |
module.exports = postcss.plugin('css-declaration-sorter', function (options) { | |
return function (css) { | |
let sortOrderPath; | |
options = options || {}; | |
// Use included sorting order if order is passed and not alphabetically | |
if (options.order && options.order !== 'alphabetically') { | |
sortOrderPath = path.join(__dirname, '../orders/', options.order) + '.json'; | |
} else if (options.customOrder) { | |
sortOrderPath = options.customOrder; | |
} else { | |
// Fallback to the default sorting order | |
return processCss(css, 'alphabetically'); | |
} | |
// Load in the array containing the order from a JSON file | |
return new Promise(function (resolve, reject) { | |
fs.readFile(sortOrderPath, function (error, data) { | |
if (error) return reject(error); | |
resolve(data); | |
}); | |
}).then(function (data) { | |
return processCss(css, JSON.parse(data)); | |
}); | |
}; | |
}); | |
function processCss (css, sortOrder) { | |
const comments = []; | |
const rulesCache = []; | |
css.walk(function (node) { | |
const nodes = node.nodes; | |
const type = node.type; | |
if (type === 'comment') { | |
// Don't do anything to root comments or the last newline comment | |
const isNewlineNode = ~node.raws.before.indexOf('\n'); | |
const lastNewlineNode = isNewlineNode && !node.next(); | |
const onlyNode = !node.prev() && !node.next(); | |
if (lastNewlineNode || onlyNode || node.parent.type === 'root') { | |
return; | |
} | |
if (isNewlineNode) { | |
const pairedNode = node.next() ? node.next() : node.prev().prev(); | |
if (pairedNode) { | |
comments.unshift({ | |
'comment': node, | |
'pairedNode': pairedNode, | |
'insertPosition': node.next() ? 'Before' : 'After', | |
}); | |
node.remove(); | |
} | |
} else { | |
const pairedNode = node.prev() ? node.prev() : node.next().next(); | |
if (pairedNode) { | |
comments.push({ | |
'comment': node, | |
'pairedNode': pairedNode, | |
'insertPosition': 'After', | |
}); | |
node.remove(); | |
} | |
} | |
return; | |
} | |
// Add rule-like nodes to a cache so that we can remove all | |
// comment nodes before we start sorting. | |
const isRule = type === 'rule' || type === 'atrule'; | |
if (isRule && nodes && nodes.length > 1) { | |
rulesCache.push(nodes); | |
} | |
}); | |
// Perform a sort once all comment nodes are removed | |
rulesCache.forEach(function (nodes) { | |
sortCssDecls(nodes, sortOrder); | |
}); | |
// Add comments back to the nodes they are paired with | |
comments.forEach(function (node) { | |
const pairedNode = node.pairedNode; | |
node.comment.remove(); | |
pairedNode.parent['insert' + node.insertPosition](pairedNode, node.comment); | |
}); | |
} | |
// Sort CSS declarations alphabetically or using the set sorting order | |
function sortCssDecls (cssDecls, sortOrder) { | |
if (sortOrder === 'alphabetically') { | |
timsort(cssDecls, function (a, b) { | |
if (a.type === 'decl' && b.type === 'decl') { | |
return comparator(a.prop, b.prop); | |
} else { | |
return compareDifferentType(a, b); | |
} | |
}); | |
} else { | |
timsort(cssDecls, function (a, b) { | |
if (a.type === 'decl' && b.type === 'decl') { | |
const aIndex = sortOrder.indexOf(a.prop); | |
const bIndex = sortOrder.indexOf(b.prop); | |
return comparator(aIndex, bIndex); | |
} else { | |
return compareDifferentType(a, b); | |
} | |
}); | |
} | |
} | |
function comparator (a, b) { | |
return a === b ? 0 : a < b ? -1 : 1; | |
} | |
function compareDifferentType (a, b) { | |
if (b.type === 'atrule') { return 0; } | |
return (a.type === 'decl') ? -1 : (b.type === 'decl') ? 1 : 0; | |
} | |
}).call(this,"/node_modules/css-declaration-sorter/src") | |
},{"fs":394,"path":397,"postcss":24,"timsort":389}],38:[function(require,module,exports){ | |
module.exports={"generic":true,"types":{"absolute-size":"xx-small | x-small | small | medium | large | x-large | xx-large","alpha-value":"<number> | <percentage>","angle-percentage":"<angle> | <percentage>","animateable-feature":"scroll-position | contents | <custom-ident>","attachment":"scroll | fixed | local","auto-repeat":"repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )","auto-track-list":"[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat> [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?","baseline-position":"[ first | last ]? baseline","basic-shape":"<inset()> | <circle()> | <ellipse()> | <polygon()>","bg-image":"none | <image>","bg-layer":"<bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <box>","bg-position":"[ [ left | center | right | top | bottom | <length-percentage> ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] | [ center | [ left | right ] <length-percentage>? ] && [ center | [ top | bottom ] <length-percentage>? ] ]","bg-size":"[ <length-percentage> | auto ]{1,2} | cover | contain","blur()":"blur( <length> )","blend-mode":"normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity","box":"border-box | padding-box | content-box","br-style":"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset","br-width":"<length> | thin | medium | thick","brightness()":"brightness( <number-percentage> )","calc()":"calc( <calc-sum> )","calc-sum":"<calc-product> [ [ '+' | '-' ] <calc-product> ]*","calc-product":"<calc-value> [ '*' <calc-value> | '/' <number> ]*","calc-value":"<number> | <dimension> | <percentage> | ( <calc-sum> )","cf-final-image":"<image> | <color>","cf-mixing-image":"<percentage>? && <image>","circle()":"circle( [ <shape-radius> ]? [ at <position> ]? )","clip-source":"<url>","color":"<rgb()> | <rgba()> | <hsl()> | <hsla()> | <hex-color> | <named-color> | currentcolor | <deprecated-system-color>","color-stop":"<color> <length-percentage>?","color-stop-list":"<color-stop>#{2,}","common-lig-values":"[ common-ligatures | no-common-ligatures ]","composite-style":"clear | copy | source-over | source-in | source-out | source-atop | destination-over | destination-in | destination-out | destination-atop | xor","compositing-operator":"add | subtract | intersect | exclude","contextual-alt-values":"[ contextual | no-contextual ]","content-distribution":"space-between | space-around | space-evenly | stretch","content-list":"[ <string> | contents | <url> | <quote> | <attr()> | counter( <ident> , <'list-style-type'>? ) ]+","content-position":"center | start | end | flex-start | flex-end","content-replacement":"<image>","contrast()":"contrast( [ <number-percentage> ] )","counter-style":"<counter-style-name> | symbols( )","counter-style-name":"<custom-ident>","cross-fade()":"cross-fade( <cf-mixing-image> , <cf-final-image>? )","cubic-bezier-timing-function":"ease | ease-in | ease-out | ease-in-out | cubic-bezier( <number> , <number> , <number> , <number> )","deprecated-system-color":"ActiveBorder | ActiveCaption | AppWorkspace | Background | ButtonFace | ButtonHighlight | ButtonShadow | ButtonText | CaptionText | GrayText | Highlight | HighlightText | InactiveBorder | InactiveCaption | InactiveCaptionText | InfoBackground | InfoText | Menu | MenuText | Scrollbar | ThreeDDarkShadow | ThreeDFace | ThreeDHighlight | ThreeDLightShadow | ThreeDShadow | Window | WindowFrame | WindowText","discretionary-lig-values":"[ discretionary-ligatures | no-discretionary-ligatures ]","display-box":"contents | none","display-inside":"flow | flow-root | table | flex | grid | subgrid | ruby","display-internal":"table-row-group | table-header-group | table-footer-group | table-row | table-cell | table-column-group | table-column | table-caption | ruby-base | ruby-text | ruby-base-container | ruby-text-container","display-legacy":"inline-block | inline-list-item | inline-table | inline-flex | inline-grid","display-listitem":"<display-outside>? && [ flow | flow-root ]? && list-item","display-outside":"block | inline | run-in","drop-shadow()":"drop-shadow( <length>{2,3} <color>? )","east-asian-variant-values":"[ jis78 | jis83 | jis90 | jis04 | simplified | traditional ]","east-asian-width-values":"[ full-width | proportional-width ]","element()":"element( <id-selector> )","ellipse()":"ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )","ending-shape":"circle | ellipse","explicit-track-list":"[ <line-names>? <track-size> ]+ <line-names>?","family-name":"<string> | <custom-ident>+","feature-tag-value":"<string> [ <integer> | on | off ]?","feature-value-name":"<custom-ident>","fill-rule":"nonzero | evenodd","filter-function":"<blur()> | <brightness()> | <contrast()> | <drop-shadow()> | <grayscale()> | <hue-rotate()> | <invert()> | <opacity()> | <saturate()> | <sepia()>","filter-function-list":"[ <filter-function> | <url> ]+","final-bg-layer":"<'background-color'> || <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <box>","fit-content()":"fit-content( [ <length> | <percentage> ] )","fixed-breadth":"<length-percentage>","fixed-repeat":"repeat( [ <positive-integer> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )","fixed-size":"<fixed-breadth> | minmax( <fixed-breadth> , <track-breadth> ) | minmax( <inflexible-breadth> , <fixed-breadth> )","font-variant-css21":"[ normal | small-caps ]","frames-timing-function":"frames( <integer> )","frequency-percentage":"<frequency> | <percentage>","generic-family":"serif | sans-serif | cursive | fantasy | monospace | -apple-system","generic-name":"serif | sans-serif | cursive | fantasy | monospace","geometry-box":"<shape-box> | fill-box | stroke-box | view-box","gradient":"<-legacy-gradient> | <linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()>","grayscale()":"grayscale( <number-percentage> )","grid-line":"auto | <custom-ident> | [ <integer> && <custom-ident>? ] | [ span && [ <integer> || <custom-ident> ] ]","historical-lig-values":"[ historical-ligatures | no-historical-ligatures ]","hsl()":"hsl( <hue> <percentage> <percentage> [ / <alpha-value> ]? ) | hsl( <hue> , <percentage> , <percentage> , <alpha-value>? )","hsla()":"hsla( <hue> <percentage> <percentage> [ / <alpha-value> ]? ) | hsla( <hue> , <percentage> , <percentage> , <alpha-value>? )","hue":"<number> | <angle>","hue-rotate()":"hue-rotate( <angle> )","image":"<url> | <image()> | <image-set()> | <element()> | <cross-fade()> | <gradient>","image()":"image( [ [ <image> | <string> ]? , <color>? ]! )","image-set()":"image-set( <image-set-option># )","image-set-option":"[ <image> | <string> ] <resolution>","inflexible-breadth":"<length> | <percentage> | min-content | max-content | auto","inset()":"inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )","invert()":"invert( <number-percentage> )","keyframes-name":"<custom-ident> | <string>","keyframe-selector":"from | to | <percentage>","leader()":"leader( <leader-type> )","leader-type":"dotted | solid | space | <string>","length-percentage":"<length> | <percentage>","line-names":"'[' <custom-ident>* ']'","line-name-list":"[ <line-names> | <name-repeat> ]+","linear-gradient()":"linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )","mask-layer":"<mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator> || <masking-mode>","mask-position":"[ <length-percentage> | left | center | right ] [ <length-percentage> | top | center | bottom ]?","mask-reference":"none | <image> | <mask-source>","mask-source":"<url>","masking-mode":"alpha | luminance | match-source","matrix()":"matrix( <number> [, <number> ]{5} )","matrix3d()":"matrix3d( <number> [, <number> ]{15} )","media-type":"<ident>","mf-boolean":"<mf-name>","mf-name":"<ident>","minmax()":"minmax( [ <length> | <percentage> | <flex> | min-content | max-content | auto ] , [ <length> | <percentage> | <flex> | min-content | max-content | auto ] )","named-color":"transparent | 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 | darkgrey | darkkhaki | darkmagenta | darkolivegreen | darkorange | darkorchid | darkred | darksalmon | darkseagreen | darkslateblue | darkslategray | darkslategrey | darkturquoise | darkviolet | deeppink | deepskyblue | dimgray | dimgrey | dodgerblue | firebrick | floralwhite | forestgreen | fuchsia | gainsboro | ghostwhite | gold | goldenrod | gray | green | greenyellow | grey | honeydew | hotpink | indianred | indigo | ivory | khaki | lavender | lavenderblush | lawngreen | lemonchiffon | lightblue | lightcoral | lightcyan | lightgoldenrodyellow | lightgray | lightgreen | lightgrey | lightpink | lightsalmon | lightseagreen | lightskyblue | lightslategray | lightslategrey | 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 | rebeccapurple | red | rosybrown | royalblue | saddlebrown | salmon | sandybrown | seagreen | seashell | sienna | silver | skyblue | slateblue | slategray | slategrey | snow | springgreen | steelblue | tan | teal | thistle | tomato | turquoise | violet | wheat | white | whitesmoke | yellow | yellowgreen | <-non-standard-color>","namespace-prefix":"<ident>","number-percentage":"<number> | <percentage>","numeric-figure-values":"[ lining-nums | oldstyle-nums ]","numeric-fraction-values":"[ diagonal-fractions | stacked-fractions ]","numeric-spacing-values":"[ proportional-nums | tabular-nums ]","opacity()":"opacity( [ <number-percentage> ] )","overflow-position":"unsafe | safe","outline-radius":"<border-radius>","perspective()":"perspective( <length> )","polygon()":"polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )","position":"[ [ left | center | right ] || [ top | center | bottom ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]? | [ [ left | right ] <length-percentage> ] && [ [ top | bottom ] <length-percentage> ] ]","quote":"open-quote | close-quote | no-open-quote | no-close-quote","radial-gradient()":"radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )","relative-size":"larger | smaller","repeat-style":"repeat-x | repeat-y | [ repeat | space | round | no-repeat ]{1,2}","repeating-linear-gradient()":"repeating-linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )","repeating-radial-gradient()":"repeating-radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )","rgb()":"rgb( <percentage>{3} [ / <alpha-value> ]? ) | rgb( <number>{3} [ / <alpha-value> ]? ) | rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? )","rgba()":"rgba( <percentage>{3} [ / <alpha-value> ]? ) | rgba( <number>{3} [ / <alpha-value> ]? ) | rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? )","rotate()":"rotate( <angle> )","rotate3d()":"rotate3d( <number> , <number> , <number> , <angle> )","rotateX()":"rotateX( <angle> )","rotateY()":"rotateY( <angle> )","rotateZ()":"rotateZ( <angle> )","saturate()":"saturate( <number-percentage> )","scale()":"scale( <number> [, <number> ]? )","scale3d()":"scale3d( <number> , <number> , <number> )","scaleX()":"scaleX( <number> )","scaleY()":"scaleY( <number> )","scaleZ()":"scaleZ( <number> )","self-position":"center | start | end | self-start | self-end | flex-start | flex-end","shape-radius":"<length-percentage> | closest-side | farthest-side","skew()":"skew( <angle> [, <angle> ]? )","skewX()":"skewX( <angle> )","skewY()":"skewY( <angle> )","sepia()":"sepia( <number-percentage> )","shadow":"inset? && <length>{2,4} && <color>?","shadow-t":"[ <length>{2,3} && <color>? ]","shape":"rect( [ [ <top> , <right> , <bottom> , <left> ] | [ <top> <right> <bottom> <left> ] ] )","shape-box":"<box> | margin-box","side-or-corner":"[ left | right ] || [ top | bottom ]","single-animation":"<time> || <single-timing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]","single-animation-direction":"normal | reverse | alternate | alternate-reverse","single-animation-fill-mode":"none | forwards | backwards | both","single-animation-iteration-count":"infinite | <number>","single-animation-play-state":"running | paused","single-timing-function":"linear | <cubic-bezier-timing-function> | <step-timing-function> | <frames-timing-function>","single-transition":"<single-transition-timing-function> || [ none | <single-transition-property> ] || <time> || <time>","single-transition-timing-function":"<single-timing-function>","single-transition-property":"all | <custom-ident>","size":"closest-side | farthest-side | closest-corner | farthest-corner | <length> | <length-percentage>{2}","step-timing-function":"step-start | step-end | steps( <integer> [, [ start | end ] ]? )","symbol":"<string> | <image> | <custom-ident>","target":"<target-counter()> | <target-counters()> | <target-text()>","target-counter()":"target-counter( [ <string> | <url> ] , <custom-ident> , <counter-style>? )","target-counters()":"target-counters( [ <string> | <url> ] , <custom-ident> , <string> , <counter-style>? )","target-text()":"target-text( [ <string> | <url> ] , [ content | before | after | first-letter ]? )","time-percentage":"<time> | <percentage>","track-breadth":"<length-percentage> | <flex> | min-content | max-content | auto","track-list":"[ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?","track-repeat":"repeat( [ <positive-integer> ] , [ <line-names>? <track-size> ]+ <line-names>? )","track-size":"<track-breadth> | minmax( <inflexible-breadth> , <track-breadth> ) | fit-content( [ <length> | <percentage> ] )","transform-function":"<matrix()> | <translate()> | <translateX()> | <translateY()> | <scale()> | <scaleX()> | <scaleY()> | <rotate()> | <skew()> | <skewX()> | <skewY()> | <matrix3d()> | <translate3d()> | <translateZ()> | <scale3d()> | <scaleZ()> | <rotate3d()> | <rotateX()> | <rotateY()> | <rotateZ()> | <perspective()>","transform-list":"<transform-function>+","translate()":"translate( <length-percentage> [, <length-percentage> ]? )","translate3d()":"translate3d( <length-percentage> , <length-percentage> , <length> )","translateX()":"translateX( <length-percentage> )","translateY()":"translateY( <length-percentage> )","translateZ()":"translateZ( <length> )","type-or-unit":"string | integer | color | url | integer | number | length | angle | time | frequency | em | ex | px | rem | vw | vh | vmin | vmax | mm | q | cm | in | pt | pc | deg | grad | rad | ms | s | Hz | kHz | %","viewport-length":"auto | <length-percentage>","-legacy-gradient":"<-webkit-gradient()> | <-legacy-linear-gradient> | <-legacy-repeating-linear-gradient> | <-legacy-radial-gradient> | <-legacy-repeating-radial-gradient>","-legacy-linear-gradient":"-moz-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-linear-gradient( <-legacy-linear-gradient-arguments> )","-legacy-repeating-linear-gradient":"-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )","-legacy-linear-gradient-arguments":"[ <angle> | <side-or-corner> ]? , <color-stop-list>","-legacy-radial-gradient":"-moz-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-radial-gradient( <-legacy-radial-gradient-arguments> )","-legacy-repeating-radial-gradient":"-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )","-legacy-radial-gradient-arguments":"[ <position> , ]? [ [ [ <-legacy-radial-gradient-shape> || <-legacy-radial-gradient-size> ] | [ <length> | <percentage> ]{2} ] , ]? <color-stop-list>","-legacy-radial-gradient-size":"closest-side | closest-corner | farthest-side | farthest-corner | contain | cover","-legacy-radial-gradient-shape":"circle | ellipse","-non-standard-font":"-apple-system-body | -apple-system-headline | -apple-system-subheadline | -apple-system-caption1 | -apple-system-caption2 | -apple-system-footnote | -apple-system-short-body | -apple-system-short-headline | -apple-system-short-subheadline | -apple-system-short-caption1 | -apple-system-short-footnote | -apple-system-tall-body","-non-standard-color":"-moz-ButtonDefault | -moz-ButtonHoverFace | -moz-ButtonHoverText | -moz-CellHighlight | -moz-CellHighlightText | -moz-Combobox | -moz-ComboboxText | -moz-Dialog | -moz-DialogText | -moz-dragtargetzone | -moz-EvenTreeRow | -moz-Field | -moz-FieldText | -moz-html-CellHighlight | -moz-html-CellHighlightText | -moz-mac-accentdarkestshadow | -moz-mac-accentdarkshadow | -moz-mac-accentface | -moz-mac-accentlightesthighlight | -moz-mac-accentlightshadow | -moz-mac-accentregularhighlight | -moz-mac-accentregularshadow | -moz-mac-chrome-active | -moz-mac-chrome-inactive | -moz-mac-focusring | -moz-mac-menuselect | -moz-mac-menushadow | -moz-mac-menutextselect | -moz-MenuHover | -moz-MenuHoverText | -moz-MenuBarText | -moz-MenuBarHoverText | -moz-nativehyperlinktext | -moz-OddTreeRow | -moz-win-communicationstext | -moz-win-mediatext | -moz-activehyperlinktext | -moz-default-background-color | -moz-default-color | -moz-hyperlinktext | -moz-visitedhyperlinktext | -webkit-activelink | -webkit-focus-ring-color | -webkit-link | -webkit-text","-non-standard-image-rendering":"optimize-contrast | -moz-crisp-edges | -o-crisp-edges | -webkit-optimize-contrast","-non-standard-overflow":"-moz-scrollbars-none | -moz-scrollbars-horizontal | -moz-scrollbars-vertical | -moz-hidden-unscrollable","-non-standard-width":"min-intrinsic | intrinsic | -moz-min-content | -moz-max-content | -webkit-min-content | -webkit-max-content","-non-standard-word-break":"break-word","-webkit-gradient()":"-webkit-gradient( <-webkit-gradient-type> , <-webkit-gradient-point> [, <-webkit-gradient-point> | , <-webkit-gradient-radius> , <-webkit-gradient-point> ] [, <-webkit-gradient-radius> ]? [, <-webkit-gradient-color-stop> ]* )","-webkit-gradient-color-stop":"from( <color> ) | color-stop( [ <number-zero-one> | <percentage> ] , <color> ) | to( <color> )","-webkit-gradient-point":"[ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]","-webkit-gradient-radius":"<length> | <percentage>","-webkit-gradient-type":"linear | radial","-webkit-mask-box-repeat":"repeat | stretch | round","-webkit-mask-clip-style":"border | border-box | padding | padding-box | content | content-box | text","-ms-filter":"[ <progid> | FlipH | FlipV ]+","age":"child | young | old","border-radius":"<length-percentage>{1,2}","bottom":"<length> | auto","generic-voice":"[ <age>? <gender> <integer>? ]","gender":"male | female | neutral","left":"<length> | auto","mask-image":"<mask-reference>#","name-repeat":"repeat( [ <positive-integer> | auto-fill ] , <line-names>+ )","paint":"none | currentColor | <color> | <url> [ none | currentColor | <color> ]?","path()":"path( <string> )","right":"<length> | auto","svg-length":"<percentage> | <length> | <number>","svg-writing-mode":"lr-tb | rl-tb | tb-rl | lr | rl | tb","top":"<length> | auto","x":"<number>","y":"<number>"},"properties":{"-ms-accelerator":"false | true","-ms-block-progression":"tb | rl | bt | lr","-ms-content-zoom-chaining":"none | chained","-ms-content-zooming":"none | zoom","-ms-content-zoom-limit":"<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>","-ms-content-zoom-limit-max":"<percentage>","-ms-content-zoom-limit-min":"<percentage>","-ms-content-zoom-snap":"<'-ms-content-zoom-snap-type'> || <'-ms-content-zoom-snap-points'>","-ms-content-zoom-snap-points":"snapInterval( <percentage> , <percentage> ) | snapList( <percentage># )","-ms-content-zoom-snap-type":"none | proximity | mandatory","-ms-filter":"<string>","-ms-flow-from":"[ none | <custom-ident> ]#","-ms-flow-into":"[ none | <custom-ident> ]#","-ms-high-contrast-adjust":"auto | none","-ms-hyphenate-limit-chars":"auto | <integer>{1,3}","-ms-hyphenate-limit-lines":"no-limit | <integer>","-ms-hyphenate-limit-zone":"<percentage> | <length>","-ms-ime-align":"auto | after","-ms-overflow-style":"auto | none | scrollbar | -ms-autohiding-scrollbar","-ms-scrollbar-3dlight-color":"<color>","-ms-scrollbar-arrow-color":"<color>","-ms-scrollbar-base-color":"<color>","-ms-scrollbar-darkshadow-color":"<color>","-ms-scrollbar-face-color":"<color>","-ms-scrollbar-highlight-color":"<color>","-ms-scrollbar-shadow-color":"<color>","-ms-scrollbar-track-color":"<color>","-ms-scroll-chaining":"chained | none","-ms-scroll-limit":"<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>","-ms-scroll-limit-x-max":"auto | <length>","-ms-scroll-limit-x-min":"<length>","-ms-scroll-limit-y-max":"auto | <length>","-ms-scroll-limit-y-min":"<length>","-ms-scroll-rails":"none | railed","-ms-scroll-snap-points-x":"snapInterval( <length-percentage> , <length-percentage> ) | snapList( <length-percentage># )","-ms-scroll-snap-points-y":"snapInterval( <length-percentage> , <length-percentage> ) | snapList( <length-percentage># )","-ms-scroll-snap-type":"none | proximity | mandatory","-ms-scroll-snap-x":"<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>","-ms-scroll-snap-y":"<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>","-ms-scroll-translation":"none | vertical-to-horizontal","-ms-text-autospace":"none | ideograph-alpha | ideograph-numeric | ideograph-parenthesis | ideograph-space","-ms-touch-select":"grippers | none","-ms-user-select":"none | element | text","-ms-wrap-flow":"auto | both | start | end | maximum | clear","-ms-wrap-margin":"<length>","-ms-wrap-through":"wrap | none","-moz-appearance":"none | button | button-arrow-down | button-arrow-next | button-arrow-previous | button-arrow-up | button-bevel | button-focus | caret | checkbox | checkbox-container | checkbox-label | checkmenuitem | dualbutton | groupbox | listbox | listitem | menuarrow | menubar | menucheckbox | menuimage | menuitem | menuitemtext | menulist | menulist-button | menulist-text | menulist-textfield | menupopup | menuradio | menuseparator | meterbar | meterchunk | progressbar | progressbar-vertical | progresschunk | progresschunk-vertical | radio | radio-container | radio-label | radiomenuitem | range | range-thumb | resizer | resizerpanel | scale-horizontal | scalethumbend | scalethumb-horizontal | scalethumbstart | scalethumbtick | scalethumb-vertical | scale-vertical | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | searchfield | separator | sheet | spinner | spinner-downbutton | spinner-textfield | spinner-upbutton | splitter | statusbar | statusbarpanel | tab | tabpanel | tabpanels | tab-scroll-arrow-back | tab-scroll-arrow-forward | textfield | textfield-multiline | toolbar | toolbarbutton | toolbarbutton-dropdown | toolbargripper | toolbox | tooltip | treeheader | treeheadercell | treeheadersortarrow | treeitem | treeline | treetwisty | treetwistyopen | treeview | -moz-mac-unified-toolbar | -moz-win-borderless-glass | -moz-win-browsertabbar-toolbox | -moz-win-communicationstext | -moz-win-communications-toolbox | -moz-win-exclude-glass | -moz-win-glass | -moz-win-mediatext | -moz-win-media-toolbox | -moz-window-button-box | -moz-window-button-box-maximized | -moz-window-button-close | -moz-window-button-maximize | -moz-window-button-minimize | -moz-window-button-restore | -moz-window-frame-bottom | -moz-window-frame-left | -moz-window-frame-right | -moz-window-titlebar | -moz-window-titlebar-maximized","-moz-binding":"<url> | none","-moz-border-bottom-colors":"<color>+ | none","-moz-border-left-colors":"<color>+ | none","-moz-border-right-colors":"<color>+ | none","-moz-border-top-colors":"<color>+ | none","-moz-context-properties":"none | [ fill | fill-opacity | stroke | stroke-opacity ]#","-moz-float-edge":"border-box | content-box | margin-box | padding-box","-moz-force-broken-image-icon":"<integer>","-moz-image-region":"<shape> | auto","-moz-orient":"inline | block | horizontal | vertical","-moz-outline-radius":"<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?","-moz-outline-radius-bottomleft":"<outline-radius>","-moz-outline-radius-bottomright":"<outline-radius>","-moz-outline-radius-topleft":"<outline-radius>","-moz-outline-radius-topright":"<outline-radius>","-moz-stack-sizing":"ignore | stretch-to-fit","-moz-text-blink":"none | blink","-moz-user-focus":"ignore | normal | select-after | select-before | select-menu | select-same | select-all | none","-moz-user-input":"auto | none | enabled | disabled","-moz-user-modify":"read-only | read-write | write-only","-moz-window-dragging":"drag | no-drag","-moz-window-shadow":"default | menu | tooltip | sheet | none","-webkit-appearance":"none | button | button-bevel | caps-lock-indicator | caret | checkbox | default-button | listbox | listitem | media-fullscreen-button | media-mute-button | media-play-button | media-seek-back-button | media-seek-forward-button | media-slider | media-sliderthumb | menulist | menulist-button | menulist-text | menulist-textfield | push-button | radio | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbargripper-horizontal | scrollbargripper-vertical | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | searchfield | searchfield-cancel-button | searchfield-decoration | searchfield-results-button | searchfield-results-decoration | slider-horizontal | slider-vertical | sliderthumb-horizontal | sliderthumb-vertical | square-button | textarea | textfield","-webkit-border-before":"<'border-width'> || <'border-style'> || <'color'>","-webkit-border-before-color":"<'color'>","-webkit-border-before-style":"<'border-style'>","-webkit-border-before-width":"<'border-width'>","-webkit-box-reflect":"[ above | below | right | left ]? <length>? <image>?","-webkit-mask":"[ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <box> | border | padding | content | text ] || [ <box> | border | padding | content ] ]#","-webkit-mask-attachment":"<attachment>#","-webkit-mask-clip":"<-webkit-mask-clip-style> [, <-webkit-mask-clip-style> ]*","-webkit-mask-composite":"<composite-style>#","-webkit-mask-image":"<mask-reference>#","-webkit-mask-origin":"[ <box> | border | padding | content ]#","-webkit-mask-position":"<position>#","-webkit-mask-position-x":"[ <length-percentage> | left | center | right ]#","-webkit-mask-position-y":"[ <length-percentage> | top | center | bottom ]#","-webkit-mask-repeat":"<repeat-style>#","-webkit-mask-repeat-x":"repeat | no-repeat | space | round","-webkit-mask-repeat-y":"repeat | no-repeat | space | round","-webkit-mask-size":"<bg-size>#","-webkit-overflow-scrolling":"auto | touch","-webkit-tap-highlight-color":"<color>","-webkit-text-fill-color":"<color>","-webkit-text-stroke":"<length> || <color>","-webkit-text-stroke-color":"<color>","-webkit-text-stroke-width":"<length>","-webkit-touch-callout":"default | none","-webkit-user-modify":"read-only | read-write | read-write-plaintext-only","align-content":"normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position>","align-items":"normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]","align-self":"auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>","all":"initial | inherit | unset | revert","animation":"<single-animation>#","animation-delay":"<time>#","animation-direction":"<single-animation-direction>#","animation-duration":"<time>#","animation-fill-mode":"<single-animation-fill-mode>#","animation-iteration-count":"<single-animation-iteration-count>#","animation-name":"[ none | <keyframes-name> ]#","animation-play-state":"<single-animation-play-state>#","animation-timing-function":"<single-timing-function>#","appearance":"auto | none","azimuth":"<angle> | [ [ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards","backdrop-filter":"none | <filter-function-list>","backface-visibility":"visible | hidden","background":"[ <bg-layer> , ]* <final-bg-layer>","background-attachment":"<attachment>#","background-blend-mode":"<blend-mode>#","background-clip":"<box>#","background-color":"<color>","background-image":"<bg-image>#","background-origin":"<box>#","background-position":"<bg-position>#","background-position-x":"[ center | [ left | right | x-start | x-end ]? <length-percentage>? ]#","background-position-y":"[ center | [ top | bottom | y-start | y-end ]? <length-percentage>? ]#","background-repeat":"<repeat-style>#","background-size":"<bg-size>#","block-overflow":"clip | ellipsis | <string>","block-size":"<'width'>","border":"<br-width> || <br-style> || <color>","border-block-end":"<'border-width'> || <'border-style'> || <'color'>","border-block-end-color":"<'color'>","border-block-end-style":"<'border-style'>","border-block-end-width":"<'border-width'>","border-block-start":"<'border-width'> || <'border-style'> || <'color'>","border-block-start-color":"<'color'>","border-block-start-style":"<'border-style'>","border-block-start-width":"<'border-width'>","border-bottom":"<br-width> || <br-style> || <color>","border-bottom-color":"<color>","border-bottom-left-radius":"<length-percentage>{1,2}","border-bottom-right-radius":"<length-percentage>{1,2}","border-bottom-style":"<br-style>","border-bottom-width":"<br-width>","border-collapse":"collapse | separate","border-color":"<color>{1,4}","border-image":"<'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>","border-image-outset":"[ <length> | <number> ]{1,4}","border-image-repeat":"[ stretch | repeat | round | space ]{1,2}","border-image-slice":"<number-percentage>{1,4} && fill?","border-image-source":"none | <image>","border-image-width":"[ <length-percentage> | <number> | auto ]{1,4}","border-inline-end":"<'border-width'> || <'border-style'> || <'color'>","border-inline-end-color":"<'color'>","border-inline-end-style":"<'border-style'>","border-inline-end-width":"<'border-width'>","border-inline-start":"<'border-width'> || <'border-style'> || <'color'>","border-inline-start-color":"<'color'>","border-inline-start-style":"<'border-style'>","border-inline-start-width":"<'border-width'>","border-left":"<br-width> || <br-style> || <color>","border-left-color":"<color>","border-left-style":"<br-style>","border-left-width":"<br-width>","border-radius":"<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?","border-right":"<br-width> || <br-style> || <color>","border-right-color":"<color>","border-right-style":"<br-style>","border-right-width":"<br-width>","border-spacing":"<length> <length>?","border-style":"<br-style>{1,4}","border-top":"<br-width> || <br-style> || <color>","border-top-color":"<color>","border-top-left-radius":"<length-percentage>{1,2}","border-top-right-radius":"<length-percentage>{1,2}","border-top-style":"<br-style>","border-top-width":"<br-width>","border-width":"<br-width>{1,4}","bottom":"<length> | <percentage> | auto","box-align":"start | center | end | baseline | stretch","box-decoration-break":"slice | clone","box-direction":"normal | reverse | inherit","box-flex":"<number>","box-flex-group":"<integer>","box-lines":"single | multiple","box-ordinal-group":"<integer>","box-orient":"horizontal | vertical | inline-axis | block-axis | inherit","box-pack":"start | center | end | justify","box-shadow":"none | <shadow>#","box-sizing":"content-box | border-box","break-after":"auto | avoid | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region","break-before":"auto | avoid | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region","break-inside":"auto | avoid | avoid-page | avoid-column | avoid-region","caption-side":"top | bottom | block-start | block-end | inline-start | inline-end","caret-color":"auto | <color>","clear":"none | left | right | both | inline-start | inline-end","clip":"<shape> | auto","clip-path":"<clip-source> | [ <basic-shape> || <geometry-box> ] | none","color":"<color>","color-adjust":"economy | exact","column-count":"<integer> | auto","column-fill":"auto | balance | balance-all","column-gap":"normal | <length-percentage>","column-rule":"<'column-rule-width'> || <'column-rule-style'> || <'column-rule-color'>","column-rule-color":"<color>","column-rule-style":"<'border-style'>","column-rule-width":"<'border-width'>","column-span":"none | all","column-width":"<length> | auto","columns":"<'column-width'> || <'column-count'>","contain":"none | strict | content | [ size || layout || style || paint ]","content":"normal | none | [ <content-replacement> | <content-list> ] [ / <string> ]?","counter-increment":"[ <custom-ident> <integer>? ]+ | none","counter-reset":"[ <custom-ident> <integer>? ]+ | none","cursor":"[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]","direction":"ltr | rtl","display":"none | inline | block | list-item | inline-list-item | inline-block | inline-table | table | table-cell | table-column | table-column-group | table-footer-group | table-header-group | table-row | table-row-group | flex | inline-flex | grid | inline-grid | run-in | ruby | ruby-base | ruby-text | ruby-base-container | ruby-text-container | contents | -ms-flexbox | -ms-inline-flexbox | -ms-grid | -ms-inline-grid | -webkit-flex | -webkit-inline-flex | -webkit-box | -webkit-inline-box | -moz-inline-stack | -moz-box | -moz-inline-box","empty-cells":"show | hide","filter":"none | <filter-function-list> | <-ms-filter>","flex":"none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]","flex-basis":"content | <'width'>","flex-direction":"row | row-reverse | column | column-reverse","flex-flow":"<'flex-direction'> || <'flex-wrap'>","flex-grow":"<number>","flex-shrink":"<number>","flex-wrap":"nowrap | wrap | wrap-reverse","float":"left | right | none | inline-start | inline-end","font":"[ [ <'font-style'> || <font-variant-css21> || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | <-non-standard-font>","font-family":"[ <family-name> | <generic-family> ]#","font-feature-settings":"normal | <feature-tag-value>#","font-kerning":"auto | normal | none","font-language-override":"normal | <string>","font-optical-sizing":"auto | none","font-variation-settings":"normal | [ <string> <number> ]#","font-size":"<absolute-size> | <relative-size> | <length-percentage>","font-size-adjust":"none | <number>","font-stretch":"normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded","font-style":"normal | italic | oblique","font-synthesis":"none | [ weight || style ]","font-variant":"normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> || stylistic( <feature-value-name> ) || historical-forms || styleset( <feature-value-name># ) || character-variant( <feature-value-name># ) || swash( <feature-value-name> ) || ornaments( <feature-value-name> ) || annotation( <feature-value-name> ) || [ small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps ] || <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero || <east-asian-variant-values> || <east-asian-width-values> || ruby ]","font-variant-alternates":"normal | [ stylistic( <feature-value-name> ) || historical-forms || styleset( <feature-value-name># ) || character-variant( <feature-value-name># ) || swash( <feature-value-name> ) || ornaments( <feature-value-name> ) || annotation( <feature-value-name> ) ]","font-variant-caps":"normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps","font-variant-east-asian":"normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]","font-variant-ligatures":"normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ]","font-variant-numeric":"normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ]","font-variant-position":"normal | sub | super","font-weight":"normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900","gap":"<'row-gap'> <'column-gap'>?","grid":"<'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>","grid-area":"<grid-line> [ / <grid-line> ]{0,3}","grid-auto-columns":"<track-size>+","grid-auto-flow":"[ row | column ] || dense","grid-auto-rows":"<track-size>+","grid-column":"<grid-line> [ / <grid-line> ]?","grid-column-end":"<grid-line>","grid-column-gap":"<length-percentage>","grid-column-start":"<grid-line>","grid-gap":"<'grid-row-gap'> <'grid-column-gap'>?","grid-row":"<grid-line> [ / <grid-line> ]?","grid-row-end":"<grid-line>","grid-row-gap":"<length-percentage>","grid-row-start":"<grid-line>","grid-template":"none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?","grid-template-areas":"none | <string>+","grid-template-columns":"none | <track-list> | <auto-track-list>","grid-template-rows":"none | <track-list> | <auto-track-list>","hanging-punctuation":"none | [ first || [ force-end | allow-end ] || last ]","height":"[ <length> | <percentage> ] && [ border-box | content-box ]? | available | min-content | max-content | fit-content | auto","hyphens":"none | manual | auto","image-orientation":"from-image | <angle> | [ <angle>? flip ]","image-rendering":"auto | crisp-edges | pixelated | optimizeSpeed | optimizeQuality | <-non-standard-image-rendering>","image-resolution":"[ from-image || <resolution> ] && snap?","ime-mode":"auto | normal | active | inactive | disabled","initial-letter":"normal | [ <number> <integer>? ]","initial-letter-align":"[ auto | alphabetic | hanging | ideographic ]","inline-size":"<'width'>","isolation":"auto | isolate","justify-content":"normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ]","justify-items":"normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ] | legacy | legacy && [ left | right | center ]","justify-self":"auto | normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ]","left":"<length> | <percentage> | auto","letter-spacing":"normal | <length-percentage>","line-break":"auto | loose | normal | strict","line-clamp":"none | <integer>","line-height":"normal | <number> | <length> | <percentage>","line-height-step":"none | <length>","list-style":"<'list-style-type'> || <'list-style-position'> || <'list-style-image'>","list-style-image":"<url> | none","list-style-position":"inside | outside","list-style-type":"<counter-style> | <string> | none","margin":"[ <length> | <percentage> | auto ]{1,4}","margin-block-end":"<'margin-left'>","margin-block-start":"<'margin-left'>","margin-bottom":"<length> | <percentage> | auto","margin-inline-end":"<'margin-left'>","margin-inline-start":"<'margin-left'>","margin-left":"<length> | <percentage> | auto","margin-right":"<length> | <percentage> | auto","margin-top":"<length> | <percentage> | auto","mask":"<mask-layer>#","mask-border":"<'mask-border-source'> || <'mask-border-slice'> [ / <'mask-border-width'>? [ / <'mask-border-outset'> ]? ]? || <'mask-border-repeat'> || <'mask-border-mode'>","mask-border-mode":"luminance | alpha","mask-border-outset":"[ <length> | <number> ]{1,4}","mask-border-repeat":"[ stretch | repeat | round | space ]{1,2}","mask-border-slice":"<number-percentage>{1,4} fill?","mask-border-source":"none | <image>","mask-border-width":"[ <length-percentage> | <number> | auto ]{1,4}","mask-clip":"[ <geometry-box> | no-clip ]#","mask-composite":"<compositing-operator>#","mask-image":"<mask-reference>#","mask-mode":"<masking-mode>#","mask-origin":"<geometry-box>#","mask-position":"<position>#","mask-repeat":"<repeat-style>#","mask-size":"<bg-size>#","mask-type":"luminance | alpha","max-block-size":"<'max-width'>","max-height":"<length> | <percentage> | none | max-content | min-content | fit-content | fill-available","max-inline-size":"<'max-width'>","max-lines":"none | <integer>","max-width":"<length> | <percentage> | none | max-content | min-content | fit-content | fill-available | <-non-standard-width>","min-block-size":"<'min-width'>","min-height":"<length> | <percentage> | auto | max-content | min-content | fit-content | fill-available","min-inline-size":"<'min-width'>","min-width":"<length> | <percentage> | auto | max-content | min-content | fit-content | fill-available | <-non-standard-width>","mix-blend-mode":"<blend-mode>","object-fit":"fill | contain | cover | none | scale-down","object-position":"<position>","offset":"[ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]?","offset-anchor":"auto | <position>","offset-block-end":"<'left'>","offset-block-start":"<'left'>","offset-inline-end":"<'left'>","offset-inline-start":"<'left'>","offset-distance":"<length-percentage>","offset-path":"none | ray( [ <angle> && <size>? && contain? ] ) | <path()> | <url> | [ <basic-shape> || <geometry-box> ]","offset-position":"auto | <position>","offset-rotate":"[ auto | reverse ] || <angle>","opacity":"<number-zero-one>","order":"<integer>","orphans":"<integer>","outline":"[ <'outline-color'> || <'outline-style'> || <'outline-width'> ]","outline-color":"<color> | invert","outline-offset":"<length>","outline-style":"auto | <br-style>","outline-width":"<br-width>","overflow":"visible | hidden | scroll | auto | <-non-standard-overflow>","overflow-anchor":"auto | none","overflow-block":"<'overflow'>","overflow-clip-box":"padding-box | content-box","overflow-inline":"<'overflow'>","overflow-wrap":"normal | break-word","overflow-x":"visible | hidden | clip | scroll | auto","overflow-y":"visible | hidden | clip | scroll | auto","overscroll-behavior":"[ contain | none | auto ]{1,2}","overscroll-behavior-x":"contain | none | auto","overscroll-behavior-y":"contain | none | auto","padding":"[ <length> | <percentage> ]{1,4}","padding-block-end":"<'padding-left'>","padding-block-start":"<'padding-left'>","padding-bottom":"<length> | <percentage>","padding-inline-end":"<'padding-left'>","padding-inline-start":"<'padding-left'>","padding-left":"<length> | <percentage>","padding-right":"<length> | <percentage>","padding-top":"<length> | <percentage>","page-break-after":"auto | always | avoid | left | right | recto | verso","page-break-before":"auto | always | avoid | left | right | recto | verso","page-break-inside":"auto | avoid","paint-order":"normal | [ fill || stroke || markers ]","perspective":"none | <length>","perspective-origin":"<position>","place-content":"<'align-content'> <'justify-content'>?","pointer-events":"auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit","position":"static | relative | absolute | sticky | fixed | -webkit-sticky","quotes":"none | [ <string> <string> ]+","resize":"none | both | horizontal | vertical","right":"<length> | <percentage> | auto","rotate":"none | [ x | y | z | <number>{3} ]? && <angle>","row-gap":"normal | <length-percentage>","ruby-align":"start | center | space-between | space-around","ruby-merge":"separate | collapse | auto","ruby-position":"over | under | inter-character","scale":"none | <number>{1,3}","scroll-behavior":"auto | smooth","scroll-snap-coordinate":"none | <position>#","scroll-snap-destination":"<position>","scroll-snap-points-x":"none | repeat( <length-percentage> )","scroll-snap-points-y":"none | repeat( <length-percentage> )","scroll-snap-type":"none | mandatory | proximity","scroll-snap-type-x":"none | mandatory | proximity","scroll-snap-type-y":"none | mandatory | proximity","shape-image-threshold":"<number>","shape-margin":"<length-percentage>","shape-outside":"none | <shape-box> || <basic-shape> | <image>","tab-size":"<integer> | <length>","table-layout":"auto | fixed","text-align":"start | end | left | right | center | justify | match-parent","text-align-last":"auto | start | end | left | right | center | justify","text-combine-upright":"none | all | [ digits <integer>? ]","text-decoration":"<'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'>","text-decoration-color":"<color>","text-decoration-line":"none | [ underline || overline || line-through || blink ]","text-decoration-skip":"none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || edges || box-decoration ]","text-decoration-skip-ink":"auto | none","text-decoration-style":"solid | double | dotted | dashed | wavy","text-emphasis":"<'text-emphasis-style'> || <'text-emphasis-color'>","text-emphasis-color":"<color>","text-emphasis-position":"[ over | under ] && [ right | left ]","text-emphasis-style":"none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>","text-indent":"<length-percentage> && hanging? && each-line?","text-justify":"auto | inter-character | inter-word | none","text-orientation":"mixed | upright | sideways","text-overflow":"[ clip | ellipsis | <string> ]{1,2}","text-rendering":"auto | optimizeSpeed | optimizeLegibility | geometricPrecision","text-shadow":"none | <shadow-t>#","text-size-adjust":"none | auto | <percentage>","text-transform":"none | capitalize | uppercase | lowercase | full-width","text-underline-position":"auto | [ under || [ left | right ] ]","top":"<length> | <percentage> | auto","touch-action":"auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] || pinch-zoom ] | manipulation","transform":"none | <transform-list>","transform-box":"border-box | fill-box | view-box","transform-origin":"[ [ <length-percentage> | left | center | right ] && [ <length-percentage> | top | center | bottom ] ] <length>? | [ <length-percentage> | left | center | right | top | bottom ]","transform-style":"flat | preserve-3d","transition":"<single-transition>#","transition-delay":"<time>#","transition-duration":"<time>#","transition-property":"none | <single-transition-property>#","transition-timing-function":"<single-transition-timing-function>#","translate":"none | <length-percentage> [ <length-percentage> <length>? ]?","unicode-bidi":"normal | embed | isolate | bidi-override | isolate-override | plaintext | -moz-isolate | -moz-isolate-override | -moz-plaintext | -webkit-isolate","user-select":"auto | text | none | contain | all","vertical-align":"baseline | sub | super | text-top | text-bottom | middle | top | bottom | <percentage> | <length>","visibility":"visible | hidden | collapse","white-space":"normal | pre | nowrap | pre-wrap | pre-line","widows":"<integer>","width":"[ <length> | <percentage> ] && [ border-box | content-box ]? | available | min-content | max-content | fit-content | auto","will-change":"auto | <animateable-feature>#","word-break":"normal | break-all | keep-all | <-non-standard-word-break>","word-spacing":"normal | <length-percentage>","word-wrap":"normal | break-word","writing-mode":"horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr | <svg-writing-mode>","z-index":"auto | <integer>","zoom":"normal | reset | <number> | <percentage>","-moz-background-clip":"padding | border","-moz-border-radius-bottomleft":"<'border-bottom-left-radius'>","-moz-border-radius-bottomright":"<'border-bottom-right-radius'>","-moz-border-radius-topleft":"<'border-top-left-radius'>","-moz-border-radius-topright":"<'border-bottom-right-radius'>","-moz-osx-font-smoothing":"auto | grayscale","-moz-user-select":"none | text | all | -moz-none","-ms-flex-align":"start | end | center | baseline | stretch","-ms-flex-item-align":"auto | start | end | center | baseline | stretch","-ms-flex-line-pack":"start | end | center | justify | distribute | stretch","-ms-flex-negative":"<'flex-shrink'>","-ms-flex-pack":"start | end | center | justify | distribute","-ms-flex-order":"<integer>","-ms-flex-positive":"<'flex-grow'>","-ms-flex-preferred-size":"<'flex-basis'>","-ms-interpolation-mode":"nearest-neighbor | bicubic","-ms-grid-column-align":"start | end | center | stretch","-ms-grid-row-align":"start | end | center | stretch","-webkit-background-clip":"[ <box> | border | padding | content | text ]#","-webkit-column-break-after":"always | auto | avoid","-webkit-column-break-before":"always | auto | avoid","-webkit-column-break-inside":"always | auto | avoid","-webkit-font-smoothing":"auto | none | antialiased | subpixel-antialiased","-webkit-line-clamp":"<positive-integer>","-webkit-mask-box-image":"[ <url> | <gradient> | none ] [ <length-percentage>{4} <-webkit-mask-box-repeat>{2} ]?","-webkit-print-color-adjust":"economy | exact","-webkit-text-security":"none | circle | disc | square","-webkit-user-drag":"none | element | auto","-webkit-user-select":"auto | none | text | all","alignment-baseline":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical","baseline-shift":"baseline | sub | super | <svg-length>","behavior":"<url>+","clip-rule":"nonzero | evenodd","cue":"<'cue-before'> <'cue-after'>?","cue-after":"<url> <decibel>? | none","cue-before":"<url> <decibel>? | none","dominant-baseline":"auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge","fill":"<paint>","fill-opacity":"<number-zero-one>","fill-rule":"nonzero | evenodd","glyph-orientation-horizontal":"<angle>","glyph-orientation-vertical":"<angle>","kerning":"auto | <svg-length>","marker":"none | <url>","marker-end":"none | <url>","marker-mid":"none | <url>","marker-start":"none | <url>","pause":"<'pause-before'> <'pause-after'>?","pause-after":"<time> | none | x-weak | weak | medium | strong | x-strong","pause-before":"<time> | none | x-weak | weak | medium | strong | x-strong","rest":"<'rest-before'> <'rest-after'>?","rest-after":"<time> | none | x-weak | weak | medium | strong | x-strong","rest-before":"<time> | none | x-weak | weak | medium | strong | x-strong","shape-rendering":"auto | optimizeSpeed | crispEdges | geometricPrecision","src":"[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#","speak":"auto | none | normal","speak-as":"normal | spell-out || digits || [ literal-punctuation | no-punctuation ]","stroke":"<paint>","stroke-dasharray":"none | [ <svg-length>+ ]#","stroke-dashoffset":"<svg-length>","stroke-linecap":"butt | round | square","stroke-linejoin":"miter | round | bevel","stroke-miterlimit":"<number-one-or-greater>","stroke-opacity":"<number-zero-one>","stroke-width":"<svg-length>","text-anchor":"start | middle | end","unicode-range":"<unicode-range>#","voice-balance":"<number> | left | center | right | leftwards | rightwards","voice-duration":"auto | <time>","voice-family":"[ [ <family-name> | <generic-voice> ] , ]* [ <family-name> | <generic-voice> ] | preserve","voice-pitch":"<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]","voice-range":"<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]","voice-rate":"[ normal | x-slow | slow | medium | fast | x-fast ] || <percentage>","voice-stress":"normal | strong | moderate | none | reduced","voice-volume":"silent | [ [ x-soft | soft | medium | loud | x-loud ] || <decibel> ]"}} | |
},{}],39:[function(require,module,exports){ | |
var List = require('../utils/list'); | |
module.exports = function createConvertors(walk) { | |
return { | |
fromPlainObject: function(ast) { | |
walk(ast, { | |
enter: function(node) { | |
if (node.children && node.children instanceof List === false) { | |
node.children = new List().fromArray(node.children); | |
} | |
} | |
}); | |
return ast; | |
}, | |
toPlainObject: function(ast) { | |
walk(ast, { | |
leave: function(node) { | |
if (node.children && node.children instanceof List) { | |
node.children = node.children.toArray(); | |
} | |
} | |
}); | |
return ast; | |
} | |
}; | |
}; | |
},{"../utils/list":142}],40:[function(require,module,exports){ | |
'use strict'; | |
var sourceMap = require('./sourceMap'); | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
function processChildren(node, delimeter) { | |
var list = node.children; | |
var prev = null; | |
if (typeof delimeter !== 'function') { | |
list.forEach(this.node, this); | |
} else { | |
list.forEach(function(node) { | |
if (prev !== null) { | |
delimeter.call(this, prev); | |
} | |
this.node(node); | |
prev = node; | |
}, this); | |
} | |
} | |
module.exports = function createGenerator(config) { | |
function processNode(node) { | |
if (hasOwnProperty.call(types, node.type)) { | |
types[node.type].call(this, node); | |
} else { | |
throw new Error('Unknown node type: ' + node.type); | |
} | |
} | |
var types = {}; | |
if (config.node) { | |
for (var name in config.node) { | |
types[name] = config.node[name].generate; | |
} | |
} | |
return function(node, options) { | |
var buffer = ''; | |
var handlers = { | |
children: processChildren, | |
node: processNode, | |
chunk: function(chunk) { | |
buffer += chunk; | |
}, | |
result: function() { | |
return buffer; | |
} | |
}; | |
if (options) { | |
if (typeof options.decorator === 'function') { | |
handlers = options.decorator(handlers); | |
} | |
if (options.sourceMap) { | |
handlers = sourceMap(handlers); | |
} | |
} | |
handlers.node(node); | |
return handlers.result(); | |
}; | |
}; | |
},{"./sourceMap":41}],41:[function(require,module,exports){ | |
'use strict'; | |
var SourceMapGenerator = require('source-map').SourceMapGenerator; | |
var trackNodes = { | |
Atrule: true, | |
Selector: true, | |
Declaration: true | |
}; | |
module.exports = function generateSourceMap(handlers) { | |
var map = new SourceMapGenerator(); | |
var line = 1; | |
var column = 0; | |
var generated = { | |
line: 1, | |
column: 0 | |
}; | |
var original = { | |
line: 0, // should be zero to add first mapping | |
column: 0 | |
}; | |
var sourceMappingActive = false; | |
var activatedGenerated = { | |
line: 1, | |
column: 0 | |
}; | |
var activatedMapping = { | |
generated: activatedGenerated | |
}; | |
var handlersNode = handlers.node; | |
handlers.node = function(node) { | |
if (node.loc && node.loc.start && trackNodes.hasOwnProperty(node.type)) { | |
var nodeLine = node.loc.start.line; | |
var nodeColumn = node.loc.start.column - 1; | |
if (original.line !== nodeLine || | |
original.column !== nodeColumn) { | |
original.line = nodeLine; | |
original.column = nodeColumn; | |
generated.line = line; | |
generated.column = column; | |
if (sourceMappingActive) { | |
sourceMappingActive = false; | |
if (generated.line !== activatedGenerated.line || | |
generated.column !== activatedGenerated.column) { | |
map.addMapping(activatedMapping); | |
} | |
} | |
sourceMappingActive = true; | |
map.addMapping({ | |
source: node.loc.source, | |
original: original, | |
generated: generated | |
}); | |
} | |
} | |
handlersNode.call(this, node); | |
if (sourceMappingActive && trackNodes.hasOwnProperty(node.type)) { | |
activatedGenerated.line = line; | |
activatedGenerated.column = column; | |
} | |
}; | |
var handlersChunk = handlers.chunk; | |
handlers.chunk = function(chunk) { | |
for (var i = 0; i < chunk.length; i++) { | |
if (chunk.charCodeAt(i) === 10) { // \n | |
line++; | |
column = 0; | |
} else { | |
column++; | |
} | |
} | |
handlersChunk(chunk); | |
}; | |
var handlersResult = handlers.result; | |
handlers.result = function() { | |
if (sourceMappingActive) { | |
map.addMapping(activatedMapping); | |
} | |
return { | |
css: handlersResult(), | |
map: map | |
}; | |
}; | |
return handlers; | |
}; | |
},{"source-map":155}],42:[function(require,module,exports){ | |
'use strict'; | |
module.exports = require('./syntax'); | |
},{"./syntax":74}],43:[function(require,module,exports){ | |
'use strict'; | |
var SyntaxReferenceError = require('./error').SyntaxReferenceError; | |
var MatchError = require('./error').MatchError; | |
var names = require('../utils/names'); | |
var generic = require('./generic'); | |
var parse = require('./grammar/parse'); | |
var generate = require('./grammar/generate'); | |
var walk = require('./grammar/walk'); | |
var astToTokens = require('./ast-to-tokens'); | |
var buildMatchGraph = require('./match-graph').buildMatchGraph; | |
var matchAsTree = require('./match').matchAsTree; | |
var trace = require('./trace'); | |
var search = require('./search'); | |
var getStructureFromConfig = require('./structure').getStructureFromConfig; | |
var cssWideKeywords = buildMatchGraph(parse('inherit | initial | unset')); | |
var cssWideKeywordsWithExpression = buildMatchGraph(parse('inherit | initial | unset | <expression>')); | |
function dumpMapSyntax(map, syntaxAsAst) { | |
var result = {}; | |
for (var name in map) { | |
if (map[name].syntax) { | |
result[name] = syntaxAsAst ? map[name].syntax : generate(map[name].syntax); | |
} | |
} | |
return result; | |
} | |
function valueHasVar(value) { | |
var hasVar = false; | |
this.syntax.walk(value, function(node) { | |
if (node.type === 'Function' && node.name.toLowerCase() === 'var') { | |
hasVar = true; | |
} | |
}); | |
return hasVar; | |
} | |
function buildMatchResult(match, error, iterations) { | |
return { | |
matched: match, | |
iterations: iterations, | |
error: error, | |
getTrace: trace.getTrace, | |
isType: trace.isType, | |
isProperty: trace.isProperty, | |
isKeyword: trace.isKeyword | |
}; | |
} | |
function matchSyntax(lexer, syntax, node, useCommon) { | |
if (!node) { | |
return buildMatchResult(null, new Error('Node is undefined')); | |
} | |
if (valueHasVar.call(lexer, node)) { | |
return buildMatchResult(null, new Error('Matching for a tree with var() is not supported')); | |
} | |
var tokens = lexer.syntax.generate(node, astToTokens); | |
var result; | |
if (useCommon) { | |
result = matchAsTree(tokens, lexer.valueCommonSyntax, lexer); | |
} | |
if (!useCommon || !result.match) { | |
result = matchAsTree(tokens, syntax.match, lexer); | |
if (!result.match) { | |
return buildMatchResult( | |
null, | |
new MatchError(result.reason, lexer, syntax.syntax, node, result), | |
result.iterations | |
); | |
} | |
} | |
return buildMatchResult(result.match, null, result.iterations); | |
} | |
var Lexer = function(config, syntax, structure) { | |
this.valueCommonSyntax = cssWideKeywords; | |
this.syntax = syntax; | |
this.generic = false; | |
this.properties = {}; | |
this.types = {}; | |
this.structure = structure || getStructureFromConfig(config); | |
if (config) { | |
if (config.generic) { | |
this.generic = true; | |
for (var name in generic) { | |
this.addType_(name, generic[name]); | |
} | |
} | |
if (config.types) { | |
for (var name in config.types) { | |
this.addType_(name, config.types[name]); | |
} | |
} | |
if (config.properties) { | |
for (var name in config.properties) { | |
this.addProperty_(name, config.properties[name]); | |
} | |
} | |
} | |
}; | |
Lexer.prototype = { | |
structure: {}, | |
checkStructure: function(ast) { | |
function collectWarning(node, message) { | |
warns.push({ | |
node: node, | |
message: message | |
}); | |
} | |
var structure = this.structure; | |
var warns = []; | |
this.syntax.walk(ast, function(node) { | |
if (structure.hasOwnProperty(node.type)) { | |
structure[node.type].check(node, collectWarning); | |
} else { | |
collectWarning(node, 'Unknown node type `' + node.type + '`'); | |
} | |
}); | |
return warns.length ? warns : false; | |
}, | |
createDescriptor: function(syntax, type, name) { | |
var ref = { | |
type: type, | |
name: name | |
}; | |
var descriptor = { | |
type: type, | |
name: name, | |
syntax: null, | |
match: null | |
}; | |
if (typeof syntax === 'function') { | |
descriptor.match = buildMatchGraph(syntax, ref); | |
} else { | |
if (typeof syntax === 'string') { | |
// lazy parsing on first access | |
Object.defineProperty(descriptor, 'syntax', { | |
get: function() { | |
Object.defineProperty(descriptor, 'syntax', { | |
value: parse(syntax) | |
}); | |
return descriptor.syntax; | |
} | |
}); | |
} else { | |
descriptor.syntax = syntax; | |
} | |
Object.defineProperty(descriptor, 'match', { | |
get: function() { | |
Object.defineProperty(descriptor, 'match', { | |
value: buildMatchGraph(descriptor.syntax, ref) | |
}); | |
return descriptor.match; | |
} | |
}); | |
} | |
return descriptor; | |
}, | |
addProperty_: function(name, syntax) { | |
this.properties[name] = this.createDescriptor(syntax, 'Property', name); | |
}, | |
addType_: function(name, syntax) { | |
this.types[name] = this.createDescriptor(syntax, 'Type', name); | |
if (syntax === generic.expression) { | |
this.valueCommonSyntax = cssWideKeywordsWithExpression; | |
} | |
}, | |
matchDeclaration: function(node) { | |
if (node.type !== 'Declaration') { | |
return buildMatchResult(null, new Error('Not a Declaration node')); | |
} | |
return this.matchProperty(node.property, node.value); | |
}, | |
matchProperty: function(propertyName, value) { | |
var property = names.property(propertyName); | |
// don't match syntax for a custom property | |
if (property.custom) { | |
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties')); | |
} | |
var propertySyntax = property.vendor | |
? this.getProperty(property.name) || this.getProperty(property.basename) | |
: this.getProperty(property.name); | |
if (!propertySyntax) { | |
return buildMatchResult(null, new SyntaxReferenceError('Unknown property', propertyName)); | |
} | |
return matchSyntax(this, propertySyntax, value, true); | |
}, | |
matchType: function(typeName, value) { | |
var typeSyntax = this.getType(typeName); | |
if (!typeSyntax) { | |
return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName)); | |
} | |
return matchSyntax(this, typeSyntax, value, false); | |
}, | |
match: function(syntax, value) { | |
if (!syntax || !syntax.type) { | |
return buildMatchResult(null, new SyntaxReferenceError('Bad syntax')); | |
} | |
if (!syntax.match) { | |
syntax = this.createDescriptor(syntax); | |
} | |
return matchSyntax(this, syntax, value, false); | |
}, | |
findValueFragments: function(propertyName, value, type, name) { | |
return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name); | |
}, | |
findDeclarationValueFragments: function(declaration, type, name) { | |
return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name); | |
}, | |
findAllFragments: function(ast, type, name) { | |
var result = []; | |
this.syntax.walk(ast, { | |
visit: 'Declaration', | |
enter: function(declaration) { | |
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name)); | |
}.bind(this) | |
}); | |
return result; | |
}, | |
getProperty: function(name) { | |
return this.properties.hasOwnProperty(name) ? this.properties[name] : null; | |
}, | |
getType: function(name) { | |
return this.types.hasOwnProperty(name) ? this.types[name] : null; | |
}, | |
validate: function() { | |
function validate(syntax, name, broken, descriptor) { | |
if (broken.hasOwnProperty(name)) { | |
return broken[name]; | |
} | |
broken[name] = false; | |
if (descriptor.syntax !== null) { | |
walk(descriptor.syntax, function(node) { | |
if (node.type !== 'Type' && node.type !== 'Property') { | |
return; | |
} | |
var map = node.type === 'Type' ? syntax.types : syntax.properties; | |
var brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties; | |
if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) { | |
broken[name] = true; | |
} | |
}, this); | |
} | |
} | |
var brokenTypes = {}; | |
var brokenProperties = {}; | |
for (var key in this.types) { | |
validate(this, key, brokenTypes, this.types[key]); | |
} | |
for (var key in this.properties) { | |
validate(this, key, brokenProperties, this.properties[key]); | |
} | |
brokenTypes = Object.keys(brokenTypes).filter(function(name) { | |
return brokenTypes[name]; | |
}); | |
brokenProperties = Object.keys(brokenProperties).filter(function(name) { | |
return brokenProperties[name]; | |
}); | |
if (brokenTypes.length || brokenProperties.length) { | |
return { | |
types: brokenTypes, | |
properties: brokenProperties | |
}; | |
} | |
return null; | |
}, | |
dump: function(syntaxAsAst) { | |
return { | |
generic: this.generic, | |
types: dumpMapSyntax(this.types, syntaxAsAst), | |
properties: dumpMapSyntax(this.properties, syntaxAsAst) | |
}; | |
}, | |
toString: function() { | |
return JSON.stringify(this.dump()); | |
} | |
}; | |
module.exports = Lexer; | |
},{"../utils/names":143,"./ast-to-tokens":44,"./error":45,"./generic":46,"./grammar/generate":48,"./grammar/parse":50,"./grammar/walk":52,"./match":54,"./match-graph":53,"./search":55,"./structure":56,"./trace":57}],44:[function(require,module,exports){ | |
module.exports = { | |
decorator: function(handlers) { | |
var curNode = null; | |
var prev = null; | |
var tokens = []; | |
return { | |
children: handlers.children, | |
node: function(node) { | |
var tmp = curNode; | |
curNode = node; | |
handlers.node.call(this, node); | |
curNode = tmp; | |
}, | |
chunk: function(chunk) { | |
if (tokens.length > 0) { | |
switch (curNode.type) { | |
case 'Dimension': | |
case 'HexColor': | |
case 'IdSelector': | |
case 'Percentage': | |
if (prev.node === curNode) { | |
prev.value += chunk; | |
return; | |
} | |
break; | |
case 'Function': | |
case 'PseudoClassSelector': | |
case 'PseudoElementSelector': | |
case 'Url': | |
if (chunk === '(') { | |
prev.value += chunk; | |
return; | |
} | |
break; | |
case 'Atrule': | |
if (prev.node === curNode && prev.value === '@') { | |
prev.value += chunk; | |
return; | |
} | |
break; | |
} | |
} | |
tokens.push(prev = { | |
value: chunk, | |
node: curNode | |
}); | |
}, | |
result: function() { | |
return tokens; | |
} | |
}; | |
} | |
}; | |
},{}],45:[function(require,module,exports){ | |
'use strict'; | |
var createCustomError = require('../utils/createCustomError'); | |
var generateGrammar = require('./grammar/generate'); | |
function fromMatchResult(matchResult) { | |
var tokens = matchResult.tokens; | |
var longestMatch = matchResult.longestMatch; | |
var node = longestMatch < tokens.length ? tokens[longestMatch].node : null; | |
var mismatchOffset = 0; | |
var entries = 0; | |
var css = ''; | |
for (var i = 0; i < tokens.length; i++) { | |
if (i === longestMatch) { | |
mismatchOffset = css.length; | |
} | |
if (node !== null && tokens[i].node === node) { | |
if (i <= longestMatch) { | |
entries++; | |
} else { | |
entries = 0; | |
} | |
} | |
css += tokens[i].value; | |
} | |
if (node === null) { | |
mismatchOffset = css.length; | |
} | |
return { | |
node: node, | |
css: css, | |
mismatchOffset: mismatchOffset, | |
last: node === null || entries > 1 | |
}; | |
} | |
function getLocation(node, point) { | |
var loc = node && node.loc && node.loc[point]; | |
if (loc) { | |
return { | |
offset: loc.offset, | |
line: loc.line, | |
column: loc.column | |
}; | |
} | |
return null; | |
} | |
var SyntaxReferenceError = function(type, referenceName) { | |
var error = createCustomError( | |
'SyntaxReferenceError', | |
type + (referenceName ? ' `' + referenceName + '`' : '') | |
); | |
error.reference = referenceName; | |
return error; | |
}; | |
var MatchError = function(message, lexer, syntax, node, matchResult) { | |
var error = createCustomError('SyntaxMatchError', message); | |
var details = fromMatchResult(matchResult); | |
var mismatchOffset = details.mismatchOffset || 0; | |
var badNode = details.node || node; | |
var end = getLocation(badNode, 'end'); | |
var start = details.last ? end : getLocation(badNode, 'start'); | |
var css = details.css; | |
error.rawMessage = message; | |
error.syntax = syntax ? generateGrammar(syntax) : '<generic>'; | |
error.css = css; | |
error.mismatchOffset = mismatchOffset; | |
error.loc = { | |
source: (badNode && badNode.loc && badNode.loc.source) || '<unknown>', | |
start: start, | |
end: end | |
}; | |
error.line = start ? start.line : undefined; | |
error.column = start ? start.column : undefined; | |
error.offset = start ? start.offset : undefined; | |
error.message = message + '\n' + | |
' syntax: ' + error.syntax + '\n' + | |
' value: ' + (error.css || '<empty string>') + '\n' + | |
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^'; | |
return error; | |
}; | |
module.exports = { | |
SyntaxReferenceError: SyntaxReferenceError, | |
MatchError: MatchError | |
}; | |
},{"../utils/createCustomError":141,"./grammar/generate":48}],46:[function(require,module,exports){ | |
var tokenizerUtils = require('../tokenizer/utils'); | |
var findIdentifierEnd = tokenizerUtils.findIdentifierEnd; | |
var findNumberEnd = tokenizerUtils.findNumberEnd; | |
var findDecimalNumberEnd = tokenizerUtils.findDecimalNumberEnd; | |
var isHex = tokenizerUtils.isHex; | |
var tokenizerConst = require('../tokenizer/const'); | |
var SYMBOL_TYPE = tokenizerConst.SYMBOL_TYPE; | |
var IDENTIFIER = tokenizerConst.TYPE.Identifier; | |
var PLUSSIGN = tokenizerConst.TYPE.PlusSign; | |
var HYPHENMINUS = tokenizerConst.TYPE.HyphenMinus; | |
var NUMBERSIGN = tokenizerConst.TYPE.NumberSign; | |
var PERCENTAGE = { | |
'%': true | |
}; | |
// https://www.w3.org/TR/css-values-3/#lengths | |
var LENGTH = { | |
// absolute length units | |
'px': true, | |
'mm': true, | |
'cm': true, | |
'in': true, | |
'pt': true, | |
'pc': true, | |
'q': true, | |
// relative length units | |
'em': true, | |
'ex': true, | |
'ch': true, | |
'rem': true, | |
// viewport-percentage lengths | |
'vh': true, | |
'vw': true, | |
'vmin': true, | |
'vmax': true, | |
'vm': true | |
}; | |
var ANGLE = { | |
'deg': true, | |
'grad': true, | |
'rad': true, | |
'turn': true | |
}; | |
var TIME = { | |
's': true, | |
'ms': true | |
}; | |
var FREQUENCY = { | |
'hz': true, | |
'khz': true | |
}; | |
// https://www.w3.org/TR/css-values-3/#resolution (https://drafts.csswg.org/css-values/#resolution) | |
var RESOLUTION = { | |
'dpi': true, | |
'dpcm': true, | |
'dppx': true, | |
'x': true // https://github.com/w3c/csswg-drafts/issues/461 | |
}; | |
// https://drafts.csswg.org/css-grid/#fr-unit | |
var FLEX = { | |
'fr': true | |
}; | |
// https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume | |
var DECIBEL = { | |
'db': true | |
}; | |
// https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch | |
var SEMITONES = { | |
'st': true | |
}; | |
function consumeFunction(token, addTokenToMatch, getNextToken) { | |
var length = 1; | |
var cursor; | |
do { | |
cursor = getNextToken(length++); | |
} while (cursor !== null && cursor.node !== token.node); | |
if (cursor === null) { | |
return false; | |
} | |
while (true) { | |
// consume tokens until cursor | |
if (addTokenToMatch() === cursor) { | |
break; | |
} | |
} | |
return true; | |
} | |
// TODO: implement | |
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed | |
// https://drafts.csswg.org/css-values/#calc-notation | |
function calc(token, addTokenToMatch, getNextToken) { | |
if (token === null) { | |
return false; | |
} | |
var name = token.value.toLowerCase(); | |
if (name !== 'calc(' && | |
name !== '-moz-calc(' && | |
name !== '-webkit-calc(') { | |
return false; | |
} | |
return consumeFunction(token, addTokenToMatch, getNextToken); | |
} | |
function attr(token, addTokenToMatch, getNextToken) { | |
if (token === null || token.value.toLowerCase() !== 'attr(') { | |
return false; | |
} | |
return consumeFunction(token, addTokenToMatch, getNextToken); | |
} | |
function expression(token, addTokenToMatch, getNextToken) { | |
if (token === null || token.value.toLowerCase() !== 'expression(') { | |
return false; | |
} | |
return consumeFunction(token, addTokenToMatch, getNextToken); | |
} | |
function url(token, addTokenToMatch, getNextToken) { | |
if (token === null || token.value.toLowerCase() !== 'url(') { | |
return false; | |
} | |
return consumeFunction(token, addTokenToMatch, getNextToken); | |
} | |
function idSelector(token, addTokenToMatch) { | |
if (token === null) { | |
return false; | |
} | |
if (token.value.charCodeAt(0) !== NUMBERSIGN) { | |
return false; | |
} | |
if (consumeIdentifier(token.value, 1) !== token.value.length) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
function isNumber(str) { | |
return /^[-+]?(\d+|\d*\.\d+)([eE][-+]?\d+)?$/.test(str); | |
} | |
function consumeNumber(str, allowFraction) { | |
var code = str.charCodeAt(0); | |
return findNumberEnd(str, code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0, allowFraction); | |
} | |
function consumeIdentifier(str, offset) { | |
var code = str.charCodeAt(offset); | |
if (code < 0x80 && SYMBOL_TYPE[code] !== IDENTIFIER && code !== HYPHENMINUS) { | |
return offset; | |
} | |
return findIdentifierEnd(str, offset + 1); | |
} | |
function astNode(type) { | |
return function(token, addTokenToMatch) { | |
if (token === null || token.node.type !== type) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
}; | |
} | |
function dimension(type) { | |
return function(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null) { | |
return false; | |
} | |
var numberEnd = consumeNumber(token.value, true); | |
if (numberEnd === 0) { | |
return false; | |
} | |
if (type) { | |
if (!type.hasOwnProperty(token.value.substr(numberEnd).toLowerCase())) { | |
return false; | |
} | |
} else { | |
var unitEnd = consumeIdentifier(token.value, numberEnd); | |
if (unitEnd === numberEnd || unitEnd !== token.value.length) { | |
return false; | |
} | |
} | |
addTokenToMatch(); | |
return true; | |
}; | |
} | |
function zeroUnitlessDimension(type) { | |
var isDimension = dimension(type); | |
return function(token, addTokenToMatch, getNextToken) { | |
if (isDimension(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null || Number(token.value) !== 0) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
}; | |
} | |
function number(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null) { | |
return false; | |
} | |
var numberEnd = consumeNumber(token.value, true); | |
if (numberEnd !== token.value.length) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
function numberZeroOne(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null || !isNumber(token.value)) { | |
return false; | |
} | |
var value = Number(token.value); | |
if (value < 0 || value > 1) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
function numberOneOrGreater(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null || !isNumber(token.value)) { | |
return false; | |
} | |
var value = Number(token.value); | |
if (value < 1) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
// TODO: fail on 10e-2 | |
function integer(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null) { | |
return false; | |
} | |
var numberEnd = consumeNumber(token.value, false); | |
if (numberEnd !== token.value.length) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
// TODO: fail on 10e-2 | |
function positiveInteger(token, addTokenToMatch, getNextToken) { | |
if (calc(token, addTokenToMatch, getNextToken)) { | |
return true; | |
} | |
if (token === null) { | |
return false; | |
} | |
var numberEnd = findDecimalNumberEnd(token.value, 0); | |
if (numberEnd !== token.value.length || token.value.charCodeAt(0) === HYPHENMINUS) { | |
return false; | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
function hexColor(token, addTokenToMatch) { | |
if (token === null || token.value.charCodeAt(0) !== NUMBERSIGN) { | |
return false; | |
} | |
var length = token.value.length - 1; | |
// valid length is 3, 4, 6 and 8 (+1 for #) | |
if (length !== 3 && length !== 4 && length !== 6 && length !== 8) { | |
return false; | |
} | |
for (var i = 1; i < length; i++) { | |
if (!isHex(token.value.charCodeAt(i))) { | |
return false; | |
} | |
} | |
addTokenToMatch(); | |
return true; | |
} | |
// https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident | |
// https://drafts.csswg.org/css-values-4/#identifier-value | |
function customIdent(token, addTokenToMatch) { | |
if (token === null) { | |
return false; | |
} | |
var identEnd = consumeIdentifier(token.value, 0); | |
if (identEnd !== token.value.length) { | |
return false; | |
} | |
var name = token.value.toLowerCase(); | |
// § 3.2. Author-defined Identifiers: the <custom-ident> type | |
// The CSS-wide keywords are not valid <custom-ident>s | |
if (name === 'unset' || name === 'initial' || name === 'inherit') { | |
return false; | |
} | |
// The default keyword is reserved and is also not a valid <custom-ident> | |
if (name === 'default') { | |
return false; | |
} | |
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident) | |
addTokenToMatch(); | |
return true; | |
} | |
module.exports = { | |
'angle': zeroUnitlessDimension(ANGLE), | |
'attr()': attr, | |
'custom-ident': customIdent, | |
'decibel': dimension(DECIBEL), | |
'dimension': dimension(), | |
'frequency': dimension(FREQUENCY), | |
'flex': dimension(FLEX), | |
'hex-color': hexColor, | |
'id-selector': idSelector, // element( <id-selector> ) | |
'ident': astNode('Identifier'), | |
'integer': integer, | |
'length': zeroUnitlessDimension(LENGTH), | |
'number': number, | |
'number-zero-one': numberZeroOne, | |
'number-one-or-greater': numberOneOrGreater, | |
'percentage': dimension(PERCENTAGE), | |
'positive-integer': positiveInteger, | |
'resolution': dimension(RESOLUTION), | |
'semitones': dimension(SEMITONES), | |
'string': astNode('String'), | |
'time': dimension(TIME), | |
'unicode-range': astNode('UnicodeRange'), | |
'url': url, | |
// old IE stuff | |
'progid': astNode('Raw'), | |
'expression': expression | |
}; | |
},{"../tokenizer/const":136,"../tokenizer/utils":139}],47:[function(require,module,exports){ | |
var createCustomError = require('../../utils/createCustomError'); | |
var SyntaxParseError = function(message, input, offset) { | |
var error = createCustomError('SyntaxParseError', message); | |
error.input = input; | |
error.offset = offset; | |
error.rawMessage = message; | |
error.message = error.rawMessage + '\n' + | |
' ' + error.input + '\n' + | |
'--' + new Array((error.offset || error.input.length) + 1).join('-') + '^'; | |
return error; | |
}; | |
module.exports = { | |
SyntaxParseError: SyntaxParseError | |
}; | |
},{"../../utils/createCustomError":141}],48:[function(require,module,exports){ | |
function noop(value) { | |
return value; | |
} | |
function generateMultiplier(multiplier) { | |
if (multiplier.min === 0 && multiplier.max === 0) { | |
return '*'; | |
} | |
if (multiplier.min === 0 && multiplier.max === 1) { | |
return '?'; | |
} | |
if (multiplier.min === 1 && multiplier.max === 0) { | |
return multiplier.comma ? '#' : '+'; | |
} | |
if (multiplier.min === 1 && multiplier.max === 1) { | |
return ''; | |
} | |
return ( | |
(multiplier.comma ? '#' : '') + | |
(multiplier.min === multiplier.max | |
? '{' + multiplier.min + '}' | |
: '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}' | |
) | |
); | |
} | |
function generateSequence(node, forceBraces, decorate) { | |
var result = node.terms.map(function(term) { | |
return generate(term, forceBraces, decorate); | |
}).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' '); | |
if (node.explicit || forceBraces) { | |
result = (result[0] !== ',' ? '[ ' : '[') + result + ' ]'; | |
} | |
return result; | |
} | |
function generate(node, forceBraces, decorate) { | |
var result; | |
switch (node.type) { | |
case 'Group': | |
result = | |
generateSequence(node, forceBraces, decorate) + | |
(node.disallowEmpty ? '!' : ''); | |
break; | |
case 'Multiplier': | |
// return since node is a composition | |
return ( | |
generate(node.term, forceBraces, decorate) + | |
decorate(generateMultiplier(node), node) | |
); | |
case 'Type': | |
result = '<' + node.name + '>'; | |
break; | |
case 'Property': | |
result = '<\'' + node.name + '\'>'; | |
break; | |
case 'Keyword': | |
result = node.name; | |
break; | |
case 'AtKeyword': | |
result = '@' + node.name; | |
break; | |
case 'Function': | |
result = node.name + '('; | |
break; | |
case 'String': | |
case 'Token': | |
result = node.value; | |
break; | |
case 'Comma': | |
result = ','; | |
break; | |
default: | |
throw new Error('Unknown node type `' + node.type + '`'); | |
} | |
return decorate(result, node); | |
} | |
module.exports = function(node, options) { | |
var decorate = noop; | |
var forceBraces = false; | |
if (typeof options === 'function') { | |
decorate = options; | |
} else if (options) { | |
forceBraces = Boolean(options.forceBraces); | |
if (typeof options.decorate === 'function') { | |
decorate = options.decorate; | |
} | |
} | |
return generate(node, forceBraces, decorate); | |
}; | |
},{}],49:[function(require,module,exports){ | |
module.exports = { | |
SyntaxParseError: require('./error').SyntaxParseError, | |
parse: require('./parse'), | |
generate: require('./generate'), | |
walk: require('./walk') | |
}; | |
},{"./error":47,"./generate":48,"./parse":50,"./walk":52}],50:[function(require,module,exports){ | |
var Tokenizer = require('./tokenizer'); | |
var TAB = 9; | |
var N = 10; | |
var F = 12; | |
var R = 13; | |
var SPACE = 32; | |
var EXCLAMATIONMARK = 33; // ! | |
var NUMBERSIGN = 35; // # | |
var AMPERSAND = 38; // & | |
var APOSTROPHE = 39; // ' | |
var LEFTPARENTHESIS = 40; // ( | |
var RIGHTPARENTHESIS = 41; // ) | |
var ASTERISK = 42; // * | |
var PLUSSIGN = 43; // + | |
var COMMA = 44; // , | |
var LESSTHANSIGN = 60; // < | |
var GREATERTHANSIGN = 62; // > | |
var QUESTIONMARK = 63; // ? | |
var COMMERCIALAT = 64; // @ | |
var LEFTSQUAREBRACKET = 91; // [ | |
var RIGHTSQUAREBRACKET = 93; // ] | |
var LEFTCURLYBRACKET = 123; // { | |
var VERTICALLINE = 124; // | | |
var RIGHTCURLYBRACKET = 125; // } | |
var NAME_CHAR = createCharMap(function(ch) { | |
return /[a-zA-Z0-9\-]/.test(ch); | |
}); | |
var COMBINATOR_PRECEDENCE = { | |
' ': 1, | |
'&&': 2, | |
'||': 3, | |
'|': 4 | |
}; | |
function createCharMap(fn) { | |
var array = typeof Uint32Array === 'function' ? new Uint32Array(128) : new Array(128); | |
for (var i = 0; i < 128; i++) { | |
array[i] = fn(String.fromCharCode(i)) ? 1 : 0; | |
} | |
return array; | |
} | |
function scanSpaces(tokenizer) { | |
return tokenizer.substringToPos( | |
tokenizer.findWsEnd(tokenizer.pos + 1) | |
); | |
} | |
function scanWord(tokenizer) { | |
var end = tokenizer.pos; | |
for (; end < tokenizer.str.length; end++) { | |
var code = tokenizer.str.charCodeAt(end); | |
if (code >= 128 || NAME_CHAR[code] === 0) { | |
break; | |
} | |
} | |
if (tokenizer.pos === end) { | |
tokenizer.error('Expect a keyword'); | |
} | |
return tokenizer.substringToPos(end); | |
} | |
function scanNumber(tokenizer) { | |
var end = tokenizer.pos; | |
for (; end < tokenizer.str.length; end++) { | |
var code = tokenizer.str.charCodeAt(end); | |
if (code < 48 || code > 57) { | |
break; | |
} | |
} | |
if (tokenizer.pos === end) { | |
tokenizer.error('Expect a number'); | |
} | |
return tokenizer.substringToPos(end); | |
} | |
function scanString(tokenizer) { | |
var end = tokenizer.str.indexOf('\'', tokenizer.pos + 1); | |
if (end === -1) { | |
tokenizer.pos = tokenizer.str.length; | |
tokenizer.error('Expect an apostrophe'); | |
} | |
return tokenizer.substringToPos(end + 1); | |
} | |
function readMultiplierRange(tokenizer) { | |
var min = null; | |
var max = null; | |
tokenizer.eat(LEFTCURLYBRACKET); | |
min = scanNumber(tokenizer); | |
if (tokenizer.charCode() === COMMA) { | |
tokenizer.pos++; | |
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) { | |
max = scanNumber(tokenizer); | |
} | |
} else { | |
max = min; | |
} | |
tokenizer.eat(RIGHTCURLYBRACKET); | |
return { | |
min: Number(min), | |
max: max ? Number(max) : 0 | |
}; | |
} | |
function readMultiplier(tokenizer) { | |
var range = null; | |
var comma = false; | |
switch (tokenizer.charCode()) { | |
case ASTERISK: | |
tokenizer.pos++; | |
range = { | |
min: 0, | |
max: 0 | |
}; | |
break; | |
case PLUSSIGN: | |
tokenizer.pos++; | |
range = { | |
min: 1, | |
max: 0 | |
}; | |
break; | |
case QUESTIONMARK: | |
tokenizer.pos++; | |
range = { | |
min: 0, | |
max: 1 | |
}; | |
break; | |
case NUMBERSIGN: | |
tokenizer.pos++; | |
comma = true; | |
if (tokenizer.charCode() === LEFTCURLYBRACKET) { | |
range = readMultiplierRange(tokenizer); | |
} else { | |
range = { | |
min: 1, | |
max: 0 | |
}; | |
} | |
break; | |
case LEFTCURLYBRACKET: | |
range = readMultiplierRange(tokenizer); | |
break; | |
default: | |
return null; | |
} | |
return { | |
type: 'Multiplier', | |
comma: comma, | |
min: range.min, | |
max: range.max, | |
term: null | |
}; | |
} | |
function maybeMultiplied(tokenizer, node) { | |
var multiplier = readMultiplier(tokenizer); | |
if (multiplier !== null) { | |
multiplier.term = node; | |
return multiplier; | |
} | |
return node; | |
} | |
function maybeToken(tokenizer) { | |
var ch = tokenizer.peek(); | |
if (ch === '') { | |
return null; | |
} | |
return { | |
type: 'Token', | |
value: ch | |
}; | |
} | |
function readProperty(tokenizer) { | |
var name; | |
tokenizer.eat(LESSTHANSIGN); | |
tokenizer.eat(APOSTROPHE); | |
name = scanWord(tokenizer); | |
tokenizer.eat(APOSTROPHE); | |
tokenizer.eat(GREATERTHANSIGN); | |
return maybeMultiplied(tokenizer, { | |
type: 'Property', | |
name: name | |
}); | |
} | |
function readType(tokenizer) { | |
var name; | |
tokenizer.eat(LESSTHANSIGN); | |
name = scanWord(tokenizer); | |
if (tokenizer.charCode() === LEFTPARENTHESIS && | |
tokenizer.nextCharCode() === RIGHTPARENTHESIS) { | |
tokenizer.pos += 2; | |
name += '()'; | |
} | |
tokenizer.eat(GREATERTHANSIGN); | |
return maybeMultiplied(tokenizer, { | |
type: 'Type', | |
name: name | |
}); | |
} | |
function readKeywordOrFunction(tokenizer) { | |
var name; | |
name = scanWord(tokenizer); | |
if (tokenizer.charCode() === LEFTPARENTHESIS) { | |
tokenizer.pos++; | |
return { | |
type: 'Function', | |
name: name | |
}; | |
} | |
return maybeMultiplied(tokenizer, { | |
type: 'Keyword', | |
name: name | |
}); | |
} | |
function regroupTerms(terms, combinators) { | |
function createGroup(terms, combinator) { | |
return { | |
type: 'Group', | |
terms: terms, | |
combinator: combinator, | |
disallowEmpty: false, | |
explicit: false | |
}; | |
} | |
combinators = Object.keys(combinators).sort(function(a, b) { | |
return COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]; | |
}); | |
while (combinators.length > 0) { | |
var combinator = combinators.shift(); | |
for (var i = 0, subgroupStart = 0; i < terms.length; i++) { | |
var term = terms[i]; | |
if (term.type === 'Combinator') { | |
if (term.value === combinator) { | |
if (subgroupStart === -1) { | |
subgroupStart = i - 1; | |
} | |
terms.splice(i, 1); | |
i--; | |
} else { | |
if (subgroupStart !== -1 && i - subgroupStart > 1) { | |
terms.splice( | |
subgroupStart, | |
i - subgroupStart, | |
createGroup(terms.slice(subgroupStart, i), combinator) | |
); | |
i = subgroupStart + 1; | |
} | |
subgroupStart = -1; | |
} | |
} | |
} | |
if (subgroupStart !== -1 && combinators.length) { | |
terms.splice( | |
subgroupStart, | |
i - subgroupStart, | |
createGroup(terms.slice(subgroupStart, i), combinator) | |
); | |
} | |
} | |
return combinator; | |
} | |
function readImplicitGroup(tokenizer) { | |
var terms = []; | |
var combinators = {}; | |
var token; | |
var prevToken = null; | |
var prevTokenPos = tokenizer.pos; | |
while (token = peek(tokenizer)) { | |
if (token.type !== 'Spaces') { | |
if (token.type === 'Combinator') { | |
// check for combinator in group beginning and double combinator sequence | |
if (prevToken === null || prevToken.type === 'Combinator') { | |
tokenizer.pos = prevTokenPos; | |
tokenizer.error('Unexpected combinator'); | |
} | |
combinators[token.value] = true; | |
} else if (prevToken !== null && prevToken.type !== 'Combinator') { | |
combinators[' '] = true; // a b | |
terms.push({ | |
type: 'Combinator', | |
value: ' ' | |
}); | |
} | |
terms.push(token); | |
prevToken = token; | |
prevTokenPos = tokenizer.pos; | |
} | |
} | |
// check for combinator in group ending | |
if (prevToken !== null && prevToken.type === 'Combinator') { | |
tokenizer.pos -= prevTokenPos; | |
tokenizer.error('Unexpected combinator'); | |
} | |
return { | |
type: 'Group', | |
terms: terms, | |
combinator: regroupTerms(terms, combinators) || ' ', | |
disallowEmpty: false, | |
explicit: false | |
}; | |
} | |
function readGroup(tokenizer) { | |
var result; | |
tokenizer.eat(LEFTSQUAREBRACKET); | |
result = readImplicitGroup(tokenizer); | |
tokenizer.eat(RIGHTSQUAREBRACKET); | |
result.explicit = true; | |
if (tokenizer.charCode() === EXCLAMATIONMARK) { | |
tokenizer.pos++; | |
result.disallowEmpty = true; | |
} | |
return result; | |
} | |
function peek(tokenizer) { | |
var code = tokenizer.charCode(); | |
if (code < 128 && NAME_CHAR[code] === 1) { | |
return readKeywordOrFunction(tokenizer); | |
} | |
switch (code) { | |
case RIGHTSQUAREBRACKET: | |
// don't eat, stop scan a group | |
break; | |
case LEFTSQUAREBRACKET: | |
return maybeMultiplied(tokenizer, readGroup(tokenizer)); | |
case LESSTHANSIGN: | |
return tokenizer.nextCharCode() === APOSTROPHE | |
? readProperty(tokenizer) | |
: readType(tokenizer); | |
case VERTICALLINE: | |
return { | |
type: 'Combinator', | |
value: tokenizer.substringToPos( | |
tokenizer.nextCharCode() === VERTICALLINE | |
? tokenizer.pos + 2 | |
: tokenizer.pos + 1 | |
) | |
}; | |
case AMPERSAND: | |
tokenizer.pos++; | |
tokenizer.eat(AMPERSAND); | |
return { | |
type: 'Combinator', | |
value: '&&' | |
}; | |
case COMMA: | |
tokenizer.pos++; | |
return { | |
type: 'Comma' | |
}; | |
case APOSTROPHE: | |
return maybeMultiplied(tokenizer, { | |
type: 'String', | |
value: scanString(tokenizer) | |
}); | |
case SPACE: | |
case TAB: | |
case N: | |
case R: | |
case F: | |
return { | |
type: 'Spaces', | |
value: scanSpaces(tokenizer) | |
}; | |
case COMMERCIALAT: | |
code = tokenizer.nextCharCode(); | |
if (code < 128 && NAME_CHAR[code] === 1) { | |
tokenizer.pos++; | |
return { | |
type: 'AtKeyword', | |
name: scanWord(tokenizer) | |
}; | |
} | |
return maybeToken(tokenizer); | |
case ASTERISK: | |
case PLUSSIGN: | |
case QUESTIONMARK: | |
case NUMBERSIGN: | |
case EXCLAMATIONMARK: | |
// prohibited tokens (used as a multiplier start) | |
break; | |
case LEFTCURLYBRACKET: | |
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting | |
// check next char isn't a number, because it's likely a disjoined multiplier | |
code = tokenizer.nextCharCode(); | |
if (code < 48 || code > 57) { | |
return maybeToken(tokenizer); | |
} | |
break; | |
default: | |
return maybeToken(tokenizer); | |
} | |
} | |
function parse(str) { | |
var tokenizer = new Tokenizer(str); | |
var result = readImplicitGroup(tokenizer); | |
if (tokenizer.pos !== str.length) { | |
tokenizer.error('Unexpected input'); | |
} | |
// reduce redundant groups with single group term | |
if (result.terms.length === 1 && result.terms[0].type === 'Group') { | |
result = result.terms[0]; | |
} | |
return result; | |
} | |
// warm up parse to elimitate code branches that never execute | |
// fix soft deoptimizations (insufficient type feedback) | |
parse('[a&&<b>#|<\'c\'>*||e() f{2} /,(% g#{1,2} h{2,})]!'); | |
module.exports = parse; | |
},{"./tokenizer":51}],51:[function(require,module,exports){ | |
var SyntaxParseError = require('./error').SyntaxParseError; | |
var TAB = 9; | |
var N = 10; | |
var F = 12; | |
var R = 13; | |
var SPACE = 32; | |
var Tokenizer = function(str) { | |
this.str = str; | |
this.pos = 0; | |
}; | |
Tokenizer.prototype = { | |
charCodeAt: function(pos) { | |
return pos < this.str.length ? this.str.charCodeAt(pos) : 0; | |
}, | |
charCode: function() { | |
return this.charCodeAt(this.pos); | |
}, | |
nextCharCode: function() { | |
return this.charCodeAt(this.pos + 1); | |
}, | |
nextNonWsCode: function(pos) { | |
return this.charCodeAt(this.findWsEnd(pos)); | |
}, | |
findWsEnd: function(pos) { | |
for (; pos < this.str.length; pos++) { | |
var code = this.str.charCodeAt(pos); | |
if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) { | |
break; | |
} | |
} | |
return pos; | |
}, | |
substringToPos: function(end) { | |
return this.str.substring(this.pos, this.pos = end); | |
}, | |
eat: function(code) { | |
if (this.charCode() !== code) { | |
this.error('Expect `' + String.fromCharCode(code) + '`'); | |
} | |
this.pos++; | |
}, | |
peek: function() { | |
return this.pos < this.str.length ? this.str.charAt(this.pos++) : ''; | |
}, | |
error: function(message) { | |
throw new SyntaxParseError(message, this.str, this.pos); | |
} | |
}; | |
module.exports = Tokenizer; | |
},{"./error":47}],52:[function(require,module,exports){ | |
'use strict'; | |
var noop = function() {}; | |
function ensureFunction(value) { | |
return typeof value === 'function' ? value : noop; | |
} | |
module.exports = function(node, options, context) { | |
function walk(node) { | |
enter.call(context, node); | |
switch (node.type) { | |
case 'Group': | |
node.terms.forEach(walk); | |
break; | |
case 'Multiplier': | |
walk(node.term); | |
break; | |
case 'Type': | |
case 'Property': | |
case 'Keyword': | |
case 'AtKeyword': | |
case 'Function': | |
case 'String': | |
case 'Token': | |
case 'Comma': | |
break; | |
default: | |
throw new Error('Unknown type: ' + node.type); | |
} | |
leave.call(context, node); | |
} | |
var enter = noop; | |
var leave = noop; | |
if (typeof options === 'function') { | |
enter = options; | |
} else if (options) { | |
enter = ensureFunction(options.enter); | |
leave = ensureFunction(options.leave); | |
} | |
if (enter === noop && leave === noop) { | |
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function'); | |
} | |
walk(node, context); | |
}; | |
},{}],53:[function(require,module,exports){ | |
var parse = require('./grammar/parse'); | |
var MATCH = { type: 'Match' }; | |
var MISMATCH = { type: 'Mismatch' }; | |
var DISALLOW_EMPTY = { type: 'DisallowEmpty' }; | |
var LEFTPARENTHESIS = 40; // ( | |
var RIGHTPARENTHESIS = 41; // ) | |
function createCondition(match, thenBranch, elseBranch) { | |
// reduce node count | |
if (thenBranch === MATCH && elseBranch === MISMATCH) { | |
return match; | |
} | |
if (match === MATCH && thenBranch === MATCH && elseBranch === MATCH) { | |
return match; | |
} | |
if (match.type === 'If' && match.else === MISMATCH && thenBranch === MATCH) { | |
thenBranch = match.then; | |
match = match.match; | |
} | |
return { | |
type: 'If', | |
match: match, | |
then: thenBranch, | |
else: elseBranch | |
}; | |
} | |
function isFunctionType(name) { | |
return ( | |
name.length > 2 && | |
name.charCodeAt(name.length - 2) === LEFTPARENTHESIS && | |
name.charCodeAt(name.length - 1) === RIGHTPARENTHESIS | |
); | |
} | |
function isEnumCapatible(term) { | |
return ( | |
term.type === 'Keyword' || | |
term.type === 'AtKeyword' || | |
term.type === 'Function' || | |
term.type === 'Type' && isFunctionType(term.name) | |
); | |
} | |
function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) { | |
switch (combinator) { | |
case ' ': | |
// Juxtaposing components means that all of them must occur, in the given order. | |
// | |
// a b c | |
// = | |
// match a | |
// then match b | |
// then match c | |
// then MATCH | |
// else MISMATCH | |
// else MISMATCH | |
// else MISMATCH | |
var result = MATCH; | |
for (var i = terms.length - 1; i >= 0; i--) { | |
var term = terms[i]; | |
result = createCondition( | |
term, | |
result, | |
MISMATCH | |
); | |
}; | |
return result; | |
case '|': | |
// A bar (|) separates two or more alternatives: exactly one of them must occur. | |
// | |
// a | b | c | |
// = | |
// match a | |
// then MATCH | |
// else match b | |
// then MATCH | |
// else match c | |
// then MATCH | |
// else MISMATCH | |
var result = MISMATCH; | |
var map = null; | |
for (var i = terms.length - 1; i >= 0; i--) { | |
var term = terms[i]; | |
// reduce sequence of keywords into a Enum | |
if (isEnumCapatible(term)) { | |
if (map === null && i > 0 && isEnumCapatible(terms[i - 1])) { | |
map = Object.create(null); | |
result = createCondition( | |
{ | |
type: 'Enum', | |
map: map | |
}, | |
MATCH, | |
result | |
); | |
} | |
if (map !== null) { | |
var key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase(); | |
if (key in map === false) { | |
map[key] = term; | |
continue; | |
} | |
} | |
} | |
map = null; | |
// create a new conditonal node | |
result = createCondition( | |
term, | |
MATCH, | |
result | |
); | |
}; | |
return result; | |
case '&&': | |
// A double ampersand (&&) separates two or more components, | |
// all of which must occur, in any order. | |
// Use MatchOnce for groups with a large number of terms, | |
// since &&-groups produces at least N!-node trees | |
if (terms.length > 5) { | |
return { | |
type: 'MatchOnce', | |
terms: terms, | |
all: true | |
}; | |
} | |
// Use a combination tree for groups with small number of terms | |
// | |
// a && b && c | |
// = | |
// match a | |
// then [b && c] | |
// else match b | |
// then [a && c] | |
// else match c | |
// then [a && b] | |
// else MISMATCH | |
// | |
// a && b | |
// = | |
// match a | |
// then match b | |
// then MATCH | |
// else MISMATCH | |
// else match b | |
// then match a | |
// then MATCH | |
// else MISMATCH | |
// else MISMATCH | |
var result = MISMATCH; | |
for (var i = terms.length - 1; i >= 0; i--) { | |
var term = terms[i]; | |
var thenClause; | |
if (terms.length > 1) { | |
thenClause = buildGroupMatchGraph( | |
combinator, | |
terms.filter(function(newGroupTerm) { | |
return newGroupTerm !== term; | |
}), | |
false | |
); | |
} else { | |
thenClause = MATCH; | |
} | |
result = createCondition( | |
term, | |
thenClause, | |
result | |
); | |
}; | |
return result; | |
case '||': | |
// A double bar (||) separates two or more options: | |
// one or more of them must occur, in any order. | |
// Use MatchOnce for groups with a large number of terms, | |
// since ||-groups produces at least N!-node trees | |
if (terms.length > 5) { | |
return { | |
type: 'MatchOnce', | |
terms: terms, | |
all: false | |
};; | |
} | |
// Use a combination tree for groups with small number of terms | |
// | |
// a || b || c | |
// = | |
// match a | |
// then [b || c] | |
// else match b | |
// then [a || c] | |
// else match c | |
// then [a || b] | |
// else MISMATCH | |
// | |
// a || b | |
// = | |
// match a | |
// then match b | |
// then MATCH | |
// else MATCH | |
// else match b | |
// then match a | |
// then MATCH | |
// else MATCH | |
// else MISMATCH | |
var result = atLeastOneTermMatched ? MATCH : MISMATCH; | |
for (var i = terms.length - 1; i >= 0; i--) { | |
var term = terms[i]; | |
var thenClause; | |
if (terms.length > 1) { | |
thenClause = buildGroupMatchGraph( | |
combinator, | |
terms.filter(function(newGroupTerm) { | |
return newGroupTerm !== term; | |
}), | |
true | |
); | |
} else { | |
thenClause = MATCH; | |
} | |
result = createCondition( | |
term, | |
thenClause, | |
result | |
); | |
}; | |
return result; | |
} | |
} | |
function buildMultiplierMatchGraph(node) { | |
var result = MATCH; | |
var matchTerm = buildMatchGraph(node.term); | |
if (node.max === 0) { | |
// disable repeating of empty match to prevent infinite loop | |
matchTerm = createCondition( | |
matchTerm, | |
DISALLOW_EMPTY, | |
MISMATCH | |
); | |
// an occurrence count is not limited, make a cycle; | |
// to collect more terms on each following matching mismatch | |
result = createCondition( | |
matchTerm, | |
null, // will be a loop | |
MISMATCH | |
); | |
result.then = createCondition( | |
MATCH, | |
MATCH, | |
result // make a loop | |
); | |
if (node.comma) { | |
result.then.else = createCondition( | |
{ type: 'Comma', syntax: node }, | |
result, | |
MISMATCH | |
); | |
} | |
} else { | |
// create a match node chain for [min .. max] interval with optional matches | |
for (var i = node.min || 1; i <= node.max; i++) { | |
if (node.comma && result !== MATCH) { | |
result = createCondition( | |
{ type: 'Comma', syntax: node }, | |
result, | |
MISMATCH | |
); | |
} | |
result = createCondition( | |
matchTerm, | |
createCondition( | |
MATCH, | |
MATCH, | |
result | |
), | |
MISMATCH | |
); | |
} | |
} | |
if (node.min === 0) { | |
// allow zero match | |
result = createCondition( | |
MATCH, | |
MATCH, | |
result | |
); | |
} else { | |
// create a match node chain to collect [0 ... min - 1] required matches | |
for (var i = 0; i < node.min - 1; i++) { | |
if (node.comma && result !== MATCH) { | |
result = createCondition( | |
{ type: 'Comma', syntax: node }, | |
result, | |
MISMATCH | |
); | |
} | |
result = createCondition( | |
matchTerm, | |
result, | |
MISMATCH | |
); | |
} | |
} | |
return result; | |
} | |
function buildMatchGraph(node) { | |
if (typeof node === 'function') { | |
return { | |
type: 'Generic', | |
fn: node | |
}; | |
} | |
switch (node.type) { | |
case 'Group': | |
var result = buildGroupMatchGraph( | |
node.combinator, | |
node.terms.map(buildMatchGraph), | |
false | |
); | |
if (node.disallowEmpty) { | |
result = createCondition( | |
result, | |
DISALLOW_EMPTY, | |
MISMATCH | |
); | |
} | |
return result; | |
case 'Multiplier': | |
return buildMultiplierMatchGraph(node); | |
case 'Type': | |
case 'Property': | |
return { | |
type: node.type, | |
name: node.name, | |
syntax: node | |
}; | |
case 'Keyword': | |
return { | |
type: node.type, | |
name: node.name.toLowerCase(), | |
syntax: node | |
}; | |
case 'AtKeyword': | |
return { | |
type: node.type, | |
name: '@' + node.name.toLowerCase(), | |
syntax: node | |
}; | |
case 'Function': | |
return { | |
type: node.type, | |
name: node.name.toLowerCase() + '(', | |
syntax: node | |
}; | |
case 'String': | |
// convert a one char length String to a Token | |
if (node.value.length === 3) { | |
return { | |
type: 'Token', | |
value: node.value.charAt(1), | |
syntax: node | |
}; | |
} | |
// otherwise use it as is | |
return { | |
type: node.type, | |
value: node.value, | |
syntax: node | |
}; | |
case 'Token': | |
return { | |
type: node.type, | |
value: node.value, | |
syntax: node | |
}; | |
case 'Comma': | |
return { | |
type: node.type, | |
syntax: node | |
}; | |
default: | |
throw new Error('Unknown node type:', node.type); | |
} | |
} | |
module.exports = { | |
MATCH: MATCH, | |
MISMATCH: MISMATCH, | |
DISALLOW_EMPTY: DISALLOW_EMPTY, | |
buildMatchGraph: function(syntaxTree, ref) { | |
if (typeof syntaxTree === 'string') { | |
syntaxTree = parse(syntaxTree); | |
} | |
return { | |
type: 'MatchGraph', | |
match: buildMatchGraph(syntaxTree), | |
syntax: ref || null, | |
source: syntaxTree | |
}; | |
} | |
}; | |
},{"./grammar/parse":50}],54:[function(require,module,exports){ | |
'use strict'; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var matchGraph = require('./match-graph'); | |
var MATCH = matchGraph.MATCH; | |
var MISMATCH = matchGraph.MISMATCH; | |
var DISALLOW_EMPTY = matchGraph.DISALLOW_EMPTY; | |
var TOKEN = 1; | |
var OPEN_SYNTAX = 2; | |
var CLOSE_SYNTAX = 3; | |
var EXIT_REASON_MATCH = 'Match'; | |
var EXIT_REASON_MISMATCH = 'Mismatch'; | |
var EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)'; | |
var ITERATION_LIMIT = 10000; | |
var totalIterationCount = 0; | |
function mapList(list, fn) { | |
var result = []; | |
while (list) { | |
result.unshift(fn(list)); | |
list = list.prev; | |
} | |
return result; | |
} | |
function isCommaContextStart(token) { | |
if (token === null) { | |
return true; | |
} | |
token = token.value.charAt(token.value.length - 1); | |
return ( | |
token === ',' || | |
token === '(' || | |
token === '[' || | |
token === '/' | |
); | |
} | |
function isCommaContextEnd(token) { | |
if (token === null) { | |
return true; | |
} | |
token = token.value.charAt(0); | |
return ( | |
token === ')' || | |
token === ']' || | |
token === '/' | |
); | |
} | |
function internalMatch(tokens, syntax, syntaxes) { | |
function moveToNextToken() { | |
do { | |
tokenCursor++; | |
token = tokenCursor < tokens.length ? tokens[tokenCursor] : null; | |
} while (token !== null && !/\S/.test(token.value)); | |
} | |
function getNextToken(offset) { | |
var nextIndex = tokenCursor + offset; | |
return nextIndex < tokens.length ? tokens[nextIndex] : null; | |
} | |
function pushThenStack(nextSyntax) { | |
thenStack = { | |
nextSyntax: nextSyntax, | |
matchStack: matchStack, | |
syntaxStack: syntaxStack, | |
prev: thenStack | |
}; | |
} | |
function pushElseStack(nextSyntax) { | |
elseStack = { | |
nextSyntax: nextSyntax, | |
matchStack: matchStack, | |
syntaxStack: syntaxStack, | |
thenStack: thenStack, | |
tokenCursor: tokenCursor, | |
token: token, | |
prev: elseStack | |
}; | |
} | |
function addTokenToMatch() { | |
matchStack = { | |
type: TOKEN, | |
syntax: syntax.syntax, | |
token: token, | |
prev: matchStack | |
}; | |
moveToNextToken(); | |
if (tokenCursor > longestMatch) { | |
longestMatch = tokenCursor; | |
} | |
return matchStack.token; | |
} | |
function openSyntax() { | |
syntaxStack = { | |
syntax: syntax, | |
prev: syntaxStack | |
}; | |
matchStack = { | |
type: OPEN_SYNTAX, | |
syntax: syntax.syntax, | |
token: matchStack.token, | |
prev: matchStack | |
}; | |
} | |
function closeSyntax() { | |
if (matchStack.type === OPEN_SYNTAX) { | |
matchStack = matchStack.prev; | |
} else { | |
matchStack = { | |
type: CLOSE_SYNTAX, | |
syntax: syntaxStack.syntax, | |
token: matchStack.token, | |
prev: matchStack | |
}; | |
} | |
syntaxStack = syntaxStack.prev; | |
} | |
var syntaxStack = null; | |
var thenStack = null; | |
var elseStack = null; | |
var iterationCount = 0; | |
var exitReason = EXIT_REASON_MATCH; | |
var matchStack = { type: 'Stub', syntax: null, token: null, tokenCursor: -1, prev: null }; | |
var longestMatch = 0; | |
var tokenCursor = -1; | |
var token = null; | |
moveToNextToken(); | |
while (true) { | |
// console.log('--\n', | |
// '#' + iterationCount, | |
// require('util').inspect({ | |
// match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? x.type + '!' + x.syntax.name : null), | |
// elseStack: mapList(elseStack, x => x.id), | |
// thenStack: mapList(thenStack, x => x.id), | |
// token: token && token.value, | |
// tokenCursor, | |
// syntax | |
// }, { depth: null }) | |
// ); | |
// prevent infinite loop | |
if (++iterationCount === ITERATION_LIMIT) { | |
console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations'); | |
exitReason = EXIT_REASON_ITERATION_LIMIT; | |
break; | |
} | |
if (syntax === MATCH) { | |
if (thenStack === null) { | |
// turn to MISMATCH when some tokens left unmatched | |
if (token !== null) { | |
// doesn't mismatch if just one token left and it's an IE hack | |
if (tokenCursor !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) { | |
syntax = MISMATCH; | |
continue; | |
} | |
} | |
// break the main loop, return a result - MATCH | |
exitReason = EXIT_REASON_MATCH; | |
break; | |
} | |
// go to next syntax (`then` branch) | |
syntax = thenStack.nextSyntax; | |
// check match is not empty | |
if (syntax === DISALLOW_EMPTY) { | |
if (thenStack.matchStack.token === matchStack.token) { | |
syntax = MISMATCH; | |
continue; | |
} else { | |
syntax = MATCH; | |
} | |
} | |
// close syntax if needed | |
while (syntaxStack !== null && thenStack.syntaxStack !== syntaxStack) { | |
closeSyntax(); | |
} | |
// pop stack | |
thenStack = thenStack.prev; | |
continue; | |
} | |
if (syntax === MISMATCH) { | |
if (elseStack === null) { | |
// break the main loop, return a result - MISMATCH | |
exitReason = EXIT_REASON_MISMATCH; | |
break; | |
} | |
// go to next syntax (`else` branch) | |
syntax = elseStack.nextSyntax; | |
// restore all the rest stack states | |
thenStack = elseStack.thenStack; | |
syntaxStack = elseStack.syntaxStack; | |
matchStack = elseStack.matchStack; | |
tokenCursor = elseStack.tokenCursor; | |
token = elseStack.token; | |
// pop stack | |
elseStack = elseStack.prev; | |
continue; | |
} | |
switch (syntax.type) { | |
case 'MatchGraph': | |
syntax = syntax.match; | |
break; | |
case 'If': | |
// IMPORTANT: else stack push must go first, | |
// since it stores the state of thenStack before changes | |
if (syntax.else !== MISMATCH) { | |
pushElseStack(syntax.else); | |
} | |
if (syntax.then !== MATCH) { | |
pushThenStack(syntax.then); | |
} | |
syntax = syntax.match; | |
break; | |
case 'MatchOnce': | |
syntax = { | |
type: 'MatchOnceBuffer', | |
terms: syntax.terms, | |
all: syntax.all, | |
matchStack: matchStack, | |
index: 0, | |
mask: 0 | |
}; | |
break; | |
case 'MatchOnceBuffer': | |
if (syntax.index === syntax.terms.length) { | |
// if no matches during a cycle | |
if (syntax.matchStack === matchStack) { | |
// no matches at all or it's required all terms to be matched | |
if (syntax.mask === 0 || syntax.all) { | |
syntax = MISMATCH; | |
break; | |
} | |
// a partial match is ok | |
syntax = MATCH; | |
break; | |
} else { | |
// start trying to match from the start | |
syntax.index = 0; | |
syntax.matchStack = matchStack; | |
} | |
} | |
for (; syntax.index < syntax.terms.length; syntax.index++) { | |
if ((syntax.mask & (1 << syntax.index)) === 0) { | |
// IMPORTANT: else stack push must go first, | |
// since it stores the state of thenStack before changes | |
pushElseStack(syntax); | |
pushThenStack({ | |
type: 'AddMatchOnce', | |
buffer: syntax | |
}); | |
// match | |
syntax = syntax.terms[syntax.index++]; | |
break; | |
} | |
} | |
break; | |
case 'AddMatchOnce': | |
syntax = syntax.buffer; | |
var newMask = syntax.mask | (1 << (syntax.index - 1)); | |
// all terms are matched | |
if (newMask === (1 << syntax.terms.length) - 1) { | |
syntax = MATCH; | |
continue; | |
} | |
syntax = { | |
type: 'MatchOnceBuffer', | |
terms: syntax.terms, | |
all: syntax.all, | |
matchStack: syntax.matchStack, | |
index: syntax.index, | |
mask: newMask | |
}; | |
break; | |
case 'Enum': | |
var name = token !== null ? token.value.toLowerCase() : ''; | |
// drop \0 and \9 hack from keyword name | |
if (name.indexOf('\\') !== -1) { | |
name = name.replace(/\\[09].*$/, ''); | |
} | |
if (hasOwnProperty.call(syntax.map, name)) { | |
syntax = syntax.map[name]; | |
} else { | |
syntax = MISMATCH; | |
} | |
break; | |
case 'Generic': | |
syntax = syntax.fn(token, addTokenToMatch, getNextToken) ? MATCH : MISMATCH; | |
break; | |
case 'Type': | |
case 'Property': | |
openSyntax(); | |
var syntaxDict = syntax.type === 'Type' ? 'types' : 'properties'; | |
if (hasOwnProperty.call(syntaxes, syntaxDict) && syntaxes[syntaxDict][syntax.name]) { | |
syntax = syntaxes[syntaxDict][syntax.name].match; | |
} else { | |
syntax = undefined; | |
} | |
if (!syntax) { | |
throw new Error( | |
'Bad syntax reference: ' + | |
(syntaxStack.syntax.type === 'Type' | |
? '<' + syntaxStack.syntax.name + '>' | |
: '<\'' + syntaxStack.syntax.name + '\'>') | |
); | |
} | |
break; | |
case 'Keyword': | |
var name = syntax.name; | |
if (token !== null) { | |
var keywordName = token.value; | |
// drop \0 and \9 hack from keyword name | |
if (keywordName.indexOf('\\') !== -1) { | |
keywordName = keywordName.replace(/\\[09].*$/, ''); | |
} | |
if (keywordName.toLowerCase() === name) { | |
addTokenToMatch(); | |
syntax = MATCH; | |
break; | |
} | |
} | |
syntax = MISMATCH; | |
break; | |
case 'AtKeyword': | |
case 'Function': | |
if (token !== null && token.value.toLowerCase() === syntax.name) { | |
addTokenToMatch(); | |
syntax = MATCH; | |
break; | |
} | |
syntax = MISMATCH; | |
break; | |
case 'Token': | |
if (token !== null && token.value === syntax.value) { | |
addTokenToMatch(); | |
syntax = MATCH; | |
break; | |
} | |
syntax = MISMATCH; | |
break; | |
case 'Comma': | |
if (token !== null && token.value === ',') { | |
if (isCommaContextStart(matchStack.token)) { | |
syntax = MISMATCH; | |
} else { | |
addTokenToMatch(); | |
syntax = isCommaContextEnd(token) ? MISMATCH : MATCH; | |
} | |
} else { | |
syntax = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? MATCH : MISMATCH; | |
} | |
break; | |
// case 'String': | |
// TODO: strings with length other than 1 char | |
default: | |
throw new Error('Unknown node type: ' + syntax.type); | |
} | |
} | |
totalIterationCount += iterationCount; | |
if (exitReason === EXIT_REASON_MATCH) { | |
while (syntaxStack !== null) { | |
closeSyntax(); | |
} | |
} else { | |
matchStack = null; | |
} | |
return { | |
tokens: tokens, | |
reason: exitReason, | |
iterations: iterationCount, | |
match: matchStack, | |
longestMatch: longestMatch | |
}; | |
} | |
function matchAsList(tokens, matchGraph, syntaxes) { | |
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {}); | |
if (matchResult.match !== null) { | |
matchResult.match = mapList(matchResult.match, function(item) { | |
if (item.type === OPEN_SYNTAX || item.type === CLOSE_SYNTAX) { | |
return { type: item.type, syntax: item.syntax }; | |
} | |
return { | |
syntax: item.syntax, | |
token: item.token && item.token.value, | |
node: item.token && item.token.node | |
}; | |
}).slice(1); | |
} | |
return matchResult; | |
} | |
function matchAsTree(tokens, matchGraph, syntaxes) { | |
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {}); | |
if (matchResult.match === null) { | |
return matchResult; | |
} | |
var cursor = matchResult.match; | |
var host = matchResult.match = { | |
syntax: matchGraph.syntax || null, | |
match: [] | |
}; | |
var stack = [host]; | |
// revert a list | |
var prev = null; | |
var next = null; | |
while (cursor !== null) { | |
next = cursor.prev; | |
cursor.prev = prev; | |
prev = cursor; | |
cursor = next; | |
} | |
// init the cursor to start with 2nd item since 1st is a stub item | |
cursor = prev.prev; | |
// build a tree | |
while (cursor !== null && cursor.syntax !== null) { | |
var entry = cursor; | |
switch (entry.type) { | |
case OPEN_SYNTAX: | |
host.match.push(host = { | |
syntax: entry.syntax, | |
match: [] | |
}); | |
stack.push(host); | |
break; | |
case CLOSE_SYNTAX: | |
stack.pop(); | |
host = stack[stack.length - 1]; | |
break; | |
default: | |
host.match.push({ | |
syntax: entry.syntax || null, | |
token: entry.token.value, | |
node: entry.token.node | |
}); | |
} | |
cursor = cursor.prev; | |
} | |
return matchResult; | |
} | |
module.exports = { | |
matchAsList: matchAsList, | |
matchAsTree: matchAsTree, | |
getTotalIterationCount: function() { | |
return totalIterationCount; | |
} | |
}; | |
},{"./match-graph":53}],55:[function(require,module,exports){ | |
var List = require('../utils/list'); | |
function getFirstMatchNode(matchNode) { | |
if ('node' in matchNode) { | |
return matchNode.node; | |
} | |
return getFirstMatchNode(matchNode.match[0]); | |
} | |
function getLastMatchNode(matchNode) { | |
if ('node' in matchNode) { | |
return matchNode.node; | |
} | |
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]); | |
} | |
function matchFragments(lexer, ast, match, type, name) { | |
function findFragments(matchNode) { | |
if (matchNode.syntax !== null && | |
matchNode.syntax.type === type && | |
matchNode.syntax.name === name) { | |
var start = getFirstMatchNode(matchNode); | |
var end = getLastMatchNode(matchNode); | |
lexer.syntax.walk(ast, function(node, item, list) { | |
if (node === start) { | |
var nodes = new List(); | |
do { | |
nodes.appendData(item.data); | |
if (item.data === end) { | |
break; | |
} | |
item = item.next; | |
} while (item !== null); | |
fragments.push({ | |
parent: list, | |
nodes: nodes | |
}); | |
} | |
}); | |
} | |
if (Array.isArray(matchNode.match)) { | |
matchNode.match.forEach(findFragments); | |
} | |
} | |
var fragments = []; | |
if (match.matched !== null) { | |
findFragments(match.matched); | |
} | |
return fragments; | |
} | |
module.exports = { | |
matchFragments: matchFragments | |
}; | |
},{"../utils/list":142}],56:[function(require,module,exports){ | |
var List = require('../utils/list'); | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
function isValidNumber(value) { | |
// Number.isInteger(value) && value >= 0 | |
return ( | |
typeof value === 'number' && | |
isFinite(value) && | |
Math.floor(value) === value && | |
value >= 0 | |
); | |
} | |
function isValidLocation(loc) { | |
return ( | |
Boolean(loc) && | |
isValidNumber(loc.offset) && | |
isValidNumber(loc.line) && | |
isValidNumber(loc.column) | |
); | |
} | |
function createNodeStructureChecker(type, fields) { | |
return function checkNode(node, warn) { | |
if (!node || node.constructor !== Object) { | |
return warn(node, 'Type of node should be an Object'); | |
} | |
for (var key in node) { | |
var valid = true; | |
if (hasOwnProperty.call(node, key) === false) { | |
continue; | |
} | |
if (key === 'type') { | |
if (node.type !== type) { | |
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`'); | |
} | |
} else if (key === 'loc') { | |
if (node.loc === null) { | |
continue; | |
} else if (node.loc && node.loc.constructor === Object) { | |
if (typeof node.loc.source !== 'string') { | |
key += '.source'; | |
} else if (!isValidLocation(node.loc.start)) { | |
key += '.start'; | |
} else if (!isValidLocation(node.loc.end)) { | |
key += '.end'; | |
} else { | |
continue; | |
} | |
} | |
valid = false; | |
} else if (fields.hasOwnProperty(key)) { | |
for (var i = 0, valid = false; !valid && i < fields[key].length; i++) { | |
var fieldType = fields[key][i]; | |
switch (fieldType) { | |
case String: | |
valid = typeof node[key] === 'string'; | |
break; | |
case Boolean: | |
valid = typeof node[key] === 'boolean'; | |
break; | |
case null: | |
valid = node[key] === null; | |
break; | |
default: | |
if (typeof fieldType === 'string') { | |
valid = node[key] && node[key].type === fieldType; | |
} else if (Array.isArray(fieldType)) { | |
valid = node[key] instanceof List; | |
} | |
} | |
} | |
} else { | |
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type'); | |
} | |
if (!valid) { | |
warn(node, 'Bad value for `' + type + '.' + key + '`'); | |
} | |
} | |
for (var key in fields) { | |
if (hasOwnProperty.call(fields, key) && | |
hasOwnProperty.call(node, key) === false) { | |
warn(node, 'Field `' + type + '.' + key + '` is missed'); | |
} | |
} | |
}; | |
} | |
function processStructure(name, nodeType) { | |
var structure = nodeType.structure; | |
var fields = { | |
type: String, | |
loc: true | |
}; | |
var docs = { | |
type: '"' + name + '"' | |
}; | |
for (var key in structure) { | |
if (hasOwnProperty.call(structure, key) === false) { | |
continue; | |
} | |
var docsTypes = []; | |
var fieldTypes = fields[key] = Array.isArray(structure[key]) | |
? structure[key].slice() | |
: [structure[key]]; | |
for (var i = 0; i < fieldTypes.length; i++) { | |
var fieldType = fieldTypes[i]; | |
if (fieldType === String || fieldType === Boolean) { | |
docsTypes.push(fieldType.name); | |
} else if (fieldType === null) { | |
docsTypes.push('null'); | |
} else if (typeof fieldType === 'string') { | |
docsTypes.push('<' + fieldType + '>'); | |
} else if (Array.isArray(fieldType)) { | |
docsTypes.push('List'); // TODO: use type enum | |
} else { | |
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition'); | |
} | |
} | |
docs[key] = docsTypes.join(' | '); | |
} | |
return { | |
docs: docs, | |
check: createNodeStructureChecker(name, fields) | |
}; | |
} | |
module.exports = { | |
getStructureFromConfig: function(config) { | |
var structure = {}; | |
if (config.node) { | |
for (var name in config.node) { | |
if (hasOwnProperty.call(config.node, name)) { | |
var nodeType = config.node[name]; | |
if (nodeType.structure) { | |
structure[name] = processStructure(name, nodeType); | |
} else { | |
throw new Error('Missed `structure` field in `' + name + '` node type definition'); | |
} | |
} | |
} | |
} | |
return structure; | |
} | |
}; | |
},{"../utils/list":142}],57:[function(require,module,exports){ | |
function getTrace(node) { | |
function shouldPutToTrace(syntax) { | |
if (syntax === null) { | |
return false; | |
} | |
return ( | |
syntax.type === 'Type' || | |
syntax.type === 'Property' || | |
syntax.type === 'Keyword' | |
); | |
} | |
function hasMatch(matchNode) { | |
if (Array.isArray(matchNode.match)) { | |
// use for-loop for better perfomance | |
for (var i = 0; i < matchNode.match.length; i++) { | |
if (hasMatch(matchNode.match[i])) { | |
if (shouldPutToTrace(matchNode.syntax)) { | |
result.unshift(matchNode.syntax); | |
} | |
return true; | |
} | |
} | |
} else if (matchNode.node === node) { | |
result = shouldPutToTrace(matchNode.syntax) | |
? [matchNode.syntax] | |
: []; | |
return true; | |
} | |
return false; | |
} | |
var result = null; | |
if (this.matched !== null) { | |
hasMatch(this.matched); | |
} | |
return result; | |
} | |
function testNode(match, node, fn) { | |
var trace = getTrace.call(match, node); | |
if (trace === null) { | |
return false; | |
} | |
return trace.some(fn); | |
} | |
function isType(node, type) { | |
return testNode(this, node, function(matchNode) { | |
return matchNode.type === 'Type' && matchNode.name === type; | |
}); | |
} | |
function isProperty(node, property) { | |
return testNode(this, node, function(matchNode) { | |
return matchNode.type === 'Property' && matchNode.name === property; | |
}); | |
} | |
function isKeyword(node) { | |
return testNode(this, node, function(matchNode) { | |
return matchNode.type === 'Keyword'; | |
}); | |
} | |
module.exports = { | |
getTrace: getTrace, | |
isType: isType, | |
isProperty: isProperty, | |
isKeyword: isKeyword | |
}; | |
},{}],58:[function(require,module,exports){ | |
'use strict'; | |
var Tokenizer = require('../tokenizer'); | |
var List = require('../utils/list'); | |
var sequence = require('./sequence'); | |
var noop = function() {}; | |
function createParseContext(name) { | |
return function() { | |
return this[name](); | |
}; | |
} | |
function processConfig(config) { | |
var parserConfig = { | |
context: {}, | |
scope: {}, | |
atrule: {}, | |
pseudo: {} | |
}; | |
if (config.parseContext) { | |
for (var name in config.parseContext) { | |
switch (typeof config.parseContext[name]) { | |
case 'function': | |
parserConfig.context[name] = config.parseContext[name]; | |
break; | |
case 'string': | |
parserConfig.context[name] = createParseContext(config.parseContext[name]); | |
break; | |
} | |
} | |
} | |
if (config.scope) { | |
for (var name in config.scope) { | |
parserConfig.scope[name] = config.scope[name]; | |
} | |
} | |
if (config.atrule) { | |
for (var name in config.atrule) { | |
var atrule = config.atrule[name]; | |
if (atrule.parse) { | |
parserConfig.atrule[name] = atrule.parse; | |
} | |
} | |
} | |
if (config.pseudo) { | |
for (var name in config.pseudo) { | |
var pseudo = config.pseudo[name]; | |
if (pseudo.parse) { | |
parserConfig.pseudo[name] = pseudo.parse; | |
} | |
} | |
} | |
if (config.node) { | |
for (var name in config.node) { | |
parserConfig[name] = config.node[name].parse; | |
} | |
} | |
return parserConfig; | |
} | |
module.exports = function createParser(config) { | |
var parser = { | |
scanner: new Tokenizer(), | |
filename: '<unknown>', | |
needPositions: false, | |
onParseError: noop, | |
onParseErrorThrow: false, | |
parseAtrulePrelude: true, | |
parseRulePrelude: true, | |
parseValue: true, | |
parseCustomProperty: false, | |
readSequence: sequence, | |
createList: function() { | |
return new List(); | |
}, | |
createSingleNodeList: function(node) { | |
return new List().appendData(node); | |
}, | |
getFirstListNode: function(list) { | |
return list && list.first(); | |
}, | |
getLastListNode: function(list) { | |
return list.last(); | |
}, | |
parseWithFallback: function(consumer, fallback) { | |
var startToken = this.scanner.currentToken; | |
try { | |
return consumer.call(this); | |
} catch (e) { | |
if (this.onParseErrorThrow) { | |
throw e; | |
} | |
var fallbackNode = fallback.call(this, startToken); | |
this.onParseErrorThrow = true; | |
this.onParseError(e, fallbackNode); | |
this.onParseErrorThrow = false; | |
return fallbackNode; | |
} | |
}, | |
getLocation: function(start, end) { | |
if (this.needPositions) { | |
return this.scanner.getLocationRange( | |
start, | |
end, | |
this.filename | |
); | |
} | |
return null; | |
}, | |
getLocationFromList: function(list) { | |
if (this.needPositions) { | |
var head = this.getFirstListNode(list); | |
var tail = this.getLastListNode(list); | |
return this.scanner.getLocationRange( | |
head !== null ? head.loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart, | |
tail !== null ? tail.loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart, | |
this.filename | |
); | |
} | |
return null; | |
} | |
}; | |
config = processConfig(config || {}); | |
for (var key in config) { | |
parser[key] = config[key]; | |
} | |
return function(source, options) { | |
options = options || {}; | |
var context = options.context || 'default'; | |
var ast; | |
parser.scanner.setSource(source, options.offset, options.line, options.column); | |
parser.filename = options.filename || '<unknown>'; | |
parser.needPositions = Boolean(options.positions); | |
parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop; | |
parser.onParseErrorThrow = false; | |
parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true; | |
parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true; | |
parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true; | |
parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false; | |
if (!parser.context.hasOwnProperty(context)) { | |
throw new Error('Unknown context `' + context + '`'); | |
} | |
ast = parser.context[context].call(parser, options); | |
if (!parser.scanner.eof) { | |
parser.scanner.error(); | |
} | |
return ast; | |
}; | |
}; | |
},{"../tokenizer":138,"../utils/list":142,"./sequence":59}],59:[function(require,module,exports){ | |
var TYPE = require('../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
module.exports = function readSequence(recognizer) { | |
var children = this.createList(); | |
var child = null; | |
var context = { | |
recognizer: recognizer, | |
space: null, | |
ignoreWS: false, | |
ignoreWSAfter: false | |
}; | |
this.scanner.skipSC(); | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case COMMENT: | |
this.scanner.next(); | |
continue; | |
case WHITESPACE: | |
if (context.ignoreWS) { | |
this.scanner.next(); | |
} else { | |
context.space = this.WhiteSpace(); | |
} | |
continue; | |
} | |
child = recognizer.getNode.call(this, context); | |
if (child === undefined) { | |
break; | |
} | |
if (context.space !== null) { | |
children.push(context.space); | |
context.space = null; | |
} | |
children.push(child); | |
if (context.ignoreWSAfter) { | |
context.ignoreWSAfter = false; | |
context.ignoreWS = true; | |
} else { | |
context.ignoreWS = false; | |
} | |
} | |
return children; | |
}; | |
},{"../tokenizer":138}],60:[function(require,module,exports){ | |
module.exports = { | |
parse: { | |
prelude: null, | |
block: function() { | |
return this.Block(true); | |
} | |
} | |
}; | |
},{}],61:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var STRING = TYPE.String; | |
var IDENTIFIER = TYPE.Identifier; | |
var URL = TYPE.Url; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
module.exports = { | |
parse: { | |
prelude: function() { | |
var children = this.createList(); | |
this.scanner.skipSC(); | |
switch (this.scanner.tokenType) { | |
case STRING: | |
children.push(this.String()); | |
break; | |
case URL: | |
children.push(this.Url()); | |
break; | |
default: | |
this.scanner.error('String or url() is expected'); | |
} | |
if (this.scanner.lookupNonWSType(0) === IDENTIFIER || | |
this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS) { | |
children.push(this.WhiteSpace()); | |
children.push(this.MediaQueryList()); | |
} | |
return children; | |
}, | |
block: null | |
} | |
}; | |
},{"../../tokenizer":138}],62:[function(require,module,exports){ | |
module.exports = { | |
'font-face': require('./font-face'), | |
'import': require('./import'), | |
'media': require('./media'), | |
'page': require('./page'), | |
'supports': require('./supports') | |
}; | |
},{"./font-face":60,"./import":61,"./media":63,"./page":64,"./supports":65}],63:[function(require,module,exports){ | |
module.exports = { | |
parse: { | |
prelude: function() { | |
return this.createSingleNodeList( | |
this.MediaQueryList() | |
); | |
}, | |
block: function() { | |
return this.Block(false); | |
} | |
} | |
}; | |
},{}],64:[function(require,module,exports){ | |
module.exports = { | |
parse: { | |
prelude: function() { | |
return this.createSingleNodeList( | |
this.SelectorList() | |
); | |
}, | |
block: function() { | |
return this.Block(true); | |
} | |
} | |
}; | |
},{}],65:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
var IDENTIFIER = TYPE.Identifier; | |
var FUNCTION = TYPE.Function; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var COLON = TYPE.Colon; | |
function consumeRaw() { | |
return this.createSingleNodeList( | |
this.Raw(this.scanner.currentToken, 0, 0, false, false) | |
); | |
} | |
function parentheses() { | |
var index = 0; | |
this.scanner.skipSC(); | |
// TODO: make it simplier | |
if (this.scanner.tokenType === IDENTIFIER) { | |
index = 1; | |
} else if (this.scanner.tokenType === HYPHENMINUS && | |
this.scanner.lookupType(1) === IDENTIFIER) { | |
index = 2; | |
} | |
if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON) { | |
return this.createSingleNodeList( | |
this.Declaration() | |
); | |
} | |
return readSequence.call(this); | |
} | |
function readSequence() { | |
var children = this.createList(); | |
var space = null; | |
var child; | |
this.scanner.skipSC(); | |
scan: | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case WHITESPACE: | |
space = this.WhiteSpace(); | |
continue; | |
case COMMENT: | |
this.scanner.next(); | |
continue; | |
case FUNCTION: | |
child = this.Function(consumeRaw, this.scope.AtrulePrelude); | |
break; | |
case IDENTIFIER: | |
child = this.Identifier(); | |
break; | |
case LEFTPARENTHESIS: | |
child = this.Parentheses(parentheses, this.scope.AtrulePrelude); | |
break; | |
default: | |
break scan; | |
} | |
if (space !== null) { | |
children.push(space); | |
space = null; | |
} | |
children.push(child); | |
} | |
return children; | |
} | |
module.exports = { | |
parse: { | |
prelude: function() { | |
var children = readSequence.call(this); | |
if (this.getFirstListNode(children) === null) { | |
this.scanner.error('Condition is expected'); | |
} | |
return children; | |
}, | |
block: function() { | |
return this.Block(false); | |
} | |
} | |
}; | |
},{"../../tokenizer":138}],66:[function(require,module,exports){ | |
var data = require('../../../data'); | |
module.exports = { | |
generic: true, | |
types: data.types, | |
properties: data.properties, | |
node: require('../node') | |
}; | |
},{"../../../data":38,"../node":115}],67:[function(require,module,exports){ | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var shape = { | |
generic: true, | |
types: {}, | |
properties: {}, | |
parseContext: {}, | |
scope: {}, | |
atrule: ['parse'], | |
pseudo: ['parse'], | |
node: ['name', 'structure', 'parse', 'generate', 'walkContext'] | |
}; | |
function isObject(value) { | |
return value && value.constructor === Object; | |
} | |
function copy(value) { | |
if (isObject(value)) { | |
var res = {}; | |
for (var key in value) { | |
if (hasOwnProperty.call(value, key)) { | |
res[key] = value[key]; | |
} | |
} | |
return res; | |
} else { | |
return value; | |
} | |
} | |
function extend(dest, src) { | |
for (var key in src) { | |
if (hasOwnProperty.call(src, key)) { | |
if (isObject(dest[key])) { | |
extend(dest[key], copy(src[key])); | |
} else { | |
dest[key] = copy(src[key]); | |
} | |
} | |
} | |
} | |
function mix(dest, src, shape) { | |
for (var key in shape) { | |
if (hasOwnProperty.call(shape, key) === false) { | |
continue; | |
} | |
if (shape[key] === true) { | |
if (key in src) { | |
if (hasOwnProperty.call(src, key)) { | |
dest[key] = copy(src[key]); | |
} | |
} | |
} else if (shape[key]) { | |
if (isObject(shape[key])) { | |
var res = {}; | |
extend(res, dest[key]); | |
extend(res, src[key]); | |
dest[key] = res; | |
} else if (Array.isArray(shape[key])) { | |
var res = {}; | |
var innerShape = shape[key].reduce(function(s, k) { | |
s[k] = true; | |
return s; | |
}, {}); | |
for (var name in dest[key]) { | |
if (hasOwnProperty.call(dest[key], name)) { | |
res[name] = {}; | |
if (dest[key] && dest[key][name]) { | |
mix(res[name], dest[key][name], innerShape); | |
} | |
} | |
} | |
for (var name in src[key]) { | |
if (hasOwnProperty.call(src[key], name)) { | |
if (!res[name]) { | |
res[name] = {}; | |
} | |
if (src[key] && src[key][name]) { | |
mix(res[name], src[key][name], innerShape); | |
} | |
} | |
} | |
dest[key] = res; | |
} | |
} | |
} | |
return dest; | |
} | |
module.exports = function(dest, src) { | |
return mix(dest, src, shape); | |
}; | |
},{}],68:[function(require,module,exports){ | |
module.exports = { | |
parseContext: { | |
default: 'StyleSheet', | |
stylesheet: 'StyleSheet', | |
atrule: 'Atrule', | |
atrulePrelude: function(options) { | |
return this.AtrulePrelude(options.atrule ? String(options.atrule) : null); | |
}, | |
mediaQueryList: 'MediaQueryList', | |
mediaQuery: 'MediaQuery', | |
rule: 'Rule', | |
selectorList: 'SelectorList', | |
selector: 'Selector', | |
block: function() { | |
return this.Block(true); | |
}, | |
declarationList: 'DeclarationList', | |
declaration: 'Declaration', | |
value: 'Value' | |
}, | |
scope: require('../scope'), | |
atrule: require('../atrule'), | |
pseudo: require('../pseudo'), | |
node: require('../node') | |
}; | |
},{"../atrule":62,"../node":115,"../pseudo":121,"../scope":132}],69:[function(require,module,exports){ | |
module.exports = { | |
node: require('../node') | |
}; | |
},{"../node":115}],70:[function(require,module,exports){ | |
var List = require('../utils/list'); | |
var Tokenizer = require('../tokenizer'); | |
var Lexer = require('../lexer/Lexer'); | |
var grammar = require('../lexer/grammar'); | |
var createParser = require('../parser/create'); | |
var createGenerator = require('../generator/create'); | |
var createConvertor = require('../convertor/create'); | |
var createWalker = require('../walker/create'); | |
var clone = require('../utils/clone'); | |
var names = require('../utils/names'); | |
var mix = require('./config/mix'); | |
function assign(dest, src) { | |
for (var key in src) { | |
dest[key] = src[key]; | |
} | |
return dest; | |
} | |
function createSyntax(config) { | |
var parse = createParser(config); | |
var walk = createWalker(config); | |
var generate = createGenerator(config); | |
var convert = createConvertor(walk); | |
var syntax = { | |
List: List, | |
Tokenizer: Tokenizer, | |
Lexer: Lexer, | |
vendorPrefix: names.vendorPrefix, | |
keyword: names.keyword, | |
property: names.property, | |
isCustomProperty: names.isCustomProperty, | |
grammar: grammar, | |
lexer: null, | |
createLexer: function(config) { | |
return new Lexer(config, syntax, syntax.lexer.structure); | |
}, | |
parse: parse, | |
walk: walk, | |
generate: generate, | |
clone: clone, | |
fromPlainObject: convert.fromPlainObject, | |
toPlainObject: convert.toPlainObject, | |
createSyntax: function(config) { | |
return createSyntax(mix({}, config)); | |
}, | |
fork: function(extension) { | |
var base = mix({}, config); // copy of config | |
return createSyntax( | |
typeof extension === 'function' | |
? extension(base, assign) | |
: mix(base, extension) | |
); | |
} | |
}; | |
syntax.lexer = new Lexer({ | |
generic: true, | |
types: config.types, | |
properties: config.properties, | |
node: config.node | |
}, syntax); | |
return syntax; | |
}; | |
exports.create = function(config) { | |
return createSyntax(mix({}, config)); | |
}; | |
},{"../convertor/create":39,"../generator/create":40,"../lexer/Lexer":43,"../lexer/grammar":49,"../parser/create":58,"../tokenizer":138,"../utils/clone":140,"../utils/list":142,"../utils/names":143,"../walker/create":144,"./config/mix":67}],71:[function(require,module,exports){ | |
// https://drafts.csswg.org/css-images-4/#element-notation | |
// https://developer.mozilla.org/en-US/docs/Web/CSS/element | |
module.exports = function() { | |
this.scanner.skipSC(); | |
var children = this.createSingleNodeList( | |
this.IdSelector() | |
); | |
this.scanner.skipSC(); | |
return children; | |
}; | |
},{}],72:[function(require,module,exports){ | |
// legacy IE function | |
// expression '(' raw ')' | |
module.exports = function() { | |
return this.createSingleNodeList( | |
this.Raw(this.scanner.currentToken, 0, 0, false, false) | |
); | |
}; | |
},{}],73:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var COMMA = TYPE.Comma; | |
var SEMICOLON = TYPE.Semicolon; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var EXCLAMATIONMARK = TYPE.ExclamationMark; | |
// var '(' ident (',' <value>? )? ')' | |
module.exports = function() { | |
var children = this.createList(); | |
this.scanner.skipSC(); | |
var identStart = this.scanner.tokenStart; | |
this.scanner.eat(HYPHENMINUS); | |
if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS) { | |
this.scanner.error('HyphenMinus is expected'); | |
} | |
this.scanner.eat(IDENTIFIER); | |
children.push({ | |
type: 'Identifier', | |
loc: this.getLocation(identStart, this.scanner.tokenStart), | |
name: this.scanner.substrToCursor(identStart) | |
}); | |
this.scanner.skipSC(); | |
if (this.scanner.tokenType === COMMA) { | |
children.push(this.Operator()); | |
children.push(this.parseCustomProperty | |
? this.Value(null) | |
: this.Raw(this.scanner.currentToken, EXCLAMATIONMARK, SEMICOLON, false, false) | |
); | |
} | |
return children; | |
}; | |
},{"../../tokenizer":138}],74:[function(require,module,exports){ | |
function merge() { | |
var dest = {}; | |
for (var i = 0; i < arguments.length; i++) { | |
var src = arguments[i]; | |
for (var key in src) { | |
dest[key] = src[key]; | |
} | |
} | |
return dest; | |
} | |
module.exports = require('./create').create( | |
merge( | |
require('./config/lexer'), | |
require('./config/parser'), | |
require('./config/walker') | |
) | |
); | |
},{"./config/lexer":66,"./config/parser":68,"./config/walker":69,"./create":70}],75:[function(require,module,exports){ | |
var cmpChar = require('../../tokenizer').cmpChar; | |
var isNumber = require('../../tokenizer').isNumber; | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var PLUSSIGN = TYPE.PlusSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var N = 110; // 'n'.charCodeAt(0) | |
var DISALLOW_SIGN = true; | |
var ALLOW_SIGN = false; | |
function checkTokenIsInteger(scanner, disallowSign) { | |
var pos = scanner.tokenStart; | |
if (scanner.source.charCodeAt(pos) === PLUSSIGN || | |
scanner.source.charCodeAt(pos) === HYPHENMINUS) { | |
if (disallowSign) { | |
scanner.error(); | |
} | |
pos++; | |
} | |
for (; pos < scanner.tokenEnd; pos++) { | |
if (!isNumber(scanner.source.charCodeAt(pos))) { | |
scanner.error('Unexpected input', pos); | |
} | |
} | |
} | |
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb | |
module.exports = { | |
name: 'AnPlusB', | |
structure: { | |
a: [String, null], | |
b: [String, null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var end = start; | |
var prefix = ''; | |
var a = null; | |
var b = null; | |
if (this.scanner.tokenType === NUMBER || | |
this.scanner.tokenType === PLUSSIGN) { | |
checkTokenIsInteger(this.scanner, ALLOW_SIGN); | |
prefix = this.scanner.getTokenValue(); | |
this.scanner.next(); | |
end = this.scanner.tokenStart; | |
} | |
if (this.scanner.tokenType === IDENTIFIER) { | |
var bStart = this.scanner.tokenStart; | |
if (cmpChar(this.scanner.source, bStart, HYPHENMINUS)) { | |
if (prefix === '') { | |
prefix = '-'; | |
bStart++; | |
} else { | |
this.scanner.error('Unexpected hyphen minus'); | |
} | |
} | |
if (!cmpChar(this.scanner.source, bStart, N)) { | |
this.scanner.error(); | |
} | |
a = prefix === '' ? '1' : | |
prefix === '+' ? '+1' : | |
prefix === '-' ? '-1' : | |
prefix; | |
var len = this.scanner.tokenEnd - bStart; | |
if (len > 1) { | |
// ..n-.. | |
if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS) { | |
this.scanner.error('Unexpected input', bStart + 1); | |
} | |
if (len > 2) { | |
// ..n-{number}.. | |
this.scanner.tokenStart = bStart + 2; | |
} else { | |
// ..n- {number} | |
this.scanner.next(); | |
this.scanner.skipSC(); | |
} | |
checkTokenIsInteger(this.scanner, DISALLOW_SIGN); | |
b = '-' + this.scanner.getTokenValue(); | |
this.scanner.next(); | |
end = this.scanner.tokenStart; | |
} else { | |
prefix = ''; | |
this.scanner.next(); | |
end = this.scanner.tokenStart; | |
this.scanner.skipSC(); | |
if (this.scanner.tokenType === HYPHENMINUS || | |
this.scanner.tokenType === PLUSSIGN) { | |
prefix = this.scanner.getTokenValue(); | |
this.scanner.next(); | |
this.scanner.skipSC(); | |
} | |
if (this.scanner.tokenType === NUMBER) { | |
checkTokenIsInteger(this.scanner, prefix !== ''); | |
if (!isNumber(this.scanner.source.charCodeAt(this.scanner.tokenStart))) { | |
prefix = this.scanner.source.charAt(this.scanner.tokenStart); | |
this.scanner.tokenStart++; | |
} | |
if (prefix === '') { | |
// should be an operator before number | |
this.scanner.error(); | |
} else if (prefix === '+') { | |
// plus is using by default | |
prefix = ''; | |
} | |
b = prefix + this.scanner.getTokenValue(); | |
this.scanner.next(); | |
end = this.scanner.tokenStart; | |
} else { | |
if (prefix) { | |
this.scanner.eat(NUMBER); | |
} | |
} | |
} | |
} else { | |
if (prefix === '' || prefix === '+') { // no number | |
this.scanner.error( | |
'Number or identifier is expected', | |
this.scanner.tokenStart + ( | |
this.scanner.tokenType === PLUSSIGN || | |
this.scanner.tokenType === HYPHENMINUS | |
) | |
); | |
} | |
b = prefix; | |
} | |
return { | |
type: 'AnPlusB', | |
loc: this.getLocation(start, end), | |
a: a, | |
b: b | |
}; | |
}, | |
generate: function(node) { | |
var a = node.a !== null && node.a !== undefined; | |
var b = node.b !== null && node.b !== undefined; | |
if (a) { | |
this.chunk( | |
node.a === '+1' ? '+n' : | |
node.a === '1' ? 'n' : | |
node.a === '-1' ? '-n' : | |
node.a + 'n' | |
); | |
if (b) { | |
b = String(node.b); | |
if (b.charAt(0) === '-' || b.charAt(0) === '+') { | |
this.chunk(b.charAt(0)); | |
this.chunk(b.substr(1)); | |
} else { | |
this.chunk('+'); | |
this.chunk(b); | |
} | |
} | |
} else { | |
this.chunk(String(node.b)); | |
} | |
} | |
}; | |
},{"../../tokenizer":138}],76:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var ATKEYWORD = TYPE.AtKeyword; | |
var SEMICOLON = TYPE.Semicolon; | |
var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | |
var RIGHTCURLYBRACKET = TYPE.RightCurlyBracket; | |
function consumeRaw(startToken) { | |
return this.Raw(startToken, SEMICOLON, LEFTCURLYBRACKET, false, true); | |
} | |
function isDeclarationBlockAtrule() { | |
for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) { | |
if (type === RIGHTCURLYBRACKET) { | |
return true; | |
} | |
if (type === LEFTCURLYBRACKET || | |
type === ATKEYWORD) { | |
return false; | |
} | |
} | |
return false; | |
} | |
module.exports = { | |
name: 'Atrule', | |
structure: { | |
name: String, | |
prelude: ['AtrulePrelude', 'Raw', null], | |
block: ['Block', null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var name; | |
var nameLowerCase; | |
var prelude = null; | |
var block = null; | |
this.scanner.eat(ATKEYWORD); | |
name = this.scanner.substrToCursor(start + 1); | |
nameLowerCase = name.toLowerCase(); | |
this.scanner.skipSC(); | |
// parse prelude | |
if (this.scanner.eof === false && | |
this.scanner.tokenType !== LEFTCURLYBRACKET && | |
this.scanner.tokenType !== SEMICOLON) { | |
if (this.parseAtrulePrelude) { | |
prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name), consumeRaw); | |
// turn empty AtrulePrelude into null | |
if (prelude.type === 'AtrulePrelude' && prelude.children.head === null) { | |
prelude = null; | |
} | |
} else { | |
prelude = consumeRaw.call(this, this.scanner.currentToken); | |
} | |
this.scanner.skipSC(); | |
} | |
switch (this.scanner.tokenType) { | |
case SEMICOLON: | |
this.scanner.next(); | |
break; | |
case LEFTCURLYBRACKET: | |
if (this.atrule.hasOwnProperty(nameLowerCase) && | |
typeof this.atrule[nameLowerCase].block === 'function') { | |
block = this.atrule[nameLowerCase].block.call(this); | |
} else { | |
// TODO: should consume block content as Raw? | |
block = this.Block(isDeclarationBlockAtrule.call(this)); | |
} | |
break; | |
} | |
return { | |
type: 'Atrule', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
prelude: prelude, | |
block: block | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('@'); | |
this.chunk(node.name); | |
if (node.prelude !== null) { | |
this.chunk(' '); | |
this.node(node.prelude); | |
} | |
if (node.block) { | |
this.node(node.block); | |
} else { | |
this.chunk(';'); | |
} | |
}, | |
walkContext: 'atrule' | |
}; | |
},{"../../tokenizer":138}],77:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var SEMICOLON = TYPE.Semicolon; | |
var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | |
module.exports = { | |
name: 'AtrulePrelude', | |
structure: { | |
children: [[]] | |
}, | |
parse: function(name) { | |
var children = null; | |
if (name !== null) { | |
name = name.toLowerCase(); | |
} | |
this.scanner.skipSC(); | |
if (this.atrule.hasOwnProperty(name) && | |
typeof this.atrule[name].prelude === 'function') { | |
// custom consumer | |
children = this.atrule[name].prelude.call(this); | |
} else { | |
// default consumer | |
children = this.readSequence(this.scope.AtrulePrelude); | |
} | |
this.scanner.skipSC(); | |
if (this.scanner.eof !== true && | |
this.scanner.tokenType !== LEFTCURLYBRACKET && | |
this.scanner.tokenType !== SEMICOLON) { | |
this.scanner.error('Semicolon or block is expected'); | |
} | |
if (children === null) { | |
children = this.createList(); | |
} | |
return { | |
type: 'AtrulePrelude', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node); | |
}, | |
walkContext: 'atrulePrelude' | |
}; | |
},{"../../tokenizer":138}],78:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var STRING = TYPE.String; | |
var DOLLARSIGN = TYPE.DollarSign; | |
var ASTERISK = TYPE.Asterisk; | |
var COLON = TYPE.Colon; | |
var EQUALSSIGN = TYPE.EqualsSign; | |
var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket; | |
var RIGHTSQUAREBRACKET = TYPE.RightSquareBracket; | |
var CIRCUMFLEXACCENT = TYPE.CircumflexAccent; | |
var VERTICALLINE = TYPE.VerticalLine; | |
var TILDE = TYPE.Tilde; | |
function getAttributeName() { | |
if (this.scanner.eof) { | |
this.scanner.error('Unexpected end of input'); | |
} | |
var start = this.scanner.tokenStart; | |
var expectIdentifier = false; | |
var checkColon = true; | |
if (this.scanner.tokenType === ASTERISK) { | |
expectIdentifier = true; | |
checkColon = false; | |
this.scanner.next(); | |
} else if (this.scanner.tokenType !== VERTICALLINE) { | |
this.scanner.eat(IDENTIFIER); | |
} | |
if (this.scanner.tokenType === VERTICALLINE) { | |
if (this.scanner.lookupType(1) !== EQUALSSIGN) { | |
this.scanner.next(); | |
this.scanner.eat(IDENTIFIER); | |
} else if (expectIdentifier) { | |
this.scanner.error('Identifier is expected', this.scanner.tokenEnd); | |
} | |
} else if (expectIdentifier) { | |
this.scanner.error('Vertical line is expected'); | |
} | |
if (checkColon && this.scanner.tokenType === COLON) { | |
this.scanner.next(); | |
this.scanner.eat(IDENTIFIER); | |
} | |
return { | |
type: 'Identifier', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: this.scanner.substrToCursor(start) | |
}; | |
} | |
function getOperator() { | |
var start = this.scanner.tokenStart; | |
var tokenType = this.scanner.tokenType; | |
if (tokenType !== EQUALSSIGN && // = | |
tokenType !== TILDE && // ~= | |
tokenType !== CIRCUMFLEXACCENT && // ^= | |
tokenType !== DOLLARSIGN && // $= | |
tokenType !== ASTERISK && // *= | |
tokenType !== VERTICALLINE // |= | |
) { | |
this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected'); | |
} | |
if (tokenType === EQUALSSIGN) { | |
this.scanner.next(); | |
} else { | |
this.scanner.next(); | |
this.scanner.eat(EQUALSSIGN); | |
} | |
return this.scanner.substrToCursor(start); | |
} | |
// '[' S* attrib_name ']' | |
// '[' S* attrib_name S* attrib_matcher S* [ IDENT | STRING ] S* attrib_flags? S* ']' | |
module.exports = { | |
name: 'AttributeSelector', | |
structure: { | |
name: 'Identifier', | |
matcher: [String, null], | |
value: ['String', 'Identifier', null], | |
flags: [String, null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var name; | |
var matcher = null; | |
var value = null; | |
var flags = null; | |
this.scanner.eat(LEFTSQUAREBRACKET); | |
this.scanner.skipSC(); | |
name = getAttributeName.call(this); | |
this.scanner.skipSC(); | |
if (this.scanner.tokenType !== RIGHTSQUAREBRACKET) { | |
// avoid case `[name i]` | |
if (this.scanner.tokenType !== IDENTIFIER) { | |
matcher = getOperator.call(this); | |
this.scanner.skipSC(); | |
value = this.scanner.tokenType === STRING | |
? this.String() | |
: this.Identifier(); | |
this.scanner.skipSC(); | |
} | |
// attribute flags | |
if (this.scanner.tokenType === IDENTIFIER) { | |
flags = this.scanner.getTokenValue(); | |
this.scanner.next(); | |
this.scanner.skipSC(); | |
} | |
} | |
this.scanner.eat(RIGHTSQUAREBRACKET); | |
return { | |
type: 'AttributeSelector', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
matcher: matcher, | |
value: value, | |
flags: flags | |
}; | |
}, | |
generate: function(node) { | |
var flagsPrefix = ' '; | |
this.chunk('['); | |
this.node(node.name); | |
if (node.matcher !== null) { | |
this.chunk(node.matcher); | |
if (node.value !== null) { | |
this.node(node.value); | |
// space between string and flags is not required | |
if (node.value.type === 'String') { | |
flagsPrefix = ''; | |
} | |
} | |
} | |
if (node.flags !== null) { | |
this.chunk(flagsPrefix); | |
this.chunk(node.flags); | |
} | |
this.chunk(']'); | |
} | |
}; | |
},{"../../tokenizer":138}],79:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
var SEMICOLON = TYPE.Semicolon; | |
var ATKEYWORD = TYPE.AtKeyword; | |
var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | |
var RIGHTCURLYBRACKET = TYPE.RightCurlyBracket; | |
function consumeRaw(startToken) { | |
return this.Raw(startToken, 0, 0, false, true); | |
} | |
function consumeRule() { | |
return this.parseWithFallback(this.Rule, consumeRaw); | |
} | |
function consumeRawDeclaration(startToken) { | |
return this.Raw(startToken, 0, SEMICOLON, true, true); | |
} | |
function consumeDeclaration() { | |
if (this.scanner.tokenType === SEMICOLON) { | |
return consumeRawDeclaration.call(this, this.scanner.currentToken); | |
} | |
var node = this.parseWithFallback(this.Declaration, consumeRawDeclaration); | |
if (this.scanner.tokenType === SEMICOLON) { | |
this.scanner.next(); | |
} | |
return node; | |
} | |
module.exports = { | |
name: 'Block', | |
structure: { | |
children: [[ | |
'Atrule', | |
'Rule', | |
'Declaration' | |
]] | |
}, | |
parse: function(isDeclaration) { | |
var consumer = isDeclaration ? consumeDeclaration : consumeRule; | |
var start = this.scanner.tokenStart; | |
var children = this.createList(); | |
this.scanner.eat(LEFTCURLYBRACKET); | |
scan: | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case RIGHTCURLYBRACKET: | |
break scan; | |
case WHITESPACE: | |
case COMMENT: | |
this.scanner.next(); | |
break; | |
case ATKEYWORD: | |
children.push(this.parseWithFallback(this.Atrule, consumeRaw)); | |
break; | |
default: | |
children.push(consumer.call(this)); | |
} | |
} | |
if (!this.scanner.eof) { | |
this.scanner.eat(RIGHTCURLYBRACKET); | |
} | |
return { | |
type: 'Block', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('{'); | |
this.children(node, function(prev) { | |
if (prev.type === 'Declaration') { | |
this.chunk(';'); | |
} | |
}); | |
this.chunk('}'); | |
}, | |
walkContext: 'block' | |
}; | |
},{"../../tokenizer":138}],80:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket; | |
var RIGHTSQUAREBRACKET = TYPE.RightSquareBracket; | |
module.exports = { | |
name: 'Brackets', | |
structure: { | |
children: [[]] | |
}, | |
parse: function(readSequence, recognizer) { | |
var start = this.scanner.tokenStart; | |
var children = null; | |
this.scanner.eat(LEFTSQUAREBRACKET); | |
children = readSequence.call(this, recognizer); | |
if (!this.scanner.eof) { | |
this.scanner.eat(RIGHTSQUAREBRACKET); | |
} | |
return { | |
type: 'Brackets', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('['); | |
this.children(node); | |
this.chunk(']'); | |
} | |
}; | |
},{"../../tokenizer":138}],81:[function(require,module,exports){ | |
var CDC = require('../../tokenizer').TYPE.CDC; | |
module.exports = { | |
name: 'CDC', | |
structure: [], | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
this.scanner.eat(CDC); // --> | |
return { | |
type: 'CDC', | |
loc: this.getLocation(start, this.scanner.tokenStart) | |
}; | |
}, | |
generate: function() { | |
this.chunk('-->'); | |
} | |
}; | |
},{"../../tokenizer":138}],82:[function(require,module,exports){ | |
var CDO = require('../../tokenizer').TYPE.CDO; | |
module.exports = { | |
name: 'CDO', | |
structure: [], | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
this.scanner.eat(CDO); // <!-- | |
return { | |
type: 'CDO', | |
loc: this.getLocation(start, this.scanner.tokenStart) | |
}; | |
}, | |
generate: function() { | |
this.chunk('<!--'); | |
} | |
}; | |
},{"../../tokenizer":138}],83:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var FULLSTOP = TYPE.FullStop; | |
// '.' ident | |
module.exports = { | |
name: 'ClassSelector', | |
structure: { | |
name: String | |
}, | |
parse: function() { | |
this.scanner.eat(FULLSTOP); | |
return { | |
type: 'ClassSelector', | |
loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd), | |
name: this.scanner.consume(IDENTIFIER) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('.'); | |
this.chunk(node.name); | |
} | |
}; | |
},{"../../tokenizer":138}],84:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var PLUSSIGN = TYPE.PlusSign; | |
var SOLIDUS = TYPE.Solidus; | |
var GREATERTHANSIGN = TYPE.GreaterThanSign; | |
var TILDE = TYPE.Tilde; | |
// + | > | ~ | /deep/ | |
module.exports = { | |
name: 'Combinator', | |
structure: { | |
name: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
switch (this.scanner.tokenType) { | |
case GREATERTHANSIGN: | |
case PLUSSIGN: | |
case TILDE: | |
this.scanner.next(); | |
break; | |
case SOLIDUS: | |
this.scanner.next(); | |
this.scanner.expectIdentifier('deep'); | |
this.scanner.eat(SOLIDUS); | |
break; | |
default: | |
this.scanner.error('Combinator is expected'); | |
} | |
return { | |
type: 'Combinator', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: this.scanner.substrToCursor(start) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.name); | |
} | |
}; | |
},{"../../tokenizer":138}],85:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var ASTERISK = TYPE.Asterisk; | |
var SOLIDUS = TYPE.Solidus; | |
// '/*' .* '*/' | |
module.exports = { | |
name: 'Comment', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var end = this.scanner.tokenEnd; | |
if ((end - start + 2) >= 2 && | |
this.scanner.source.charCodeAt(end - 2) === ASTERISK && | |
this.scanner.source.charCodeAt(end - 1) === SOLIDUS) { | |
end -= 2; | |
} | |
this.scanner.next(); | |
return { | |
type: 'Comment', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: this.scanner.source.substring(start + 2, end) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('/*'); | |
this.chunk(node.value); | |
this.chunk('*/'); | |
} | |
}; | |
},{"../../tokenizer":138}],86:[function(require,module,exports){ | |
var isCustomProperty = require('../../utils/names').isCustomProperty; | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var COLON = TYPE.Colon; | |
var EXCLAMATIONMARK = TYPE.ExclamationMark; | |
var SOLIDUS = TYPE.Solidus; | |
var ASTERISK = TYPE.Asterisk; | |
var DOLLARSIGN = TYPE.DollarSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var SEMICOLON = TYPE.Semicolon; | |
var PLUSSIGN = TYPE.PlusSign; | |
var NUMBERSIGN = TYPE.NumberSign; | |
function consumeValueRaw(startToken) { | |
return this.Raw(startToken, EXCLAMATIONMARK, SEMICOLON, false, true); | |
} | |
function consumeCustomPropertyRaw(startToken) { | |
return this.Raw(startToken, EXCLAMATIONMARK, SEMICOLON, false, false); | |
} | |
function consumeValue() { | |
var startValueToken = this.scanner.currentToken; | |
var value = this.Value(); | |
if (value.type !== 'Raw' && | |
this.scanner.eof === false && | |
this.scanner.tokenType !== SEMICOLON && | |
this.scanner.tokenType !== EXCLAMATIONMARK && | |
this.scanner.isBalanceEdge(startValueToken) === false) { | |
this.scanner.error(); | |
} | |
return value; | |
} | |
module.exports = { | |
name: 'Declaration', | |
structure: { | |
important: [Boolean, String], | |
property: String, | |
value: ['Value', 'Raw'] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var startToken = this.scanner.currentToken; | |
var property = readProperty.call(this); | |
var customProperty = isCustomProperty(property); | |
var parseValue = customProperty ? this.parseCustomProperty : this.parseValue; | |
var consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw; | |
var important = false; | |
var value; | |
this.scanner.skipSC(); | |
this.scanner.eat(COLON); | |
if (!customProperty) { | |
this.scanner.skipSC(); | |
} | |
if (parseValue) { | |
value = this.parseWithFallback(consumeValue, consumeRaw); | |
} else { | |
value = consumeRaw.call(this, this.scanner.currentToken); | |
} | |
if (this.scanner.tokenType === EXCLAMATIONMARK) { | |
important = getImportant(this.scanner); | |
this.scanner.skipSC(); | |
} | |
// Do not include semicolon to range per spec | |
// https://drafts.csswg.org/css-syntax/#declaration-diagram | |
if (this.scanner.eof === false && | |
this.scanner.tokenType !== SEMICOLON && | |
this.scanner.isBalanceEdge(startToken) === false) { | |
this.scanner.error(); | |
} | |
return { | |
type: 'Declaration', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
important: important, | |
property: property, | |
value: value | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.property); | |
this.chunk(':'); | |
this.node(node.value); | |
if (node.important) { | |
this.chunk(node.important === true ? '!important' : '!' + node.important); | |
} | |
}, | |
walkContext: 'declaration' | |
}; | |
function readProperty() { | |
var start = this.scanner.tokenStart; | |
var prefix = 0; | |
// hacks | |
switch (this.scanner.tokenType) { | |
case ASTERISK: | |
case DOLLARSIGN: | |
case PLUSSIGN: | |
case NUMBERSIGN: | |
prefix = 1; | |
break; | |
// TODO: not sure we should support this hack | |
case SOLIDUS: | |
prefix = this.scanner.lookupType(1) === SOLIDUS ? 2 : 1; | |
break; | |
} | |
if (this.scanner.lookupType(prefix) === HYPHENMINUS) { | |
prefix++; | |
} | |
if (prefix) { | |
this.scanner.skip(prefix); | |
} | |
this.scanner.eat(IDENTIFIER); | |
return this.scanner.substrToCursor(start); | |
} | |
// ! ws* important | |
function getImportant(scanner) { | |
scanner.eat(EXCLAMATIONMARK); | |
scanner.skipSC(); | |
var important = scanner.consume(IDENTIFIER); | |
// store original value in case it differ from `important` | |
// for better original source restoring and hacks like `!ie` support | |
return important === 'important' ? true : important; | |
} | |
},{"../../tokenizer":138,"../../utils/names":143}],87:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
var SEMICOLON = TYPE.Semicolon; | |
function consumeRaw(startToken) { | |
return this.Raw(startToken, 0, SEMICOLON, true, true); | |
} | |
module.exports = { | |
name: 'DeclarationList', | |
structure: { | |
children: [[ | |
'Declaration' | |
]] | |
}, | |
parse: function() { | |
var children = this.createList(); | |
scan: | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case WHITESPACE: | |
case COMMENT: | |
case SEMICOLON: | |
this.scanner.next(); | |
break; | |
default: | |
children.push(this.parseWithFallback(this.Declaration, consumeRaw)); | |
} | |
} | |
return { | |
type: 'DeclarationList', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node, function(prev) { | |
if (prev.type === 'Declaration') { | |
this.chunk(';'); | |
} | |
}); | |
} | |
}; | |
},{"../../tokenizer":138}],88:[function(require,module,exports){ | |
var NUMBER = require('../../tokenizer').TYPE.Number; | |
// special reader for units to avoid adjoined IE hacks (i.e. '1px\9') | |
function readUnit(scanner) { | |
var unit = scanner.getTokenValue(); | |
var backSlashPos = unit.indexOf('\\'); | |
if (backSlashPos > 0) { | |
// patch token offset | |
scanner.tokenStart += backSlashPos; | |
// return part before backslash | |
return unit.substring(0, backSlashPos); | |
} | |
// no backslash in unit name | |
scanner.next(); | |
return unit; | |
} | |
// number ident | |
module.exports = { | |
name: 'Dimension', | |
structure: { | |
value: String, | |
unit: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var value = this.scanner.consume(NUMBER); | |
var unit = readUnit(this.scanner); | |
return { | |
type: 'Dimension', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: value, | |
unit: unit | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
this.chunk(node.unit); | |
} | |
}; | |
},{"../../tokenizer":138}],89:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
// <function-token> <sequence> ')' | |
module.exports = { | |
name: 'Function', | |
structure: { | |
name: String, | |
children: [[]] | |
}, | |
parse: function(readSequence, recognizer) { | |
var start = this.scanner.tokenStart; | |
var name = this.scanner.consumeFunctionName(); | |
var nameLowerCase = name.toLowerCase(); | |
var children; | |
children = recognizer.hasOwnProperty(nameLowerCase) | |
? recognizer[nameLowerCase].call(this, recognizer) | |
: readSequence.call(this, recognizer); | |
if (!this.scanner.eof) { | |
this.scanner.eat(RIGHTPARENTHESIS); | |
} | |
return { | |
type: 'Function', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.name); | |
this.chunk('('); | |
this.children(node); | |
this.chunk(')'); | |
}, | |
walkContext: 'function' | |
}; | |
},{"../../tokenizer":138}],90:[function(require,module,exports){ | |
var isHex = require('../../tokenizer').isHex; | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var NUMBERSIGN = TYPE.NumberSign; | |
function consumeHexSequence(scanner, required) { | |
if (!isHex(scanner.source.charCodeAt(scanner.tokenStart))) { | |
if (required) { | |
scanner.error('Unexpected input', scanner.tokenStart); | |
} else { | |
return; | |
} | |
} | |
for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) { | |
var code = scanner.source.charCodeAt(pos); | |
// break on non-hex char | |
if (!isHex(code)) { | |
// break token, exclude symbol | |
scanner.tokenStart = pos; | |
return; | |
} | |
} | |
// token is full hex sequence, go to next token | |
scanner.next(); | |
} | |
// # ident | |
module.exports = { | |
name: 'HexColor', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
this.scanner.eat(NUMBERSIGN); | |
scan: | |
switch (this.scanner.tokenType) { | |
case NUMBER: | |
consumeHexSequence(this.scanner, true); | |
// if token is identifier then number consists of hex only, | |
// try to add identifier to result | |
if (this.scanner.tokenType === IDENTIFIER) { | |
consumeHexSequence(this.scanner, false); | |
} | |
break; | |
case IDENTIFIER: | |
consumeHexSequence(this.scanner, true); | |
break; | |
default: | |
this.scanner.error('Number or identifier is expected'); | |
} | |
return { | |
type: 'HexColor', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: this.scanner.substrToCursor(start + 1) // skip # | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('#'); | |
this.chunk(node.value); | |
} | |
}; | |
},{"../../tokenizer":138}],91:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBERSIGN = TYPE.NumberSign; | |
// '#' ident | |
module.exports = { | |
name: 'IdSelector', | |
structure: { | |
name: String | |
}, | |
parse: function() { | |
this.scanner.eat(NUMBERSIGN); | |
return { | |
type: 'IdSelector', | |
loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd), | |
name: this.scanner.consume(IDENTIFIER) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('#'); | |
this.chunk(node.name); | |
} | |
}; | |
},{"../../tokenizer":138}],92:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
module.exports = { | |
name: 'Identifier', | |
structure: { | |
name: String | |
}, | |
parse: function() { | |
return { | |
type: 'Identifier', | |
loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd), | |
name: this.scanner.consume(IDENTIFIER) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.name); | |
} | |
}; | |
},{"../../tokenizer":138}],93:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
var COLON = TYPE.Colon; | |
var SOLIDUS = TYPE.Solidus; | |
module.exports = { | |
name: 'MediaFeature', | |
structure: { | |
name: String, | |
value: ['Identifier', 'Number', 'Dimension', 'Ratio', null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var name; | |
var value = null; | |
this.scanner.eat(LEFTPARENTHESIS); | |
this.scanner.skipSC(); | |
name = this.scanner.consume(IDENTIFIER); | |
this.scanner.skipSC(); | |
if (this.scanner.tokenType !== RIGHTPARENTHESIS) { | |
this.scanner.eat(COLON); | |
this.scanner.skipSC(); | |
switch (this.scanner.tokenType) { | |
case NUMBER: | |
if (this.scanner.lookupType(1) === IDENTIFIER) { | |
value = this.Dimension(); | |
} else if (this.scanner.lookupNonWSType(1) === SOLIDUS) { | |
value = this.Ratio(); | |
} else { | |
value = this.Number(); | |
} | |
break; | |
case IDENTIFIER: | |
value = this.Identifier(); | |
break; | |
default: | |
this.scanner.error('Number, dimension, ratio or identifier is expected'); | |
} | |
this.scanner.skipSC(); | |
} | |
this.scanner.eat(RIGHTPARENTHESIS); | |
return { | |
type: 'MediaFeature', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
value: value | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('('); | |
this.chunk(node.name); | |
if (node.value !== null) { | |
this.chunk(':'); | |
this.node(node.value); | |
} | |
this.chunk(')'); | |
} | |
}; | |
},{"../../tokenizer":138}],94:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
var IDENTIFIER = TYPE.Identifier; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
module.exports = { | |
name: 'MediaQuery', | |
structure: { | |
children: [[ | |
'Identifier', | |
'MediaFeature', | |
'WhiteSpace' | |
]] | |
}, | |
parse: function() { | |
this.scanner.skipSC(); | |
var children = this.createList(); | |
var child = null; | |
var space = null; | |
scan: | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case COMMENT: | |
this.scanner.next(); | |
continue; | |
case WHITESPACE: | |
space = this.WhiteSpace(); | |
continue; | |
case IDENTIFIER: | |
child = this.Identifier(); | |
break; | |
case LEFTPARENTHESIS: | |
child = this.MediaFeature(); | |
break; | |
default: | |
break scan; | |
} | |
if (space !== null) { | |
children.push(space); | |
space = null; | |
} | |
children.push(child); | |
} | |
if (child === null) { | |
this.scanner.error('Identifier or parenthesis is expected'); | |
} | |
return { | |
type: 'MediaQuery', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node); | |
} | |
}; | |
},{"../../tokenizer":138}],95:[function(require,module,exports){ | |
var COMMA = require('../../tokenizer').TYPE.Comma; | |
module.exports = { | |
name: 'MediaQueryList', | |
structure: { | |
children: [[ | |
'MediaQuery' | |
]] | |
}, | |
parse: function(relative) { | |
var children = this.createList(); | |
this.scanner.skipSC(); | |
while (!this.scanner.eof) { | |
children.push(this.MediaQuery(relative)); | |
if (this.scanner.tokenType !== COMMA) { | |
break; | |
} | |
this.scanner.next(); | |
} | |
return { | |
type: 'MediaQueryList', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node, function() { | |
this.chunk(','); | |
}); | |
} | |
}; | |
},{"../../tokenizer":138}],96:[function(require,module,exports){ | |
// https://drafts.csswg.org/css-syntax-3/#the-anb-type | |
module.exports = { | |
name: 'Nth', | |
structure: { | |
nth: ['AnPlusB', 'Identifier'], | |
selector: ['SelectorList', null] | |
}, | |
parse: function(allowOfClause) { | |
this.scanner.skipSC(); | |
var start = this.scanner.tokenStart; | |
var end = start; | |
var selector = null; | |
var query; | |
if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) { | |
query = this.Identifier(); | |
} else { | |
query = this.AnPlusB(); | |
} | |
this.scanner.skipSC(); | |
if (allowOfClause && this.scanner.lookupValue(0, 'of')) { | |
this.scanner.next(); | |
selector = this.SelectorList(); | |
if (this.needPositions) { | |
end = this.getLastListNode(selector.children).loc.end.offset; | |
} | |
} else { | |
if (this.needPositions) { | |
end = query.loc.end.offset; | |
} | |
} | |
return { | |
type: 'Nth', | |
loc: this.getLocation(start, end), | |
nth: query, | |
selector: selector | |
}; | |
}, | |
generate: function(node) { | |
this.node(node.nth); | |
if (node.selector !== null) { | |
this.chunk(' of '); | |
this.node(node.selector); | |
} | |
} | |
}; | |
},{}],97:[function(require,module,exports){ | |
var NUMBER = require('../../tokenizer').TYPE.Number; | |
module.exports = { | |
name: 'Number', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
return { | |
type: 'Number', | |
loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd), | |
value: this.scanner.consume(NUMBER) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{"../../tokenizer":138}],98:[function(require,module,exports){ | |
// '/' | '*' | ',' | ':' | '+' | '-' | |
module.exports = { | |
name: 'Operator', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
this.scanner.next(); | |
return { | |
type: 'Operator', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: this.scanner.substrToCursor(start) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{}],99:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
module.exports = { | |
name: 'Parentheses', | |
structure: { | |
children: [[]] | |
}, | |
parse: function(readSequence, recognizer) { | |
var start = this.scanner.tokenStart; | |
var children = null; | |
this.scanner.eat(LEFTPARENTHESIS); | |
children = readSequence.call(this, recognizer); | |
if (!this.scanner.eof) { | |
this.scanner.eat(RIGHTPARENTHESIS); | |
} | |
return { | |
type: 'Parentheses', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('('); | |
this.children(node); | |
this.chunk(')'); | |
} | |
}; | |
},{"../../tokenizer":138}],100:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var NUMBER = TYPE.Number; | |
var PERCENTSIGN = TYPE.PercentSign; | |
module.exports = { | |
name: 'Percentage', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var number = this.scanner.consume(NUMBER); | |
this.scanner.eat(PERCENTSIGN); | |
return { | |
type: 'Percentage', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: number | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
this.chunk('%'); | |
} | |
}; | |
},{"../../tokenizer":138}],101:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var FUNCTION = TYPE.Function; | |
var COLON = TYPE.Colon; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
// : ident [ '(' .. ')' ]? | |
module.exports = { | |
name: 'PseudoClassSelector', | |
structure: { | |
name: String, | |
children: [['Raw'], null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var children = null; | |
var name; | |
var nameLowerCase; | |
this.scanner.eat(COLON); | |
if (this.scanner.tokenType === FUNCTION) { | |
name = this.scanner.consumeFunctionName(); | |
nameLowerCase = name.toLowerCase(); | |
if (this.pseudo.hasOwnProperty(nameLowerCase)) { | |
this.scanner.skipSC(); | |
children = this.pseudo[nameLowerCase].call(this); | |
this.scanner.skipSC(); | |
} else { | |
children = this.createList(); | |
children.push( | |
this.Raw(this.scanner.currentToken, 0, 0, false, false) | |
); | |
} | |
this.scanner.eat(RIGHTPARENTHESIS); | |
} else { | |
name = this.scanner.consume(IDENTIFIER); | |
} | |
return { | |
type: 'PseudoClassSelector', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(':'); | |
this.chunk(node.name); | |
if (node.children !== null) { | |
this.chunk('('); | |
this.children(node); | |
this.chunk(')'); | |
} | |
}, | |
walkContext: 'function' | |
}; | |
},{"../../tokenizer":138}],102:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var FUNCTION = TYPE.Function; | |
var COLON = TYPE.Colon; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
// :: ident [ '(' .. ')' ]? | |
module.exports = { | |
name: 'PseudoElementSelector', | |
structure: { | |
name: String, | |
children: [['Raw'], null] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var children = null; | |
var name; | |
var nameLowerCase; | |
this.scanner.eat(COLON); | |
this.scanner.eat(COLON); | |
if (this.scanner.tokenType === FUNCTION) { | |
name = this.scanner.consumeFunctionName(); | |
nameLowerCase = name.toLowerCase(); | |
if (this.pseudo.hasOwnProperty(nameLowerCase)) { | |
this.scanner.skipSC(); | |
children = this.pseudo[nameLowerCase].call(this); | |
this.scanner.skipSC(); | |
} else { | |
children = this.createList(); | |
children.push( | |
this.Raw(this.scanner.currentToken, 0, 0, false, false) | |
); | |
} | |
this.scanner.eat(RIGHTPARENTHESIS); | |
} else { | |
name = this.scanner.consume(IDENTIFIER); | |
} | |
return { | |
type: 'PseudoElementSelector', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: name, | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('::'); | |
this.chunk(node.name); | |
if (node.children !== null) { | |
this.chunk('('); | |
this.children(node); | |
this.chunk(')'); | |
} | |
}, | |
walkContext: 'function' | |
}; | |
},{"../../tokenizer":138}],103:[function(require,module,exports){ | |
var isNumber = require('../../tokenizer').isNumber; | |
var TYPE = require('../../tokenizer').TYPE; | |
var NUMBER = TYPE.Number; | |
var SOLIDUS = TYPE.Solidus; | |
var FULLSTOP = TYPE.FullStop; | |
// Terms of <ratio> should to be a positive number (not zero or negative) | |
// (see https://drafts.csswg.org/mediaqueries-3/#values) | |
// However, -o-min-device-pixel-ratio takes fractional values as a ratio's term | |
// and this is using by various sites. Therefore we relax checking on parse | |
// to test a term is unsigned number without exponent part. | |
// Additional checks may to be applied on lexer validation. | |
function consumeNumber(scanner) { | |
var value = scanner.consumeNonWS(NUMBER); | |
for (var i = 0; i < value.length; i++) { | |
var code = value.charCodeAt(i); | |
if (!isNumber(code) && code !== FULLSTOP) { | |
scanner.error('Unsigned number is expected', scanner.tokenStart - value.length + i); | |
} | |
} | |
if (Number(value) === 0) { | |
scanner.error('Zero number is not allowed', scanner.tokenStart - value.length); | |
} | |
return value; | |
} | |
// <positive-integer> S* '/' S* <positive-integer> | |
module.exports = { | |
name: 'Ratio', | |
structure: { | |
left: String, | |
right: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var left = consumeNumber(this.scanner); | |
var right; | |
this.scanner.eatNonWS(SOLIDUS); | |
right = consumeNumber(this.scanner); | |
return { | |
type: 'Ratio', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
left: left, | |
right: right | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.left); | |
this.chunk('/'); | |
this.chunk(node.right); | |
} | |
}; | |
},{"../../tokenizer":138}],104:[function(require,module,exports){ | |
module.exports = { | |
name: 'Raw', | |
structure: { | |
value: String | |
}, | |
parse: function(startToken, endTokenType1, endTokenType2, includeTokenType2, excludeWhiteSpace) { | |
var startOffset = this.scanner.getTokenStart(startToken); | |
var endOffset; | |
this.scanner.skip( | |
this.scanner.getRawLength( | |
startToken, | |
endTokenType1, | |
endTokenType2, | |
includeTokenType2 | |
) | |
); | |
if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) { | |
endOffset = this.scanner.getOffsetExcludeWS(); | |
} else { | |
endOffset = this.scanner.tokenStart; | |
} | |
return { | |
type: 'Raw', | |
loc: this.getLocation(startOffset, endOffset), | |
value: this.scanner.source.substring(startOffset, endOffset) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{}],105:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | |
function consumeRaw(startToken) { | |
return this.Raw(startToken, LEFTCURLYBRACKET, 0, false, true); | |
} | |
function consumePrelude() { | |
var prelude = this.SelectorList(); | |
if (prelude.type !== 'Raw' && | |
this.scanner.eof === false && | |
this.scanner.tokenType !== LEFTCURLYBRACKET) { | |
this.scanner.error(); | |
} | |
return prelude; | |
} | |
module.exports = { | |
name: 'Rule', | |
structure: { | |
prelude: ['SelectorList', 'Raw'], | |
block: ['Block'] | |
}, | |
parse: function() { | |
var startToken = this.scanner.currentToken; | |
var startOffset = this.scanner.tokenStart; | |
var prelude; | |
var block; | |
if (this.parseRulePrelude) { | |
prelude = this.parseWithFallback(consumePrelude, consumeRaw); | |
} else { | |
prelude = consumeRaw.call(this, startToken); | |
} | |
block = this.Block(true); | |
return { | |
type: 'Rule', | |
loc: this.getLocation(startOffset, this.scanner.tokenStart), | |
prelude: prelude, | |
block: block | |
}; | |
}, | |
generate: function(node) { | |
this.node(node.prelude); | |
this.node(node.block); | |
}, | |
walkContext: 'rule' | |
}; | |
},{"../../tokenizer":138}],106:[function(require,module,exports){ | |
module.exports = { | |
name: 'Selector', | |
structure: { | |
children: [[ | |
'TypeSelector', | |
'IdSelector', | |
'ClassSelector', | |
'AttributeSelector', | |
'PseudoClassSelector', | |
'PseudoElementSelector', | |
'Combinator', | |
'WhiteSpace' | |
]] | |
}, | |
parse: function() { | |
var children = this.readSequence(this.scope.Selector); | |
// nothing were consumed | |
if (this.getFirstListNode(children) === null) { | |
this.scanner.error('Selector is expected'); | |
} | |
return { | |
type: 'Selector', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node); | |
} | |
}; | |
},{}],107:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var COMMA = TYPE.Comma; | |
module.exports = { | |
name: 'SelectorList', | |
structure: { | |
children: [[ | |
'Selector', | |
'Raw' | |
]] | |
}, | |
parse: function() { | |
var children = this.createList(); | |
while (!this.scanner.eof) { | |
children.push(this.Selector()); | |
if (this.scanner.tokenType === COMMA) { | |
this.scanner.next(); | |
continue; | |
} | |
break; | |
} | |
return { | |
type: 'SelectorList', | |
loc: this.getLocationFromList(children), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node, function() { | |
this.chunk(','); | |
}); | |
}, | |
walkContext: 'selector' | |
}; | |
},{"../../tokenizer":138}],108:[function(require,module,exports){ | |
var STRING = require('../../tokenizer').TYPE.String; | |
module.exports = { | |
name: 'String', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
return { | |
type: 'String', | |
loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd), | |
value: this.scanner.consume(STRING) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{"../../tokenizer":138}],109:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var COMMENT = TYPE.Comment; | |
var EXCLAMATIONMARK = TYPE.ExclamationMark; | |
var ATKEYWORD = TYPE.AtKeyword; | |
var CDO = TYPE.CDO; | |
var CDC = TYPE.CDC; | |
function consumeRaw(startToken) { | |
return this.Raw(startToken, 0, 0, false, false); | |
} | |
module.exports = { | |
name: 'StyleSheet', | |
structure: { | |
children: [[ | |
'Comment', | |
'CDO', | |
'CDC', | |
'Atrule', | |
'Rule', | |
'Raw' | |
]] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var children = this.createList(); | |
var child; | |
scan: | |
while (!this.scanner.eof) { | |
switch (this.scanner.tokenType) { | |
case WHITESPACE: | |
this.scanner.next(); | |
continue; | |
case COMMENT: | |
// ignore comments except exclamation comments (i.e. /*! .. */) on top level | |
if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK) { | |
this.scanner.next(); | |
continue; | |
} | |
child = this.Comment(); | |
break; | |
case CDO: // <!-- | |
child = this.CDO(); | |
break; | |
case CDC: // --> | |
child = this.CDC(); | |
break; | |
// CSS Syntax Module Level 3 | |
// §2.2 Error handling | |
// At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule. | |
case ATKEYWORD: | |
child = this.parseWithFallback(this.Atrule, consumeRaw); | |
break; | |
// Anything else starts a qualified rule ... | |
default: | |
child = this.parseWithFallback(this.Rule, consumeRaw); | |
} | |
children.push(child); | |
} | |
return { | |
type: 'StyleSheet', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node); | |
}, | |
walkContext: 'stylesheet' | |
}; | |
},{"../../tokenizer":138}],110:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var ASTERISK = TYPE.Asterisk; | |
var VERTICALLINE = TYPE.VerticalLine; | |
function eatIdentifierOrAsterisk() { | |
if (this.scanner.tokenType !== IDENTIFIER && | |
this.scanner.tokenType !== ASTERISK) { | |
this.scanner.error('Identifier or asterisk is expected'); | |
} | |
this.scanner.next(); | |
} | |
// ident | |
// ident|ident | |
// ident|* | |
// * | |
// *|ident | |
// *|* | |
// |ident | |
// |* | |
module.exports = { | |
name: 'TypeSelector', | |
structure: { | |
name: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
if (this.scanner.tokenType === VERTICALLINE) { | |
this.scanner.next(); | |
eatIdentifierOrAsterisk.call(this); | |
} else { | |
eatIdentifierOrAsterisk.call(this); | |
if (this.scanner.tokenType === VERTICALLINE) { | |
this.scanner.next(); | |
eatIdentifierOrAsterisk.call(this); | |
} | |
} | |
return { | |
type: 'TypeSelector', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
name: this.scanner.substrToCursor(start) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.name); | |
} | |
}; | |
},{"../../tokenizer":138}],111:[function(require,module,exports){ | |
var isHex = require('../../tokenizer').isHex; | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var PLUSSIGN = TYPE.PlusSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var FULLSTOP = TYPE.FullStop; | |
var QUESTIONMARK = TYPE.QuestionMark; | |
function scanUnicodeNumber(scanner) { | |
for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) { | |
var code = scanner.source.charCodeAt(pos); | |
// break on fullstop or hyperminus/plussign after exponent | |
if (code === FULLSTOP || code === PLUSSIGN) { | |
// break token, exclude symbol | |
scanner.tokenStart = pos; | |
return false; | |
} | |
} | |
return true; | |
} | |
// https://drafts.csswg.org/css-syntax-3/#urange | |
function scanUnicodeRange(scanner) { | |
var hexStart = scanner.tokenStart + 1; // skip + | |
var hexLength = 0; | |
scan: { | |
if (scanner.tokenType === NUMBER) { | |
if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP && scanUnicodeNumber(scanner)) { | |
scanner.next(); | |
} else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS) { | |
break scan; | |
} | |
} else { | |
scanner.next(); // PLUSSIGN | |
} | |
if (scanner.tokenType === HYPHENMINUS) { | |
scanner.next(); | |
} | |
if (scanner.tokenType === NUMBER) { | |
scanner.next(); | |
} | |
if (scanner.tokenType === IDENTIFIER) { | |
scanner.next(); | |
} | |
if (scanner.tokenStart === hexStart) { | |
scanner.error('Unexpected input', hexStart); | |
} | |
} | |
// validate for U+x{1,6} or U+x{1,6}-x{1,6} | |
// where x is [0-9a-fA-F] | |
for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) { | |
var code = scanner.source.charCodeAt(i); | |
if (isHex(code) === false && (code !== HYPHENMINUS || wasHyphenMinus)) { | |
scanner.error('Unexpected input', i); | |
} | |
if (code === HYPHENMINUS) { | |
// hex sequence shouldn't be an empty | |
if (hexLength === 0) { | |
scanner.error('Unexpected input', i); | |
} | |
wasHyphenMinus = true; | |
hexLength = 0; | |
} else { | |
hexLength++; | |
// too long hex sequence | |
if (hexLength > 6) { | |
scanner.error('Too long hex sequence', i); | |
} | |
} | |
} | |
// check we have a non-zero sequence | |
if (hexLength === 0) { | |
scanner.error('Unexpected input', i - 1); | |
} | |
// U+abc??? | |
if (!wasHyphenMinus) { | |
// consume as many U+003F QUESTION MARK (?) code points as possible | |
for (; hexLength < 6 && !scanner.eof; scanner.next()) { | |
if (scanner.tokenType !== QUESTIONMARK) { | |
break; | |
} | |
hexLength++; | |
} | |
} | |
} | |
module.exports = { | |
name: 'UnicodeRange', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
this.scanner.next(); // U or u | |
scanUnicodeRange(this.scanner); | |
return { | |
type: 'UnicodeRange', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: this.scanner.substrToCursor(start) | |
}; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{"../../tokenizer":138}],112:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var STRING = TYPE.String; | |
var URL = TYPE.Url; | |
var RAW = TYPE.Raw; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
// url '(' S* (string | raw) S* ')' | |
module.exports = { | |
name: 'Url', | |
structure: { | |
value: ['String', 'Raw'] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var value; | |
this.scanner.eat(URL); | |
this.scanner.skipSC(); | |
switch (this.scanner.tokenType) { | |
case STRING: | |
value = this.String(); | |
break; | |
case RAW: | |
value = this.Raw(this.scanner.currentToken, 0, RAW, true, false); | |
break; | |
default: | |
this.scanner.error('String or Raw is expected'); | |
} | |
this.scanner.skipSC(); | |
this.scanner.eat(RIGHTPARENTHESIS); | |
return { | |
type: 'Url', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
value: value | |
}; | |
}, | |
generate: function(node) { | |
this.chunk('url'); | |
this.chunk('('); | |
this.node(node.value); | |
this.chunk(')'); | |
} | |
}; | |
},{"../../tokenizer":138}],113:[function(require,module,exports){ | |
module.exports = { | |
name: 'Value', | |
structure: { | |
children: [[]] | |
}, | |
parse: function() { | |
var start = this.scanner.tokenStart; | |
var children = this.readSequence(this.scope.Value); | |
return { | |
type: 'Value', | |
loc: this.getLocation(start, this.scanner.tokenStart), | |
children: children | |
}; | |
}, | |
generate: function(node) { | |
this.children(node); | |
} | |
}; | |
},{}],114:[function(require,module,exports){ | |
var WHITESPACE = require('../../tokenizer').TYPE.WhiteSpace; | |
var SPACE = Object.freeze({ | |
type: 'WhiteSpace', | |
loc: null, | |
value: ' ' | |
}); | |
module.exports = { | |
name: 'WhiteSpace', | |
structure: { | |
value: String | |
}, | |
parse: function() { | |
this.scanner.eat(WHITESPACE); | |
return SPACE; | |
// return { | |
// type: 'WhiteSpace', | |
// loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd), | |
// value: this.scanner.consume(WHITESPACE) | |
// }; | |
}, | |
generate: function(node) { | |
this.chunk(node.value); | |
} | |
}; | |
},{"../../tokenizer":138}],115:[function(require,module,exports){ | |
module.exports = { | |
AnPlusB: require('./AnPlusB'), | |
Atrule: require('./Atrule'), | |
AtrulePrelude: require('./AtrulePrelude'), | |
AttributeSelector: require('./AttributeSelector'), | |
Block: require('./Block'), | |
Brackets: require('./Brackets'), | |
CDC: require('./CDC'), | |
CDO: require('./CDO'), | |
ClassSelector: require('./ClassSelector'), | |
Combinator: require('./Combinator'), | |
Comment: require('./Comment'), | |
Declaration: require('./Declaration'), | |
DeclarationList: require('./DeclarationList'), | |
Dimension: require('./Dimension'), | |
Function: require('./Function'), | |
HexColor: require('./HexColor'), | |
Identifier: require('./Identifier'), | |
IdSelector: require('./IdSelector'), | |
MediaFeature: require('./MediaFeature'), | |
MediaQuery: require('./MediaQuery'), | |
MediaQueryList: require('./MediaQueryList'), | |
Nth: require('./Nth'), | |
Number: require('./Number'), | |
Operator: require('./Operator'), | |
Parentheses: require('./Parentheses'), | |
Percentage: require('./Percentage'), | |
PseudoClassSelector: require('./PseudoClassSelector'), | |
PseudoElementSelector: require('./PseudoElementSelector'), | |
Ratio: require('./Ratio'), | |
Raw: require('./Raw'), | |
Rule: require('./Rule'), | |
Selector: require('./Selector'), | |
SelectorList: require('./SelectorList'), | |
String: require('./String'), | |
StyleSheet: require('./StyleSheet'), | |
TypeSelector: require('./TypeSelector'), | |
UnicodeRange: require('./UnicodeRange'), | |
Url: require('./Url'), | |
Value: require('./Value'), | |
WhiteSpace: require('./WhiteSpace') | |
}; | |
},{"./AnPlusB":75,"./Atrule":76,"./AtrulePrelude":77,"./AttributeSelector":78,"./Block":79,"./Brackets":80,"./CDC":81,"./CDO":82,"./ClassSelector":83,"./Combinator":84,"./Comment":85,"./Declaration":86,"./DeclarationList":87,"./Dimension":88,"./Function":89,"./HexColor":90,"./IdSelector":91,"./Identifier":92,"./MediaFeature":93,"./MediaQuery":94,"./MediaQueryList":95,"./Nth":96,"./Number":97,"./Operator":98,"./Parentheses":99,"./Percentage":100,"./PseudoClassSelector":101,"./PseudoElementSelector":102,"./Ratio":103,"./Raw":104,"./Rule":105,"./Selector":106,"./SelectorList":107,"./String":108,"./StyleSheet":109,"./TypeSelector":110,"./UnicodeRange":111,"./Url":112,"./Value":113,"./WhiteSpace":114}],116:[function(require,module,exports){ | |
var DISALLOW_OF_CLAUSE = false; | |
module.exports = { | |
parse: function nth() { | |
return this.createSingleNodeList( | |
this.Nth(DISALLOW_OF_CLAUSE) | |
); | |
} | |
}; | |
},{}],117:[function(require,module,exports){ | |
var ALLOW_OF_CLAUSE = true; | |
module.exports = { | |
parse: function nthWithOfClause() { | |
return this.createSingleNodeList( | |
this.Nth(ALLOW_OF_CLAUSE) | |
); | |
} | |
}; | |
},{}],118:[function(require,module,exports){ | |
module.exports = { | |
parse: function selectorList() { | |
return this.createSingleNodeList( | |
this.SelectorList() | |
); | |
} | |
}; | |
},{}],119:[function(require,module,exports){ | |
module.exports = { | |
parse: function() { | |
return this.createSingleNodeList( | |
this.Identifier() | |
); | |
} | |
}; | |
},{}],120:[function(require,module,exports){ | |
module.exports = { | |
parse: function() { | |
return this.createSingleNodeList( | |
this.SelectorList() | |
); | |
} | |
}; | |
},{}],121:[function(require,module,exports){ | |
module.exports = { | |
'dir': require('./dir'), | |
'has': require('./has'), | |
'lang': require('./lang'), | |
'matches': require('./matches'), | |
'not': require('./not'), | |
'nth-child': require('./nth-child'), | |
'nth-last-child': require('./nth-last-child'), | |
'nth-last-of-type': require('./nth-last-of-type'), | |
'nth-of-type': require('./nth-of-type'), | |
'slotted': require('./slotted') | |
}; | |
},{"./dir":119,"./has":120,"./lang":122,"./matches":123,"./not":124,"./nth-child":125,"./nth-last-child":126,"./nth-last-of-type":127,"./nth-of-type":128,"./slotted":129}],122:[function(require,module,exports){ | |
arguments[4][119][0].apply(exports,arguments) | |
},{"dup":119}],123:[function(require,module,exports){ | |
module.exports = require('./common/selectorList'); | |
},{"./common/selectorList":118}],124:[function(require,module,exports){ | |
arguments[4][123][0].apply(exports,arguments) | |
},{"./common/selectorList":118,"dup":123}],125:[function(require,module,exports){ | |
module.exports = require('./common/nthWithOfClause'); | |
},{"./common/nthWithOfClause":117}],126:[function(require,module,exports){ | |
arguments[4][125][0].apply(exports,arguments) | |
},{"./common/nthWithOfClause":117,"dup":125}],127:[function(require,module,exports){ | |
module.exports = require('./common/nth'); | |
},{"./common/nth":116}],128:[function(require,module,exports){ | |
arguments[4][127][0].apply(exports,arguments) | |
},{"./common/nth":116,"dup":127}],129:[function(require,module,exports){ | |
module.exports = { | |
parse: function compoundSelector() { | |
return this.createSingleNodeList( | |
this.Selector() | |
); | |
} | |
}; | |
},{}],130:[function(require,module,exports){ | |
module.exports = { | |
getNode: require('./default') | |
}; | |
},{"./default":131}],131:[function(require,module,exports){ | |
var cmpChar = require('../../tokenizer').cmpChar; | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var STRING = TYPE.String; | |
var NUMBER = TYPE.Number; | |
var FUNCTION = TYPE.Function; | |
var URL = TYPE.Url; | |
var NUMBERSIGN = TYPE.NumberSign; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket; | |
var PLUSSIGN = TYPE.PlusSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var COMMA = TYPE.Comma; | |
var SOLIDUS = TYPE.Solidus; | |
var ASTERISK = TYPE.Asterisk; | |
var PERCENTSIGN = TYPE.PercentSign; | |
var BACKSLASH = TYPE.Backslash; | |
var U = 117; // 'u'.charCodeAt(0) | |
module.exports = function defaultRecognizer(context) { | |
switch (this.scanner.tokenType) { | |
case NUMBERSIGN: | |
return this.HexColor(); | |
case COMMA: | |
context.space = null; | |
context.ignoreWSAfter = true; | |
return this.Operator(); | |
case SOLIDUS: | |
case ASTERISK: | |
case PLUSSIGN: | |
case HYPHENMINUS: | |
return this.Operator(); | |
case LEFTPARENTHESIS: | |
return this.Parentheses(this.readSequence, context.recognizer); | |
case LEFTSQUAREBRACKET: | |
return this.Brackets(this.readSequence, context.recognizer); | |
case STRING: | |
return this.String(); | |
case NUMBER: | |
switch (this.scanner.lookupType(1)) { | |
case PERCENTSIGN: | |
return this.Percentage(); | |
case IDENTIFIER: | |
// edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension | |
if (cmpChar(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) { | |
return this.Number(); | |
} else { | |
return this.Dimension(); | |
} | |
default: | |
return this.Number(); | |
} | |
case FUNCTION: | |
return this.Function(this.readSequence, context.recognizer); | |
case URL: | |
return this.Url(); | |
case IDENTIFIER: | |
// check for unicode range, it should start with u+ or U+ | |
if (cmpChar(this.scanner.source, this.scanner.tokenStart, U) && | |
cmpChar(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN)) { | |
return this.UnicodeRange(); | |
} else { | |
return this.Identifier(); | |
} | |
} | |
}; | |
},{"../../tokenizer":138}],132:[function(require,module,exports){ | |
module.exports = { | |
AtrulePrelude: require('./atrulePrelude'), | |
Selector: require('./selector'), | |
Value: require('./value') | |
}; | |
},{"./atrulePrelude":130,"./selector":133,"./value":134}],133:[function(require,module,exports){ | |
var TYPE = require('../../tokenizer').TYPE; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var NUMBERSIGN = TYPE.NumberSign; | |
var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket; | |
var PLUSSIGN = TYPE.PlusSign; | |
var SOLIDUS = TYPE.Solidus; | |
var ASTERISK = TYPE.Asterisk; | |
var FULLSTOP = TYPE.FullStop; | |
var COLON = TYPE.Colon; | |
var GREATERTHANSIGN = TYPE.GreaterThanSign; | |
var VERTICALLINE = TYPE.VerticalLine; | |
var TILDE = TYPE.Tilde; | |
function getNode(context) { | |
switch (this.scanner.tokenType) { | |
case PLUSSIGN: | |
case GREATERTHANSIGN: | |
case TILDE: | |
context.space = null; | |
context.ignoreWSAfter = true; | |
return this.Combinator(); | |
case SOLIDUS: // /deep/ | |
return this.Combinator(); | |
case FULLSTOP: | |
return this.ClassSelector(); | |
case LEFTSQUAREBRACKET: | |
return this.AttributeSelector(); | |
case NUMBERSIGN: | |
return this.IdSelector(); | |
case COLON: | |
if (this.scanner.lookupType(1) === COLON) { | |
return this.PseudoElementSelector(); | |
} else { | |
return this.PseudoClassSelector(); | |
} | |
case IDENTIFIER: | |
case ASTERISK: | |
case VERTICALLINE: | |
return this.TypeSelector(); | |
case NUMBER: | |
return this.Percentage(); | |
} | |
}; | |
module.exports = { | |
getNode: getNode | |
}; | |
},{"../../tokenizer":138}],134:[function(require,module,exports){ | |
module.exports = { | |
getNode: require('./default'), | |
'-moz-element': require('../function/element'), | |
'element': require('../function/element'), | |
'expression': require('../function/expression'), | |
'var': require('../function/var') | |
}; | |
},{"../function/element":71,"../function/expression":72,"../function/var":73,"./default":131}],135:[function(require,module,exports){ | |
'use strict'; | |
var CssSyntaxError = require('./error'); | |
var constants = require('./const'); | |
var TYPE = constants.TYPE; | |
var NAME = constants.NAME; | |
var SYMBOL_TYPE = constants.SYMBOL_TYPE; | |
var utils = require('./utils'); | |
var firstCharOffset = utils.firstCharOffset; | |
var cmpStr = utils.cmpStr; | |
var isNumber = utils.isNumber; | |
var findWhiteSpaceStart = utils.findWhiteSpaceStart; | |
var findWhiteSpaceEnd = utils.findWhiteSpaceEnd; | |
var findCommentEnd = utils.findCommentEnd; | |
var findStringEnd = utils.findStringEnd; | |
var findNumberEnd = utils.findNumberEnd; | |
var findIdentifierEnd = utils.findIdentifierEnd; | |
var findUrlRawEnd = utils.findUrlRawEnd; | |
var NULL = 0; | |
var WHITESPACE = TYPE.WhiteSpace; | |
var IDENTIFIER = TYPE.Identifier; | |
var NUMBER = TYPE.Number; | |
var STRING = TYPE.String; | |
var COMMENT = TYPE.Comment; | |
var PUNCTUATOR = TYPE.Punctuator; | |
var CDO = TYPE.CDO; | |
var CDC = TYPE.CDC; | |
var ATKEYWORD = TYPE.AtKeyword; | |
var FUNCTION = TYPE.Function; | |
var URL = TYPE.Url; | |
var RAW = TYPE.Raw; | |
var N = 10; | |
var F = 12; | |
var R = 13; | |
var STAR = TYPE.Asterisk; | |
var SLASH = TYPE.Solidus; | |
var FULLSTOP = TYPE.FullStop; | |
var PLUSSIGN = TYPE.PlusSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var GREATERTHANSIGN = TYPE.GreaterThanSign; | |
var LESSTHANSIGN = TYPE.LessThanSign; | |
var EXCLAMATIONMARK = TYPE.ExclamationMark; | |
var COMMERCIALAT = TYPE.CommercialAt; | |
var QUOTATIONMARK = TYPE.QuotationMark; | |
var APOSTROPHE = TYPE.Apostrophe; | |
var LEFTPARENTHESIS = TYPE.LeftParenthesis; | |
var RIGHTPARENTHESIS = TYPE.RightParenthesis; | |
var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | |
var RIGHTCURLYBRACKET = TYPE.RightCurlyBracket; | |
var LEFTSQUAREBRACKET = TYPE.LeftSquareBracket; | |
var RIGHTSQUAREBRACKET = TYPE.RightSquareBracket; | |
var MIN_BUFFER_SIZE = 16 * 1024; | |
var OFFSET_MASK = 0x00FFFFFF; | |
var TYPE_SHIFT = 24; | |
var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported | |
function computeLinesAndColumns(tokenizer, source) { | |
var sourceLength = source.length; | |
var start = firstCharOffset(source); | |
var lines = tokenizer.lines; | |
var line = tokenizer.startLine; | |
var columns = tokenizer.columns; | |
var column = tokenizer.startColumn; | |
if (lines === null || lines.length < sourceLength + 1) { | |
lines = new SafeUint32Array(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE)); | |
columns = new SafeUint32Array(lines.length); | |
} | |
for (var i = start; i < sourceLength; i++) { | |
var code = source.charCodeAt(i); | |
lines[i] = line; | |
columns[i] = column++; | |
if (code === N || code === R || code === F) { | |
if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) { | |
i++; | |
lines[i] = line; | |
columns[i] = column; | |
} | |
line++; | |
column = 1; | |
} | |
} | |
lines[i] = line; | |
columns[i] = column; | |
tokenizer.linesAnsColumnsComputed = true; | |
tokenizer.lines = lines; | |
tokenizer.columns = columns; | |
} | |
function tokenLayout(tokenizer, source, startPos) { | |
var sourceLength = source.length; | |
var offsetAndType = tokenizer.offsetAndType; | |
var balance = tokenizer.balance; | |
var tokenCount = 0; | |
var prevType = 0; | |
var offset = startPos; | |
var anchor = 0; | |
var balanceCloseCode = 0; | |
var balanceStart = 0; | |
var balancePrev = 0; | |
if (offsetAndType === null || offsetAndType.length < sourceLength + 1) { | |
offsetAndType = new SafeUint32Array(sourceLength + 1024); | |
balance = new SafeUint32Array(sourceLength + 1024); | |
} | |
while (offset < sourceLength) { | |
var code = source.charCodeAt(offset); | |
var type = code < 0x80 ? SYMBOL_TYPE[code] : IDENTIFIER; | |
balance[tokenCount] = sourceLength; | |
switch (type) { | |
case WHITESPACE: | |
offset = findWhiteSpaceEnd(source, offset + 1); | |
break; | |
case PUNCTUATOR: | |
switch (code) { | |
case balanceCloseCode: | |
balancePrev = balanceStart & OFFSET_MASK; | |
balanceStart = balance[balancePrev]; | |
balanceCloseCode = balanceStart >> TYPE_SHIFT; | |
balance[tokenCount] = balancePrev; | |
balance[balancePrev++] = tokenCount; | |
for (; balancePrev < tokenCount; balancePrev++) { | |
if (balance[balancePrev] === sourceLength) { | |
balance[balancePrev] = tokenCount; | |
} | |
} | |
break; | |
case LEFTSQUAREBRACKET: | |
balance[tokenCount] = balanceStart; | |
balanceCloseCode = RIGHTSQUAREBRACKET; | |
balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount; | |
break; | |
case LEFTCURLYBRACKET: | |
balance[tokenCount] = balanceStart; | |
balanceCloseCode = RIGHTCURLYBRACKET; | |
balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount; | |
break; | |
case LEFTPARENTHESIS: | |
balance[tokenCount] = balanceStart; | |
balanceCloseCode = RIGHTPARENTHESIS; | |
balanceStart = (balanceCloseCode << TYPE_SHIFT) | tokenCount; | |
break; | |
} | |
// /* | |
if (code === STAR && prevType === SLASH) { | |
type = COMMENT; | |
offset = findCommentEnd(source, offset + 1); | |
tokenCount--; // rewrite prev token | |
break; | |
} | |
// edge case for -.123 and +.123 | |
if (code === FULLSTOP && (prevType === PLUSSIGN || prevType === HYPHENMINUS)) { | |
if (offset + 1 < sourceLength && isNumber(source.charCodeAt(offset + 1))) { | |
type = NUMBER; | |
offset = findNumberEnd(source, offset + 2, false); | |
tokenCount--; // rewrite prev token | |
break; | |
} | |
} | |
// <!-- | |
if (code === EXCLAMATIONMARK && prevType === LESSTHANSIGN) { | |
if (offset + 2 < sourceLength && | |
source.charCodeAt(offset + 1) === HYPHENMINUS && | |
source.charCodeAt(offset + 2) === HYPHENMINUS) { | |
type = CDO; | |
offset = offset + 3; | |
tokenCount--; // rewrite prev token | |
break; | |
} | |
} | |
// --> | |
if (code === HYPHENMINUS && prevType === HYPHENMINUS) { | |
if (offset + 1 < sourceLength && source.charCodeAt(offset + 1) === GREATERTHANSIGN) { | |
type = CDC; | |
offset = offset + 2; | |
tokenCount--; // rewrite prev token | |
break; | |
} | |
} | |
// ident( | |
if (code === LEFTPARENTHESIS && prevType === IDENTIFIER) { | |
offset = offset + 1; | |
tokenCount--; // rewrite prev token | |
balance[tokenCount] = balance[tokenCount + 1]; | |
balanceStart--; | |
// 4 char length identifier and equal to `url(` (case insensitive) | |
if (offset - anchor === 4 && cmpStr(source, anchor, offset, 'url(')) { | |
// special case for url() because it can contain any symbols sequence with few exceptions | |
anchor = findWhiteSpaceEnd(source, offset); | |
code = source.charCodeAt(anchor); | |
if (code !== LEFTPARENTHESIS && | |
code !== RIGHTPARENTHESIS && | |
code !== QUOTATIONMARK && | |
code !== APOSTROPHE) { | |
// url( | |
offsetAndType[tokenCount++] = (URL << TYPE_SHIFT) | offset; | |
balance[tokenCount] = sourceLength; | |
// ws* | |
if (anchor !== offset) { | |
offsetAndType[tokenCount++] = (WHITESPACE << TYPE_SHIFT) | anchor; | |
balance[tokenCount] = sourceLength; | |
} | |
// raw | |
type = RAW; | |
offset = findUrlRawEnd(source, anchor); | |
} else { | |
type = URL; | |
} | |
} else { | |
type = FUNCTION; | |
} | |
break; | |
} | |
type = code; | |
offset = offset + 1; | |
break; | |
case NUMBER: | |
offset = findNumberEnd(source, offset + 1, prevType !== FULLSTOP); | |
// merge number with a preceding dot, dash or plus | |
if (prevType === FULLSTOP || | |
prevType === HYPHENMINUS || | |
prevType === PLUSSIGN) { | |
tokenCount--; // rewrite prev token | |
} | |
break; | |
case STRING: | |
offset = findStringEnd(source, offset + 1, code); | |
break; | |
default: | |
anchor = offset; | |
offset = findIdentifierEnd(source, offset); | |
// merge identifier with a preceding dash | |
if (prevType === HYPHENMINUS) { | |
// rewrite prev token | |
tokenCount--; | |
// restore prev prev token type | |
// for case @-prefix-ident | |
prevType = tokenCount === 0 ? 0 : offsetAndType[tokenCount - 1] >> TYPE_SHIFT; | |
} | |
if (prevType === COMMERCIALAT) { | |
// rewrite prev token and change type to <at-keyword-token> | |
tokenCount--; | |
type = ATKEYWORD; | |
} | |
} | |
offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | offset; | |
prevType = type; | |
} | |
// finalize arrays | |
offsetAndType[tokenCount] = offset; | |
balance[tokenCount] = sourceLength; | |
balance[sourceLength] = sourceLength; // prevents false positive balance match with any token | |
while (balanceStart !== 0) { | |
balancePrev = balanceStart & OFFSET_MASK; | |
balanceStart = balance[balancePrev]; | |
balance[balancePrev] = sourceLength; | |
} | |
tokenizer.offsetAndType = offsetAndType; | |
tokenizer.tokenCount = tokenCount; | |
tokenizer.balance = balance; | |
} | |
// | |
// tokenizer | |
// | |
var Tokenizer = function(source, startOffset, startLine, startColumn) { | |
this.offsetAndType = null; | |
this.balance = null; | |
this.lines = null; | |
this.columns = null; | |
this.setSource(source, startOffset, startLine, startColumn); | |
}; | |
Tokenizer.prototype = { | |
setSource: function(source, startOffset, startLine, startColumn) { | |
var safeSource = String(source || ''); | |
var start = firstCharOffset(safeSource); | |
this.source = safeSource; | |
this.firstCharOffset = start; | |
this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset; | |
this.startLine = typeof startLine === 'undefined' ? 1 : startLine; | |
this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn; | |
this.linesAnsColumnsComputed = false; | |
this.eof = false; | |
this.currentToken = -1; | |
this.tokenType = 0; | |
this.tokenStart = start; | |
this.tokenEnd = start; | |
tokenLayout(this, safeSource, start); | |
this.next(); | |
}, | |
lookupType: function(offset) { | |
offset += this.currentToken; | |
if (offset < this.tokenCount) { | |
return this.offsetAndType[offset] >> TYPE_SHIFT; | |
} | |
return NULL; | |
}, | |
lookupNonWSType: function(offset) { | |
offset += this.currentToken; | |
for (var type; offset < this.tokenCount; offset++) { | |
type = this.offsetAndType[offset] >> TYPE_SHIFT; | |
if (type !== WHITESPACE) { | |
return type; | |
} | |
} | |
return NULL; | |
}, | |
lookupValue: function(offset, referenceStr) { | |
offset += this.currentToken; | |
if (offset < this.tokenCount) { | |
return cmpStr( | |
this.source, | |
this.offsetAndType[offset - 1] & OFFSET_MASK, | |
this.offsetAndType[offset] & OFFSET_MASK, | |
referenceStr | |
); | |
} | |
return false; | |
}, | |
getTokenStart: function(tokenNum) { | |
if (tokenNum === this.currentToken) { | |
return this.tokenStart; | |
} | |
if (tokenNum > 0) { | |
return tokenNum < this.tokenCount | |
? this.offsetAndType[tokenNum - 1] & OFFSET_MASK | |
: this.offsetAndType[this.tokenCount] & OFFSET_MASK; | |
} | |
return this.firstCharOffset; | |
}, | |
getOffsetExcludeWS: function() { | |
if (this.currentToken > 0) { | |
if ((this.offsetAndType[this.currentToken - 1] >> TYPE_SHIFT) === WHITESPACE) { | |
return this.currentToken > 1 | |
? this.offsetAndType[this.currentToken - 2] & OFFSET_MASK | |
: this.firstCharOffset; | |
} | |
} | |
return this.tokenStart; | |
}, | |
getRawLength: function(startToken, endTokenType1, endTokenType2, includeTokenType2) { | |
var cursor = startToken; | |
var balanceEnd; | |
loop: | |
for (; cursor < this.tokenCount; cursor++) { | |
balanceEnd = this.balance[cursor]; | |
// belance end points to offset before start | |
if (balanceEnd < startToken) { | |
break loop; | |
} | |
// check token is stop type | |
switch (this.offsetAndType[cursor] >> TYPE_SHIFT) { | |
case endTokenType1: | |
break loop; | |
case endTokenType2: | |
if (includeTokenType2) { | |
cursor++; | |
} | |
break loop; | |
default: | |
// fast forward to the end of balanced block | |
if (this.balance[balanceEnd] === cursor) { | |
cursor = balanceEnd; | |
} | |
} | |
} | |
return cursor - this.currentToken; | |
}, | |
isBalanceEdge: function(pos) { | |
var balanceStart = this.balance[this.currentToken]; | |
return balanceStart < pos; | |
}, | |
getTokenValue: function() { | |
return this.source.substring(this.tokenStart, this.tokenEnd); | |
}, | |
substrToCursor: function(start) { | |
return this.source.substring(start, this.tokenStart); | |
}, | |
skipWS: function() { | |
for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) { | |
if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE) { | |
break; | |
} | |
} | |
if (skipTokenCount > 0) { | |
this.skip(skipTokenCount); | |
} | |
}, | |
skipSC: function() { | |
while (this.tokenType === WHITESPACE || this.tokenType === COMMENT) { | |
this.next(); | |
} | |
}, | |
skip: function(tokenCount) { | |
var next = this.currentToken + tokenCount; | |
if (next < this.tokenCount) { | |
this.currentToken = next; | |
this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK; | |
next = this.offsetAndType[next]; | |
this.tokenType = next >> TYPE_SHIFT; | |
this.tokenEnd = next & OFFSET_MASK; | |
} else { | |
this.currentToken = this.tokenCount; | |
this.next(); | |
} | |
}, | |
next: function() { | |
var next = this.currentToken + 1; | |
if (next < this.tokenCount) { | |
this.currentToken = next; | |
this.tokenStart = this.tokenEnd; | |
next = this.offsetAndType[next]; | |
this.tokenType = next >> TYPE_SHIFT; | |
this.tokenEnd = next & OFFSET_MASK; | |
} else { | |
this.currentToken = this.tokenCount; | |
this.eof = true; | |
this.tokenType = NULL; | |
this.tokenStart = this.tokenEnd = this.source.length; | |
} | |
}, | |
eat: function(tokenType) { | |
if (this.tokenType !== tokenType) { | |
var offset = this.tokenStart; | |
var message = NAME[tokenType] + ' is expected'; | |
// tweak message and offset | |
if (tokenType === IDENTIFIER) { | |
// when identifier is expected but there is a function or url | |
if (this.tokenType === FUNCTION || this.tokenType === URL) { | |
offset = this.tokenEnd - 1; | |
message += ' but function found'; | |
} | |
} else { | |
// when test type is part of another token show error for current position + 1 | |
// e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd | |
if (this.source.charCodeAt(this.tokenStart) === tokenType) { | |
offset = offset + 1; | |
} | |
} | |
this.error(message, offset); | |
} | |
this.next(); | |
}, | |
eatNonWS: function(tokenType) { | |
this.skipWS(); | |
this.eat(tokenType); | |
}, | |
consume: function(tokenType) { | |
var value = this.getTokenValue(); | |
this.eat(tokenType); | |
return value; | |
}, | |
consumeFunctionName: function() { | |
var name = this.source.substring(this.tokenStart, this.tokenEnd - 1); | |
this.eat(FUNCTION); | |
return name; | |
}, | |
consumeNonWS: function(tokenType) { | |
this.skipWS(); | |
return this.consume(tokenType); | |
}, | |
expectIdentifier: function(name) { | |
if (this.tokenType !== IDENTIFIER || cmpStr(this.source, this.tokenStart, this.tokenEnd, name) === false) { | |
this.error('Identifier `' + name + '` is expected'); | |
} | |
this.next(); | |
}, | |
getLocation: function(offset, filename) { | |
if (!this.linesAnsColumnsComputed) { | |
computeLinesAndColumns(this, this.source); | |
} | |
return { | |
source: filename, | |
offset: this.startOffset + offset, | |
line: this.lines[offset], | |
column: this.columns[offset] | |
}; | |
}, | |
getLocationRange: function(start, end, filename) { | |
if (!this.linesAnsColumnsComputed) { | |
computeLinesAndColumns(this, this.source); | |
} | |
return { | |
source: filename, | |
start: { | |
offset: this.startOffset + start, | |
line: this.lines[start], | |
column: this.columns[start] | |
}, | |
end: { | |
offset: this.startOffset + end, | |
line: this.lines[end], | |
column: this.columns[end] | |
} | |
}; | |
}, | |
error: function(message, offset) { | |
var location = typeof offset !== 'undefined' && offset < this.source.length | |
? this.getLocation(offset) | |
: this.eof | |
? this.getLocation(findWhiteSpaceStart(this.source, this.source.length - 1)) | |
: this.getLocation(this.tokenStart); | |
throw new CssSyntaxError( | |
message || 'Unexpected input', | |
this.source, | |
location.offset, | |
location.line, | |
location.column | |
); | |
}, | |
dump: function() { | |
var offset = 0; | |
return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item, idx) { | |
var start = offset; | |
var end = item & OFFSET_MASK; | |
offset = end; | |
return { | |
idx: idx, | |
type: NAME[item >> TYPE_SHIFT], | |
chunk: this.source.substring(start, end), | |
balance: this.balance[idx] | |
}; | |
}, this); | |
} | |
}; | |
// extend with error class | |
Tokenizer.CssSyntaxError = CssSyntaxError; | |
// extend tokenizer with constants | |
Object.keys(constants).forEach(function(key) { | |
Tokenizer[key] = constants[key]; | |
}); | |
// extend tokenizer with static methods from utils | |
Object.keys(utils).forEach(function(key) { | |
Tokenizer[key] = utils[key]; | |
}); | |
// warm up tokenizer to elimitate code branches that never execute | |
// fix soft deoptimizations (insufficient type feedback) | |
new Tokenizer('\n\r\r\n\f<!---->//""\'\'/*\r\n\f*/1a;.\\31\t\+2{url(a);func();+1.2e3 -.4e-5 .6e+7}').getLocation(); | |
module.exports = Tokenizer; | |
},{"./const":136,"./error":137,"./utils":139}],136:[function(require,module,exports){ | |
'use strict'; | |
// token types (note: value shouldn't intersect with used char codes) | |
var WHITESPACE = 1; | |
var IDENTIFIER = 2; | |
var NUMBER = 3; | |
var STRING = 4; | |
var COMMENT = 5; | |
var PUNCTUATOR = 6; | |
var CDO = 7; | |
var CDC = 8; | |
var ATKEYWORD = 14; | |
var FUNCTION = 15; | |
var URL = 16; | |
var RAW = 17; | |
var TAB = 9; | |
var N = 10; | |
var F = 12; | |
var R = 13; | |
var SPACE = 32; | |
var TYPE = { | |
WhiteSpace: WHITESPACE, | |
Identifier: IDENTIFIER, | |
Number: NUMBER, | |
String: STRING, | |
Comment: COMMENT, | |
Punctuator: PUNCTUATOR, | |
CDO: CDO, | |
CDC: CDC, | |
AtKeyword: ATKEYWORD, | |
Function: FUNCTION, | |
Url: URL, | |
Raw: RAW, | |
ExclamationMark: 33, // ! | |
QuotationMark: 34, // " | |
NumberSign: 35, // # | |
DollarSign: 36, // $ | |
PercentSign: 37, // % | |
Ampersand: 38, // & | |
Apostrophe: 39, // ' | |
LeftParenthesis: 40, // ( | |
RightParenthesis: 41, // ) | |
Asterisk: 42, // * | |
PlusSign: 43, // + | |
Comma: 44, // , | |
HyphenMinus: 45, // - | |
FullStop: 46, // . | |
Solidus: 47, // / | |
Colon: 58, // : | |
Semicolon: 59, // ; | |
LessThanSign: 60, // < | |
EqualsSign: 61, // = | |
GreaterThanSign: 62, // > | |
QuestionMark: 63, // ? | |
CommercialAt: 64, // @ | |
LeftSquareBracket: 91, // [ | |
Backslash: 92, // \ | |
RightSquareBracket: 93, // ] | |
CircumflexAccent: 94, // ^ | |
LowLine: 95, // _ | |
GraveAccent: 96, // ` | |
LeftCurlyBracket: 123, // { | |
VerticalLine: 124, // | | |
RightCurlyBracket: 125, // } | |
Tilde: 126 // ~ | |
}; | |
var NAME = Object.keys(TYPE).reduce(function(result, key) { | |
result[TYPE[key]] = key; | |
return result; | |
}, {}); | |
// https://drafts.csswg.org/css-syntax/#tokenizer-definitions | |
// > non-ASCII code point | |
// > A code point with a value equal to or greater than U+0080 <control> | |
// > name-start code point | |
// > A letter, a non-ASCII code point, or U+005F LOW LINE (_). | |
// > name code point | |
// > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-) | |
// That means only ASCII code points has a special meaning and we a maps for 0..127 codes only | |
var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported | |
var SYMBOL_TYPE = new SafeUint32Array(0x80); | |
var PUNCTUATION = new SafeUint32Array(0x80); | |
var STOP_URL_RAW = new SafeUint32Array(0x80); | |
for (var i = 0; i < SYMBOL_TYPE.length; i++) { | |
SYMBOL_TYPE[i] = IDENTIFIER; | |
} | |
// fill categories | |
[ | |
TYPE.ExclamationMark, // ! | |
TYPE.QuotationMark, // " | |
TYPE.NumberSign, // # | |
TYPE.DollarSign, // $ | |
TYPE.PercentSign, // % | |
TYPE.Ampersand, // & | |
TYPE.Apostrophe, // ' | |
TYPE.LeftParenthesis, // ( | |
TYPE.RightParenthesis, // ) | |
TYPE.Asterisk, // * | |
TYPE.PlusSign, // + | |
TYPE.Comma, // , | |
TYPE.HyphenMinus, // - | |
TYPE.FullStop, // . | |
TYPE.Solidus, // / | |
TYPE.Colon, // : | |
TYPE.Semicolon, // ; | |
TYPE.LessThanSign, // < | |
TYPE.EqualsSign, // = | |
TYPE.GreaterThanSign, // > | |
TYPE.QuestionMark, // ? | |
TYPE.CommercialAt, // @ | |
TYPE.LeftSquareBracket, // [ | |
// TYPE.Backslash, // \ | |
TYPE.RightSquareBracket, // ] | |
TYPE.CircumflexAccent, // ^ | |
// TYPE.LowLine, // _ | |
TYPE.GraveAccent, // ` | |
TYPE.LeftCurlyBracket, // { | |
TYPE.VerticalLine, // | | |
TYPE.RightCurlyBracket, // } | |
TYPE.Tilde // ~ | |
].forEach(function(key) { | |
SYMBOL_TYPE[Number(key)] = PUNCTUATOR; | |
PUNCTUATION[Number(key)] = PUNCTUATOR; | |
}); | |
for (var i = 48; i <= 57; i++) { | |
SYMBOL_TYPE[i] = NUMBER; | |
} | |
SYMBOL_TYPE[SPACE] = WHITESPACE; | |
SYMBOL_TYPE[TAB] = WHITESPACE; | |
SYMBOL_TYPE[N] = WHITESPACE; | |
SYMBOL_TYPE[R] = WHITESPACE; | |
SYMBOL_TYPE[F] = WHITESPACE; | |
SYMBOL_TYPE[TYPE.Apostrophe] = STRING; | |
SYMBOL_TYPE[TYPE.QuotationMark] = STRING; | |
STOP_URL_RAW[SPACE] = 1; | |
STOP_URL_RAW[TAB] = 1; | |
STOP_URL_RAW[N] = 1; | |
STOP_URL_RAW[R] = 1; | |
STOP_URL_RAW[F] = 1; | |
STOP_URL_RAW[TYPE.Apostrophe] = 1; | |
STOP_URL_RAW[TYPE.QuotationMark] = 1; | |
STOP_URL_RAW[TYPE.LeftParenthesis] = 1; | |
STOP_URL_RAW[TYPE.RightParenthesis] = 1; | |
// whitespace is punctuation ... | |
PUNCTUATION[SPACE] = PUNCTUATOR; | |
PUNCTUATION[TAB] = PUNCTUATOR; | |
PUNCTUATION[N] = PUNCTUATOR; | |
PUNCTUATION[R] = PUNCTUATOR; | |
PUNCTUATION[F] = PUNCTUATOR; | |
// ... hyper minus is not | |
PUNCTUATION[TYPE.HyphenMinus] = 0; | |
module.exports = { | |
TYPE: TYPE, | |
NAME: NAME, | |
SYMBOL_TYPE: SYMBOL_TYPE, | |
PUNCTUATION: PUNCTUATION, | |
STOP_URL_RAW: STOP_URL_RAW | |
}; | |
},{}],137:[function(require,module,exports){ | |
'use strict'; | |
var createCustomError = require('../utils/createCustomError'); | |
var MAX_LINE_LENGTH = 100; | |
var OFFSET_CORRECTION = 60; | |
var TAB_REPLACEMENT = ' '; | |
function sourceFragment(error, extraLines) { | |
function processLines(start, end) { | |
return lines.slice(start, end).map(function(line, idx) { | |
var num = String(start + idx + 1); | |
while (num.length < maxNumLength) { | |
num = ' ' + num; | |
} | |
return num + ' |' + line; | |
}).join('\n'); | |
} | |
var lines = error.source.split(/\r\n?|\n|\f/); | |
var line = error.line; | |
var column = error.column; | |
var startLine = Math.max(1, line - extraLines) - 1; | |
var endLine = Math.min(line + extraLines, lines.length + 1); | |
var maxNumLength = Math.max(4, String(endLine).length) + 1; | |
var cutLeft = 0; | |
// column correction according to replaced tab before column | |
column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length; | |
if (column > MAX_LINE_LENGTH) { | |
cutLeft = column - OFFSET_CORRECTION + 3; | |
column = OFFSET_CORRECTION - 2; | |
} | |
for (var i = startLine; i <= endLine; i++) { | |
if (i >= 0 && i < lines.length) { | |
lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT); | |
lines[i] = | |
(cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') + | |
lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) + | |
(lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : ''); | |
} | |
} | |
return [ | |
processLines(startLine, line), | |
new Array(column + maxNumLength + 2).join('-') + '^', | |
processLines(line, endLine) | |
].filter(Boolean).join('\n'); | |
} | |
var CssSyntaxError = function(message, source, offset, line, column) { | |
var error = createCustomError('CssSyntaxError', message); | |
error.source = source; | |
error.offset = offset; | |
error.line = line; | |
error.column = column; | |
error.sourceFragment = function(extraLines) { | |
return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines); | |
}; | |
Object.defineProperty(error, 'formattedMessage', { | |
get: function() { | |
return ( | |
'Parse error: ' + error.message + '\n' + | |
sourceFragment(error, 2) | |
); | |
} | |
}); | |
// for backward capability | |
error.parseError = { | |
offset: offset, | |
line: line, | |
column: column | |
}; | |
return error; | |
}; | |
module.exports = CssSyntaxError; | |
},{"../utils/createCustomError":141}],138:[function(require,module,exports){ | |
module.exports = require('./Tokenizer'); | |
},{"./Tokenizer":135}],139:[function(require,module,exports){ | |
'use strict'; | |
var constants = require('./const'); | |
var PUNCTUATION = constants.PUNCTUATION; | |
var STOP_URL_RAW = constants.STOP_URL_RAW; | |
var TYPE = constants.TYPE; | |
var FULLSTOP = TYPE.FullStop; | |
var PLUSSIGN = TYPE.PlusSign; | |
var HYPHENMINUS = TYPE.HyphenMinus; | |
var PUNCTUATOR = TYPE.Punctuator; | |
var TAB = 9; | |
var N = 10; | |
var F = 12; | |
var R = 13; | |
var SPACE = 32; | |
var BACK_SLASH = 92; | |
var E = 101; // 'e'.charCodeAt(0) | |
function firstCharOffset(source) { | |
// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark) | |
if (source.charCodeAt(0) === 0xFEFF || // UTF-16BE | |
source.charCodeAt(0) === 0xFFFE) { // UTF-16LE | |
return 1; | |
} | |
return 0; | |
} | |
function isHex(code) { | |
return (code >= 48 && code <= 57) || // 0 .. 9 | |
(code >= 65 && code <= 70) || // A .. F | |
(code >= 97 && code <= 102); // a .. f | |
} | |
function isNumber(code) { | |
return code >= 48 && code <= 57; | |
} | |
function isWhiteSpace(code) { | |
return code === SPACE || code === TAB || isNewline(code); | |
} | |
function isNewline(code) { | |
return code === R || code === N || code === F; | |
} | |
function getNewlineLength(source, offset, code) { | |
if (isNewline(code)) { | |
if (code === R && offset + 1 < source.length && source.charCodeAt(offset + 1) === N) { | |
return 2; | |
} | |
return 1; | |
} | |
return 0; | |
} | |
function cmpChar(testStr, offset, referenceCode) { | |
var code = testStr.charCodeAt(offset); | |
// code.toLowerCase() for A..Z | |
if (code >= 65 && code <= 90) { | |
code = code | 32; | |
} | |
return code === referenceCode; | |
} | |
function cmpStr(testStr, start, end, referenceStr) { | |
if (end - start !== referenceStr.length) { | |
return false; | |
} | |
if (start < 0 || end > testStr.length) { | |
return false; | |
} | |
for (var i = start; i < end; i++) { | |
var testCode = testStr.charCodeAt(i); | |
var refCode = referenceStr.charCodeAt(i - start); | |
// testCode.toLowerCase() for A..Z | |
if (testCode >= 65 && testCode <= 90) { | |
testCode = testCode | 32; | |
} | |
if (testCode !== refCode) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function findWhiteSpaceStart(source, offset) { | |
while (offset >= 0 && isWhiteSpace(source.charCodeAt(offset))) { | |
offset--; | |
} | |
return offset + 1; | |
} | |
function findWhiteSpaceEnd(source, offset) { | |
while (offset < source.length && isWhiteSpace(source.charCodeAt(offset))) { | |
offset++; | |
} | |
return offset; | |
} | |
function findCommentEnd(source, offset) { | |
var commentEnd = source.indexOf('*/', offset); | |
if (commentEnd === -1) { | |
return source.length; | |
} | |
return commentEnd + 2; | |
} | |
function findStringEnd(source, offset, quote) { | |
for (; offset < source.length; offset++) { | |
var code = source.charCodeAt(offset); | |
// TODO: bad string | |
if (code === BACK_SLASH) { | |
offset++; | |
} else if (code === quote) { | |
offset++; | |
break; | |
} | |
} | |
return offset; | |
} | |
function findDecimalNumberEnd(source, offset) { | |
while (offset < source.length && isNumber(source.charCodeAt(offset))) { | |
offset++; | |
} | |
return offset; | |
} | |
function findNumberEnd(source, offset, allowFraction) { | |
var code; | |
offset = findDecimalNumberEnd(source, offset); | |
// fraction: .\d+ | |
if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP) { | |
code = source.charCodeAt(offset + 1); | |
if (isNumber(code)) { | |
offset = findDecimalNumberEnd(source, offset + 1); | |
} | |
} | |
// exponent: e[+-]\d+ | |
if (offset + 1 < source.length) { | |
if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e` | |
code = source.charCodeAt(offset + 1); | |
if (code === PLUSSIGN || code === HYPHENMINUS) { | |
if (offset + 2 < source.length) { | |
code = source.charCodeAt(offset + 2); | |
} | |
} | |
if (isNumber(code)) { | |
offset = findDecimalNumberEnd(source, offset + 2); | |
} | |
} | |
} | |
return offset; | |
} | |
// skip escaped unicode sequence that can ends with space | |
// [0-9a-f]{1,6}(\r\n|[ \n\r\t\f])? | |
function findEscapeEnd(source, offset) { | |
for (var i = 0; i < 7 && offset + i < source.length; i++) { | |
var code = source.charCodeAt(offset + i); | |
if (i !== 6 && isHex(code)) { | |
continue; | |
} | |
if (i > 0) { | |
offset += i - 1 + getNewlineLength(source, offset + i, code); | |
if (code === SPACE || code === TAB) { | |
offset++; | |
} | |
} | |
break; | |
} | |
return offset; | |
} | |
function findIdentifierEnd(source, offset) { | |
for (; offset < source.length; offset++) { | |
var code = source.charCodeAt(offset); | |
if (code === BACK_SLASH) { | |
offset = findEscapeEnd(source, offset + 1); | |
} else if (code < 0x80 && PUNCTUATION[code] === PUNCTUATOR) { | |
break; | |
} | |
} | |
return offset; | |
} | |
function findUrlRawEnd(source, offset) { | |
for (; offset < source.length; offset++) { | |
var code = source.charCodeAt(offset); | |
if (code === BACK_SLASH) { | |
offset = findEscapeEnd(source, offset + 1); | |
} else if (code < 0x80 && STOP_URL_RAW[code] === 1) { | |
break; | |
} | |
} | |
return offset; | |
} | |
module.exports = { | |
firstCharOffset: firstCharOffset, | |
isHex: isHex, | |
isNumber: isNumber, | |
isWhiteSpace: isWhiteSpace, | |
isNewline: isNewline, | |
getNewlineLength: getNewlineLength, | |
cmpChar: cmpChar, | |
cmpStr: cmpStr, | |
findWhiteSpaceStart: findWhiteSpaceStart, | |
findWhiteSpaceEnd: findWhiteSpaceEnd, | |
findCommentEnd: findCommentEnd, | |
findStringEnd: findStringEnd, | |
findDecimalNumberEnd: findDecimalNumberEnd, | |
findNumberEnd: findNumberEnd, | |
findEscapeEnd: findEscapeEnd, | |
findIdentifierEnd: findIdentifierEnd, | |
findUrlRawEnd: findUrlRawEnd | |
}; | |
},{"./const":136}],140:[function(require,module,exports){ | |
'use strict'; | |
var List = require('./list'); | |
module.exports = function clone(node) { | |
var result = {}; | |
for (var key in node) { | |
var value = node[key]; | |
if (value) { | |
if (Array.isArray(value) || value instanceof List) { | |
value = value.map(clone); | |
} else if (value.constructor === Object) { | |
value = clone(value); | |
} | |
} | |
result[key] = value; | |
} | |
return result; | |
}; | |
},{"./list":142}],141:[function(require,module,exports){ | |
module.exports = function createCustomError(name, message) { | |
// use Object.create(), because some VMs prevent setting line/column otherwise | |
// (iOS Safari 10 even throws an exception) | |
var error = Object.create(SyntaxError.prototype); | |
var errorStack = new Error(); | |
error.name = name; | |
error.message = message; | |
Object.defineProperty(error, 'stack', { | |
get: function() { | |
return (errorStack.stack || '').replace(/^(.+\n){1,3}/, name + ': ' + message + '\n'); | |
} | |
}); | |
return error; | |
}; | |
},{}],142:[function(require,module,exports){ | |
'use strict'; | |
// | |
// item item item item | |
// /------\ /------\ /------\ /------\ | |
// | data | | data | | data | | data | | |
// null <--+-prev |<---+-prev |<---+-prev |<---+-prev | | |
// | next-+--->| next-+--->| next-+--->| next-+--> null | |
// \------/ \------/ \------/ \------/ | |
// ^ ^ | |
// | list | | |
// | /------\ | | |
// \--------------+-head | | | |
// | tail-+--------------/ | |
// \------/ | |
// | |
function createItem(data) { | |
return { | |
prev: null, | |
next: null, | |
data: data | |
}; | |
} | |
function allocateCursor(node, prev, next) { | |
var cursor; | |
if (cursors !== null) { | |
cursor = cursors; | |
cursors = cursors.cursor; | |
cursor.prev = prev; | |
cursor.next = next; | |
cursor.cursor = node.cursor; | |
} else { | |
cursor = { | |
prev: prev, | |
next: next, | |
cursor: node.cursor | |
}; | |
} | |
node.cursor = cursor; | |
return cursor; | |
} | |
function releaseCursor(node) { | |
var cursor = node.cursor; | |
node.cursor = cursor.cursor; | |
cursor.prev = null; | |
cursor.next = null; | |
cursor.cursor = cursors; | |
cursors = cursor; | |
} | |
var cursors = null; | |
var List = function() { | |
this.cursor = null; | |
this.head = null; | |
this.tail = null; | |
}; | |
List.createItem = createItem; | |
List.prototype.createItem = createItem; | |
List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) { | |
var cursor = this.cursor; | |
while (cursor !== null) { | |
if (cursor.prev === prevOld) { | |
cursor.prev = prevNew; | |
} | |
if (cursor.next === nextOld) { | |
cursor.next = nextNew; | |
} | |
cursor = cursor.cursor; | |
} | |
}; | |
List.prototype.getSize = function() { | |
var size = 0; | |
var cursor = this.head; | |
while (cursor) { | |
size++; | |
cursor = cursor.next; | |
} | |
return size; | |
}; | |
List.prototype.fromArray = function(array) { | |
var cursor = null; | |
this.head = null; | |
for (var i = 0; i < array.length; i++) { | |
var item = createItem(array[i]); | |
if (cursor !== null) { | |
cursor.next = item; | |
} else { | |
this.head = item; | |
} | |
item.prev = cursor; | |
cursor = item; | |
} | |
this.tail = cursor; | |
return this; | |
}; | |
List.prototype.toArray = function() { | |
var cursor = this.head; | |
var result = []; | |
while (cursor) { | |
result.push(cursor.data); | |
cursor = cursor.next; | |
} | |
return result; | |
}; | |
List.prototype.toJSON = List.prototype.toArray; | |
List.prototype.isEmpty = function() { | |
return this.head === null; | |
}; | |
List.prototype.first = function() { | |
return this.head && this.head.data; | |
}; | |
List.prototype.last = function() { | |
return this.tail && this.tail.data; | |
}; | |
List.prototype.each = function(fn, context) { | |
var item; | |
if (context === undefined) { | |
context = this; | |
} | |
// push cursor | |
var cursor = allocateCursor(this, null, this.head); | |
while (cursor.next !== null) { | |
item = cursor.next; | |
cursor.next = item.next; | |
fn.call(context, item.data, item, this); | |
} | |
// pop cursor | |
releaseCursor(this); | |
}; | |
List.prototype.forEach = List.prototype.each; | |
List.prototype.eachRight = function(fn, context) { | |
var item; | |
if (context === undefined) { | |
context = this; | |
} | |
// push cursor | |
var cursor = allocateCursor(this, this.tail, null); | |
while (cursor.prev !== null) { | |
item = cursor.prev; | |
cursor.prev = item.prev; | |
fn.call(context, item.data, item, this); | |
} | |
// pop cursor | |
releaseCursor(this); | |
}; | |
List.prototype.forEachRight = List.prototype.eachRight; | |
List.prototype.nextUntil = function(start, fn, context) { | |
if (start === null) { | |
return; | |
} | |
var item; | |
if (context === undefined) { | |
context = this; | |
} | |
// push cursor | |
var cursor = allocateCursor(this, null, start); | |
while (cursor.next !== null) { | |
item = cursor.next; | |
cursor.next = item.next; | |
if (fn.call(context, item.data, item, this)) { | |
break; | |
} | |
} | |
// pop cursor | |
releaseCursor(this); | |
}; | |
List.prototype.prevUntil = function(start, fn, context) { | |
if (start === null) { | |
return; | |
} | |
var item; | |
if (context === undefined) { | |
context = this; | |
} | |
// push cursor | |
var cursor = allocateCursor(this, start, null); | |
while (cursor.prev !== null) { | |
item = cursor.prev; | |
cursor.prev = item.prev; | |
if (fn.call(context, item.data, item, this)) { | |
break; | |
} | |
} | |
// pop cursor | |
releaseCursor(this); | |
}; | |
List.prototype.some = function(fn, context) { | |
var cursor = this.head; | |
if (context === undefined) { | |
context = this; | |
} | |
while (cursor !== null) { | |
if (fn.call(context, cursor.data, cursor, this)) { | |
return true; | |
} | |
cursor = cursor.next; | |
} | |
return false; | |
}; | |
List.prototype.map = function(fn, context) { | |
var result = new List(); | |
var cursor = this.head; | |
if (context === undefined) { | |
context = this; | |
} | |
while (cursor !== null) { | |
result.appendData(fn.call(context, cursor.data, cursor, this)); | |
cursor = cursor.next; | |
} | |
return result; | |
}; | |
List.prototype.filter = function(fn, context) { | |
var result = new List(); | |
var cursor = this.head; | |
if (context === undefined) { | |
context = this; | |
} | |
while (cursor !== null) { | |
if (fn.call(context, cursor.data, cursor, this)) { | |
result.appendData(cursor.data); | |
} | |
cursor = cursor.next; | |
} | |
return result; | |
}; | |
List.prototype.clear = function() { | |
this.head = null; | |
this.tail = null; | |
}; | |
List.prototype.copy = function() { | |
var result = new List(); | |
var cursor = this.head; | |
while (cursor !== null) { | |
result.insert(createItem(cursor.data)); | |
cursor = cursor.next; | |
} | |
return result; | |
}; | |
List.prototype.prepend = function(item) { | |
// head | |
// ^ | |
// item | |
this.updateCursors(null, item, this.head, item); | |
// insert to the beginning of the list | |
if (this.head !== null) { | |
// new item <- first item | |
this.head.prev = item; | |
// new item -> first item | |
item.next = this.head; | |
} else { | |
// if list has no head, then it also has no tail | |
// in this case tail points to the new item | |
this.tail = item; | |
} | |
// head always points to new item | |
this.head = item; | |
return this; | |
}; | |
List.prototype.prependData = function(data) { | |
return this.prepend(createItem(data)); | |
}; | |
List.prototype.append = function(item) { | |
return this.insert(item); | |
}; | |
List.prototype.appendData = function(data) { | |
return this.insert(createItem(data)); | |
}; | |
List.prototype.insert = function(item, before) { | |
if (before !== undefined && before !== null) { | |
// prev before | |
// ^ | |
// item | |
this.updateCursors(before.prev, item, before, item); | |
if (before.prev === null) { | |
// insert to the beginning of list | |
if (this.head !== before) { | |
throw new Error('before doesn\'t belong to list'); | |
} | |
// since head points to before therefore list doesn't empty | |
// no need to check tail | |
this.head = item; | |
before.prev = item; | |
item.next = before; | |
this.updateCursors(null, item); | |
} else { | |
// insert between two items | |
before.prev.next = item; | |
item.prev = before.prev; | |
before.prev = item; | |
item.next = before; | |
} | |
} else { | |
// tail | |
// ^ | |
// item | |
this.updateCursors(this.tail, item, null, item); | |
// insert to the ending of the list | |
if (this.tail !== null) { | |
// last item -> new item | |
this.tail.next = item; | |
// last item <- new item | |
item.prev = this.tail; | |
} else { | |
// if list has no tail, then it also has no head | |
// in this case head points to new item | |
this.head = item; | |
} | |
// tail always points to new item | |
this.tail = item; | |
} | |
return this; | |
}; | |
List.prototype.insertData = function(data, before) { | |
return this.insert(createItem(data), before); | |
}; | |
List.prototype.remove = function(item) { | |
// item | |
// ^ | |
// prev next | |
this.updateCursors(item, item.prev, item, item.next); | |
if (item.prev !== null) { | |
item.prev.next = item.next; | |
} else { | |
if (this.head !== item) { | |
throw new Error('item doesn\'t belong to list'); | |
} | |
this.head = item.next; | |
} | |
if (item.next !== null) { | |
item.next.prev = item.prev; | |
} else { | |
if (this.tail !== item) { | |
throw new Error('item doesn\'t belong to list'); | |
} | |
this.tail = item.prev; | |
} | |
item.prev = null; | |
item.next = null; | |
return item; | |
}; | |
List.prototype.push = function(data) { | |
this.insert(createItem(data)); | |
}; | |
List.prototype.pop = function() { | |
if (this.tail !== null) { | |
return this.remove(this.tail); | |
} | |
}; | |
List.prototype.unshift = function(data) { | |
this.prepend(createItem(data)); | |
}; | |
List.prototype.shift = function() { | |
if (this.head !== null) { | |
return this.remove(this.head); | |
} | |
}; | |
List.prototype.prependList = function(list) { | |
return this.insertList(list, this.head); | |
}; | |
List.prototype.appendList = function(list) { | |
return this.insertList(list); | |
}; | |
List.prototype.insertList = function(list, before) { | |
// ignore empty lists | |
if (list.head === null) { | |
return this; | |
} | |
if (before !== undefined && before !== null) { | |
this.updateCursors(before.prev, list.tail, before, list.head); | |
// insert in the middle of dist list | |
if (before.prev !== null) { | |
// before.prev <-> list.head | |
before.prev.next = list.head; | |
list.head.prev = before.prev; | |
} else { | |
this.head = list.head; | |
} | |
before.prev = list.tail; | |
list.tail.next = before; | |
} else { | |
this.updateCursors(this.tail, list.tail, null, list.head); | |
// insert to end of the list | |
if (this.tail !== null) { | |
// if destination list has a tail, then it also has a head, | |
// but head doesn't change | |
// dest tail -> source head | |
this.tail.next = list.head; | |
// dest tail <- source head | |
list.head.prev = this.tail; | |
} else { | |
// if list has no a tail, then it also has no a head | |
// in this case points head to new item | |
this.head = list.head; | |
} | |
// tail always start point to new item | |
this.tail = list.tail; | |
} | |
list.head = null; | |
list.tail = null; | |
return this; | |
}; | |
List.prototype.replace = function(oldItem, newItemOrList) { | |
if ('head' in newItemOrList) { | |
this.insertList(newItemOrList, oldItem); | |
} else { | |
this.insert(newItemOrList, oldItem); | |
} | |
this.remove(oldItem); | |
}; | |
module.exports = List; | |
},{}],143:[function(require,module,exports){ | |
'use strict'; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var keywords = Object.create(null); | |
var properties = Object.create(null); | |
var HYPHENMINUS = 45; // '-'.charCodeAt() | |
function isCustomProperty(str, offset) { | |
offset = offset || 0; | |
return str.length - offset >= 2 && | |
str.charCodeAt(offset) === HYPHENMINUS && | |
str.charCodeAt(offset + 1) === HYPHENMINUS; | |
} | |
function getVendorPrefix(str, offset) { | |
offset = offset || 0; | |
// verdor prefix should be at least 3 chars length | |
if (str.length - offset >= 3) { | |
// vendor prefix starts with hyper minus following non-hyper minus | |
if (str.charCodeAt(offset) === HYPHENMINUS && | |
str.charCodeAt(offset + 1) !== HYPHENMINUS) { | |
// vendor prefix should contain a hyper minus at the ending | |
var secondDashIndex = str.indexOf('-', offset + 2); | |
if (secondDashIndex !== -1) { | |
return str.substring(offset, secondDashIndex + 1); | |
} | |
} | |
} | |
return ''; | |
} | |
function getKeywordDescriptor(keyword) { | |
if (hasOwnProperty.call(keywords, keyword)) { | |
return keywords[keyword]; | |
} | |
var name = keyword.toLowerCase(); | |
if (hasOwnProperty.call(keywords, name)) { | |
return keywords[keyword] = keywords[name]; | |
} | |
var custom = isCustomProperty(name, 0); | |
var vendor = !custom ? getVendorPrefix(name, 0) : ''; | |
return keywords[keyword] = Object.freeze({ | |
basename: name.substr(vendor.length), | |
name: name, | |
vendor: vendor, | |
prefix: vendor, | |
custom: custom | |
}); | |
} | |
function getPropertyDescriptor(property) { | |
if (hasOwnProperty.call(properties, property)) { | |
return properties[property]; | |
} | |
var name = property; | |
var hack = property[0]; | |
if (hack === '/') { | |
hack = property[1] === '/' ? '//' : '/'; | |
} else if (hack !== '_' && | |
hack !== '*' && | |
hack !== '$' && | |
hack !== '#' && | |
hack !== '+') { | |
hack = ''; | |
} | |
var custom = isCustomProperty(name, hack.length); | |
// re-use result when possible (the same as for lower case) | |
if (!custom) { | |
name = name.toLowerCase(); | |
if (hasOwnProperty.call(properties, name)) { | |
return properties[property] = properties[name]; | |
} | |
} | |
var vendor = !custom ? getVendorPrefix(name, hack.length) : ''; | |
var prefix = name.substr(0, hack.length + vendor.length); | |
return properties[property] = Object.freeze({ | |
basename: name.substr(prefix.length), | |
name: name.substr(hack.length), | |
hack: hack, | |
vendor: vendor, | |
prefix: prefix, | |
custom: custom | |
}); | |
} | |
module.exports = { | |
keyword: getKeywordDescriptor, | |
property: getPropertyDescriptor, | |
isCustomProperty: isCustomProperty, | |
vendorPrefix: getVendorPrefix | |
}; | |
},{}],144:[function(require,module,exports){ | |
'use strict'; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var noop = function() {}; | |
function ensureFunction(value) { | |
return typeof value === 'function' ? value : noop; | |
} | |
function invokeForType(fn, type) { | |
return function(node, item, list) { | |
if (node.type === type) { | |
fn.call(this, node, item, list); | |
} | |
}; | |
} | |
function getWalkersFromStructure(name, nodeType) { | |
var structure = nodeType.structure; | |
var walkers = []; | |
for (var key in structure) { | |
if (hasOwnProperty.call(structure, key) === false) { | |
continue; | |
} | |
var fieldTypes = structure[key]; | |
var walker = { | |
name: key, | |
type: false, | |
nullable: false | |
}; | |
if (!Array.isArray(structure[key])) { | |
fieldTypes = [structure[key]]; | |
} | |
for (var i = 0; i < fieldTypes.length; i++) { | |
var fieldType = fieldTypes[i]; | |
if (fieldType === null) { | |
walker.nullable = true; | |
} else if (typeof fieldType === 'string') { | |
walker.type = 'node'; | |
} else if (Array.isArray(fieldType)) { | |
walker.type = 'list'; | |
} | |
} | |
if (walker.type) { | |
walkers.push(walker); | |
} | |
} | |
if (walkers.length) { | |
return { | |
context: nodeType.walkContext, | |
fields: walkers | |
}; | |
} | |
return null; | |
} | |
function getTypesFromConfig(config) { | |
var types = {}; | |
for (var name in config.node) { | |
if (hasOwnProperty.call(config.node, name)) { | |
var nodeType = config.node[name]; | |
if (!nodeType.structure) { | |
throw new Error('Missed `structure` field in `' + name + '` node type definition'); | |
} | |
types[name] = getWalkersFromStructure(name, nodeType); | |
} | |
} | |
return types; | |
} | |
function createTypeIterator(config, reverse) { | |
var fields = reverse ? config.fields.slice().reverse() : config.fields; | |
var body = fields.map(function(field) { | |
var ref = 'node.' + field.name; | |
var line; | |
if (field.type === 'list') { | |
line = reverse | |
? ref + '.forEachRight(walk);' | |
: ref + '.forEach(walk);'; | |
} else { | |
line = 'walk(' + ref + ');'; | |
} | |
if (field.nullable) { | |
line = 'if (' + ref + ') {\n ' + line + '}'; | |
} | |
return line; | |
}); | |
if (config.context) { | |
body = [].concat( | |
'var old = context.' + config.context + ';', | |
'context.' + config.context + ' = node;', | |
body, | |
'context.' + config.context + ' = old;' | |
); | |
} | |
return new Function('node', 'context', 'walk', body.join('\n')); | |
} | |
function createFastTraveralMap(iterators) { | |
return { | |
Atrule: { | |
StyleSheet: iterators.StyleSheet, | |
Atrule: iterators.Atrule, | |
Rule: iterators.Rule, | |
Block: iterators.Block | |
}, | |
Rule: { | |
StyleSheet: iterators.StyleSheet, | |
Atrule: iterators.Atrule, | |
Rule: iterators.Rule, | |
Block: iterators.Block | |
}, | |
Declaration: { | |
StyleSheet: iterators.StyleSheet, | |
Atrule: iterators.Atrule, | |
Rule: iterators.Rule, | |
Block: iterators.Block | |
} | |
}; | |
} | |
module.exports = function createWalker(config) { | |
var types = getTypesFromConfig(config); | |
var iteratorsNatural = {}; | |
var iteratorsReverse = {}; | |
for (var name in types) { | |
if (hasOwnProperty.call(types, name) && types[name] !== null) { | |
iteratorsNatural[name] = createTypeIterator(types[name], false); | |
iteratorsReverse[name] = createTypeIterator(types[name], true); | |
} | |
} | |
var fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural); | |
var fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse); | |
return function walk(root, options) { | |
function walkNode(node, item, list) { | |
enter.call(context, node, item, list); | |
if (iterators.hasOwnProperty(node.type)) { | |
iterators[node.type](node, context, walkNode); | |
} | |
leave.call(context, node, item, list); | |
} | |
var enter = noop; | |
var leave = noop; | |
var iterators = iteratorsNatural; | |
var context = { | |
root: root, | |
stylesheet: null, | |
atrule: null, | |
atrulePrelude: null, | |
rule: null, | |
selector: null, | |
block: null, | |
declaration: null, | |
function: null | |
}; | |
if (typeof options === 'function') { | |
enter = options; | |
} else if (options) { | |
enter = ensureFunction(options.enter); | |
leave = ensureFunction(options.leave); | |
if (options.reverse) { | |
iterators = iteratorsReverse; | |
} | |
if (options.visit) { | |
if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) { | |
iterators = options.reverse | |
? fastTraversalIteratorsReverse[options.visit] | |
: fastTraversalIteratorsNatural[options.visit]; | |
} else if (!types.hasOwnProperty(options.visit)) { | |
throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).join(', ') + ')'); | |
} | |
enter = invokeForType(enter, options.visit); | |
leave = invokeForType(leave, options.visit); | |
} | |
} | |
if (enter === noop && leave === noop) { | |
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function'); | |
} | |
// swap handlers in reverse mode to invert visit order | |
if (options.reverse) { | |
var tmp = enter; | |
enter = leave; | |
leave = tmp; | |
} | |
walkNode(root); | |
}; | |
}; | |
},{}],145:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var util = require('./util'); | |
var has = Object.prototype.hasOwnProperty; | |
var hasNativeMap = typeof Map !== "undefined"; | |
/** | |
* A data structure which is a combination of an array and a set. Adding a new | |
* member is O(1), testing for membership is O(1), and finding the index of an | |
* element is O(1). Removing elements from the set is not supported. Only | |
* strings are supported for membership. | |
*/ | |
function ArraySet() { | |
this._array = []; | |
this._set = hasNativeMap ? new Map() : Object.create(null); | |
} | |
/** | |
* Static method for creating ArraySet instances from an existing array. | |
*/ | |
ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { | |
var set = new ArraySet(); | |
for (var i = 0, len = aArray.length; i < len; i++) { | |
set.add(aArray[i], aAllowDuplicates); | |
} | |
return set; | |
}; | |
/** | |
* Return how many unique items are in this ArraySet. If duplicates have been | |
* added, than those do not count towards the size. | |
* | |
* @returns Number | |
*/ | |
ArraySet.prototype.size = function ArraySet_size() { | |
return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; | |
}; | |
/** | |
* Add the given string to this set. | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { | |
var sStr = hasNativeMap ? aStr : util.toSetString(aStr); | |
var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); | |
var idx = this._array.length; | |
if (!isDuplicate || aAllowDuplicates) { | |
this._array.push(aStr); | |
} | |
if (!isDuplicate) { | |
if (hasNativeMap) { | |
this._set.set(aStr, idx); | |
} else { | |
this._set[sStr] = idx; | |
} | |
} | |
}; | |
/** | |
* Is the given string a member of this set? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.has = function ArraySet_has(aStr) { | |
if (hasNativeMap) { | |
return this._set.has(aStr); | |
} else { | |
var sStr = util.toSetString(aStr); | |
return has.call(this._set, sStr); | |
} | |
}; | |
/** | |
* What is the index of the given string in the array? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { | |
if (hasNativeMap) { | |
var idx = this._set.get(aStr); | |
if (idx >= 0) { | |
return idx; | |
} | |
} else { | |
var sStr = util.toSetString(aStr); | |
if (has.call(this._set, sStr)) { | |
return this._set[sStr]; | |
} | |
} | |
throw new Error('"' + aStr + '" is not in the set.'); | |
}; | |
/** | |
* What is the element at the given index? | |
* | |
* @param Number aIdx | |
*/ | |
ArraySet.prototype.at = function ArraySet_at(aIdx) { | |
if (aIdx >= 0 && aIdx < this._array.length) { | |
return this._array[aIdx]; | |
} | |
throw new Error('No element indexed by ' + aIdx); | |
}; | |
/** | |
* Returns the array representation of this set (which has the proper indices | |
* indicated by indexOf). Note that this is a copy of the internal array used | |
* for storing the members so that no one can mess with internal state. | |
*/ | |
ArraySet.prototype.toArray = function ArraySet_toArray() { | |
return this._array.slice(); | |
}; | |
exports.ArraySet = ArraySet; | |
},{"./util":154}],146:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
* | |
* Based on the Base 64 VLQ implementation in Closure Compiler: | |
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java | |
* | |
* Copyright 2011 The Closure Compiler Authors. All rights reserved. | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* * Redistributions in binary form must reproduce the above | |
* copyright notice, this list of conditions and the following | |
* disclaimer in the documentation and/or other materials provided | |
* with the distribution. | |
* * Neither the name of Google Inc. nor the names of its | |
* contributors may be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
var base64 = require('./base64'); | |
// A single base 64 digit can contain 6 bits of data. For the base 64 variable | |
// length quantities we use in the source map spec, the first bit is the sign, | |
// the next four bits are the actual value, and the 6th bit is the | |
// continuation bit. The continuation bit tells us whether there are more | |
// digits in this value following this digit. | |
// | |
// Continuation | |
// | Sign | |
// | | | |
// V V | |
// 101011 | |
var VLQ_BASE_SHIFT = 5; | |
// binary: 100000 | |
var VLQ_BASE = 1 << VLQ_BASE_SHIFT; | |
// binary: 011111 | |
var VLQ_BASE_MASK = VLQ_BASE - 1; | |
// binary: 100000 | |
var VLQ_CONTINUATION_BIT = VLQ_BASE; | |
/** | |
* Converts from a two-complement value to a value where the sign bit is | |
* placed in the least significant bit. For example, as decimals: | |
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) | |
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) | |
*/ | |
function toVLQSigned(aValue) { | |
return aValue < 0 | |
? ((-aValue) << 1) + 1 | |
: (aValue << 1) + 0; | |
} | |
/** | |
* Converts to a two-complement value from a value where the sign bit is | |
* placed in the least significant bit. For example, as decimals: | |
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 | |
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 | |
*/ | |
function fromVLQSigned(aValue) { | |
var isNegative = (aValue & 1) === 1; | |
var shifted = aValue >> 1; | |
return isNegative | |
? -shifted | |
: shifted; | |
} | |
/** | |
* Returns the base 64 VLQ encoded value. | |
*/ | |
exports.encode = function base64VLQ_encode(aValue) { | |
var encoded = ""; | |
var digit; | |
var vlq = toVLQSigned(aValue); | |
do { | |
digit = vlq & VLQ_BASE_MASK; | |
vlq >>>= VLQ_BASE_SHIFT; | |
if (vlq > 0) { | |
// There are still more digits in this value, so we must make sure the | |
// continuation bit is marked. | |
digit |= VLQ_CONTINUATION_BIT; | |
} | |
encoded += base64.encode(digit); | |
} while (vlq > 0); | |
return encoded; | |
}; | |
/** | |
* Decodes the next base 64 VLQ value from the given string and returns the | |
* value and the rest of the string via the out parameter. | |
*/ | |
exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { | |
var strLen = aStr.length; | |
var result = 0; | |
var shift = 0; | |
var continuation, digit; | |
do { | |
if (aIndex >= strLen) { | |
throw new Error("Expected more digits in base 64 VLQ value."); | |
} | |
digit = base64.decode(aStr.charCodeAt(aIndex++)); | |
if (digit === -1) { | |
throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); | |
} | |
continuation = !!(digit & VLQ_CONTINUATION_BIT); | |
digit &= VLQ_BASE_MASK; | |
result = result + (digit << shift); | |
shift += VLQ_BASE_SHIFT; | |
} while (continuation); | |
aOutParam.value = fromVLQSigned(result); | |
aOutParam.rest = aIndex; | |
}; | |
},{"./base64":147}],147:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); | |
/** | |
* Encode an integer in the range of 0 to 63 to a single base 64 digit. | |
*/ | |
exports.encode = function (number) { | |
if (0 <= number && number < intToCharMap.length) { | |
return intToCharMap[number]; | |
} | |
throw new TypeError("Must be between 0 and 63: " + number); | |
}; | |
/** | |
* Decode a single base 64 character code digit to an integer. Returns -1 on | |
* failure. | |
*/ | |
exports.decode = function (charCode) { | |
var bigA = 65; // 'A' | |
var bigZ = 90; // 'Z' | |
var littleA = 97; // 'a' | |
var littleZ = 122; // 'z' | |
var zero = 48; // '0' | |
var nine = 57; // '9' | |
var plus = 43; // '+' | |
var slash = 47; // '/' | |
var littleOffset = 26; | |
var numberOffset = 52; | |
// 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ | |
if (bigA <= charCode && charCode <= bigZ) { | |
return (charCode - bigA); | |
} | |
// 26 - 51: abcdefghijklmnopqrstuvwxyz | |
if (littleA <= charCode && charCode <= littleZ) { | |
return (charCode - littleA + littleOffset); | |
} | |
// 52 - 61: 0123456789 | |
if (zero <= charCode && charCode <= nine) { | |
return (charCode - zero + numberOffset); | |
} | |
// 62: + | |
if (charCode == plus) { | |
return 62; | |
} | |
// 63: / | |
if (charCode == slash) { | |
return 63; | |
} | |
// Invalid base64 digit. | |
return -1; | |
}; | |
},{}],148:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
exports.GREATEST_LOWER_BOUND = 1; | |
exports.LEAST_UPPER_BOUND = 2; | |
/** | |
* Recursive implementation of binary search. | |
* | |
* @param aLow Indices here and lower do not contain the needle. | |
* @param aHigh Indices here and higher do not contain the needle. | |
* @param aNeedle The element being searched for. | |
* @param aHaystack The non-empty array being searched. | |
* @param aCompare Function which takes two elements and returns -1, 0, or 1. | |
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or | |
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the | |
* closest element that is smaller than or greater than the one we are | |
* searching for, respectively, if the exact element cannot be found. | |
*/ | |
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { | |
// This function terminates when one of the following is true: | |
// | |
// 1. We find the exact element we are looking for. | |
// | |
// 2. We did not find the exact element, but we can return the index of | |
// the next-closest element. | |
// | |
// 3. We did not find the exact element, and there is no next-closest | |
// element than the one we are searching for, so we return -1. | |
var mid = Math.floor((aHigh - aLow) / 2) + aLow; | |
var cmp = aCompare(aNeedle, aHaystack[mid], true); | |
if (cmp === 0) { | |
// Found the element we are looking for. | |
return mid; | |
} | |
else if (cmp > 0) { | |
// Our needle is greater than aHaystack[mid]. | |
if (aHigh - mid > 1) { | |
// The element is in the upper half. | |
return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); | |
} | |
// The exact needle element was not found in this haystack. Determine if | |
// we are in termination case (3) or (2) and return the appropriate thing. | |
if (aBias == exports.LEAST_UPPER_BOUND) { | |
return aHigh < aHaystack.length ? aHigh : -1; | |
} else { | |
return mid; | |
} | |
} | |
else { | |
// Our needle is less than aHaystack[mid]. | |
if (mid - aLow > 1) { | |
// The element is in the lower half. | |
return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); | |
} | |
// we are in termination case (3) or (2) and return the appropriate thing. | |
if (aBias == exports.LEAST_UPPER_BOUND) { | |
return mid; | |
} else { | |
return aLow < 0 ? -1 : aLow; | |
} | |
} | |
} | |
/** | |
* This is an implementation of binary search which will always try and return | |
* the index of the closest element if there is no exact hit. This is because | |
* mappings between original and generated line/col pairs are single points, | |
* and there is an implicit region between each of them, so a miss just means | |
* that you aren't on the very start of a region. | |
* | |
* @param aNeedle The element you are looking for. | |
* @param aHaystack The array that is being searched. | |
* @param aCompare A function which takes the needle and an element in the | |
* array and returns -1, 0, or 1 depending on whether the needle is less | |
* than, equal to, or greater than the element, respectively. | |
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or | |
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the | |
* closest element that is smaller than or greater than the one we are | |
* searching for, respectively, if the exact element cannot be found. | |
* Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. | |
*/ | |
exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { | |
if (aHaystack.length === 0) { | |
return -1; | |
} | |
var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, | |
aCompare, aBias || exports.GREATEST_LOWER_BOUND); | |
if (index < 0) { | |
return -1; | |
} | |
// We have found either the exact element, or the next-closest element than | |
// the one we are searching for. However, there may be more than one such | |
// element. Make sure we always return the smallest of these. | |
while (index - 1 >= 0) { | |
if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { | |
break; | |
} | |
--index; | |
} | |
return index; | |
}; | |
},{}],149:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2014 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var util = require('./util'); | |
/** | |
* Determine whether mappingB is after mappingA with respect to generated | |
* position. | |
*/ | |
function generatedPositionAfter(mappingA, mappingB) { | |
// Optimized for most common case | |
var lineA = mappingA.generatedLine; | |
var lineB = mappingB.generatedLine; | |
var columnA = mappingA.generatedColumn; | |
var columnB = mappingB.generatedColumn; | |
return lineB > lineA || lineB == lineA && columnB >= columnA || | |
util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; | |
} | |
/** | |
* A data structure to provide a sorted view of accumulated mappings in a | |
* performance conscious manner. It trades a neglibable overhead in general | |
* case for a large speedup in case of mappings being added in order. | |
*/ | |
function MappingList() { | |
this._array = []; | |
this._sorted = true; | |
// Serves as infimum | |
this._last = {generatedLine: -1, generatedColumn: 0}; | |
} | |
/** | |
* Iterate through internal items. This method takes the same arguments that | |
* `Array.prototype.forEach` takes. | |
* | |
* NOTE: The order of the mappings is NOT guaranteed. | |
*/ | |
MappingList.prototype.unsortedForEach = | |
function MappingList_forEach(aCallback, aThisArg) { | |
this._array.forEach(aCallback, aThisArg); | |
}; | |
/** | |
* Add the given source mapping. | |
* | |
* @param Object aMapping | |
*/ | |
MappingList.prototype.add = function MappingList_add(aMapping) { | |
if (generatedPositionAfter(this._last, aMapping)) { | |
this._last = aMapping; | |
this._array.push(aMapping); | |
} else { | |
this._sorted = false; | |
this._array.push(aMapping); | |
} | |
}; | |
/** | |
* Returns the flat, sorted array of mappings. The mappings are sorted by | |
* generated position. | |
* | |
* WARNING: This method returns internal data without copying, for | |
* performance. The return value must NOT be mutated, and should be treated as | |
* an immutable borrow. If you want to take ownership, you must make your own | |
* copy. | |
*/ | |
MappingList.prototype.toArray = function MappingList_toArray() { | |
if (!this._sorted) { | |
this._array.sort(util.compareByGeneratedPositionsInflated); | |
this._sorted = true; | |
} | |
return this._array; | |
}; | |
exports.MappingList = MappingList; | |
},{"./util":154}],150:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
// It turns out that some (most?) JavaScript engines don't self-host | |
// `Array.prototype.sort`. This makes sense because C++ will likely remain | |
// faster than JS when doing raw CPU-intensive sorting. However, when using a | |
// custom comparator function, calling back and forth between the VM's C++ and | |
// JIT'd JS is rather slow *and* loses JIT type information, resulting in | |
// worse generated code for the comparator function than would be optimal. In | |
// fact, when sorting with a comparator, these costs outweigh the benefits of | |
// sorting in C++. By using our own JS-implemented Quick Sort (below), we get | |
// a ~3500ms mean speed-up in `bench/bench.html`. | |
/** | |
* Swap the elements indexed by `x` and `y` in the array `ary`. | |
* | |
* @param {Array} ary | |
* The array. | |
* @param {Number} x | |
* The index of the first item. | |
* @param {Number} y | |
* The index of the second item. | |
*/ | |
function swap(ary, x, y) { | |
var temp = ary[x]; | |
ary[x] = ary[y]; | |
ary[y] = temp; | |
} | |
/** | |
* Returns a random integer within the range `low .. high` inclusive. | |
* | |
* @param {Number} low | |
* The lower bound on the range. | |
* @param {Number} high | |
* The upper bound on the range. | |
*/ | |
function randomIntInRange(low, high) { | |
return Math.round(low + (Math.random() * (high - low))); | |
} | |
/** | |
* The Quick Sort algorithm. | |
* | |
* @param {Array} ary | |
* An array to sort. | |
* @param {function} comparator | |
* Function to use to compare two items. | |
* @param {Number} p | |
* Start index of the array | |
* @param {Number} r | |
* End index of the array | |
*/ | |
function doQuickSort(ary, comparator, p, r) { | |
// If our lower bound is less than our upper bound, we (1) partition the | |
// array into two pieces and (2) recurse on each half. If it is not, this is | |
// the empty array and our base case. | |
if (p < r) { | |
// (1) Partitioning. | |
// | |
// The partitioning chooses a pivot between `p` and `r` and moves all | |
// elements that are less than or equal to the pivot to the before it, and | |
// all the elements that are greater than it after it. The effect is that | |
// once partition is done, the pivot is in the exact place it will be when | |
// the array is put in sorted order, and it will not need to be moved | |
// again. This runs in O(n) time. | |
// Always choose a random pivot so that an input array which is reverse | |
// sorted does not cause O(n^2) running time. | |
var pivotIndex = randomIntInRange(p, r); | |
var i = p - 1; | |
swap(ary, pivotIndex, r); | |
var pivot = ary[r]; | |
// Immediately after `j` is incremented in this loop, the following hold | |
// true: | |
// | |
// * Every element in `ary[p .. i]` is less than or equal to the pivot. | |
// | |
// * Every element in `ary[i+1 .. j-1]` is greater than the pivot. | |
for (var j = p; j < r; j++) { | |
if (comparator(ary[j], pivot) <= 0) { | |
i += 1; | |
swap(ary, i, j); | |
} | |
} | |
swap(ary, i + 1, j); | |
var q = i + 1; | |
// (2) Recurse on each half. | |
doQuickSort(ary, comparator, p, q - 1); | |
doQuickSort(ary, comparator, q + 1, r); | |
} | |
} | |
/** | |
* Sort the given array in-place with the given comparator function. | |
* | |
* @param {Array} ary | |
* An array to sort. | |
* @param {function} comparator | |
* Function to use to compare two items. | |
*/ | |
exports.quickSort = function (ary, comparator) { | |
doQuickSort(ary, comparator, 0, ary.length - 1); | |
}; | |
},{}],151:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var util = require('./util'); | |
var binarySearch = require('./binary-search'); | |
var ArraySet = require('./array-set').ArraySet; | |
var base64VLQ = require('./base64-vlq'); | |
var quickSort = require('./quick-sort').quickSort; | |
function SourceMapConsumer(aSourceMap) { | |
var sourceMap = aSourceMap; | |
if (typeof aSourceMap === 'string') { | |
sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); | |
} | |
return sourceMap.sections != null | |
? new IndexedSourceMapConsumer(sourceMap) | |
: new BasicSourceMapConsumer(sourceMap); | |
} | |
SourceMapConsumer.fromSourceMap = function(aSourceMap) { | |
return BasicSourceMapConsumer.fromSourceMap(aSourceMap); | |
} | |
/** | |
* The version of the source mapping spec that we are consuming. | |
*/ | |
SourceMapConsumer.prototype._version = 3; | |
// `__generatedMappings` and `__originalMappings` are arrays that hold the | |
// parsed mapping coordinates from the source map's "mappings" attribute. They | |
// are lazily instantiated, accessed via the `_generatedMappings` and | |
// `_originalMappings` getters respectively, and we only parse the mappings | |
// and create these arrays once queried for a source location. We jump through | |
// these hoops because there can be many thousands of mappings, and parsing | |
// them is expensive, so we only want to do it if we must. | |
// | |
// Each object in the arrays is of the form: | |
// | |
// { | |
// generatedLine: The line number in the generated code, | |
// generatedColumn: The column number in the generated code, | |
// source: The path to the original source file that generated this | |
// chunk of code, | |
// originalLine: The line number in the original source that | |
// corresponds to this chunk of generated code, | |
// originalColumn: The column number in the original source that | |
// corresponds to this chunk of generated code, | |
// name: The name of the original symbol which generated this chunk of | |
// code. | |
// } | |
// | |
// All properties except for `generatedLine` and `generatedColumn` can be | |
// `null`. | |
// | |
// `_generatedMappings` is ordered by the generated positions. | |
// | |
// `_originalMappings` is ordered by the original positions. | |
SourceMapConsumer.prototype.__generatedMappings = null; | |
Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { | |
get: function () { | |
if (!this.__generatedMappings) { | |
this._parseMappings(this._mappings, this.sourceRoot); | |
} | |
return this.__generatedMappings; | |
} | |
}); | |
SourceMapConsumer.prototype.__originalMappings = null; | |
Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { | |
get: function () { | |
if (!this.__originalMappings) { | |
this._parseMappings(this._mappings, this.sourceRoot); | |
} | |
return this.__originalMappings; | |
} | |
}); | |
SourceMapConsumer.prototype._charIsMappingSeparator = | |
function SourceMapConsumer_charIsMappingSeparator(aStr, index) { | |
var c = aStr.charAt(index); | |
return c === ";" || c === ","; | |
}; | |
/** | |
* Parse the mappings in a string in to a data structure which we can easily | |
* query (the ordered arrays in the `this.__generatedMappings` and | |
* `this.__originalMappings` properties). | |
*/ | |
SourceMapConsumer.prototype._parseMappings = | |
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { | |
throw new Error("Subclasses must implement _parseMappings"); | |
}; | |
SourceMapConsumer.GENERATED_ORDER = 1; | |
SourceMapConsumer.ORIGINAL_ORDER = 2; | |
SourceMapConsumer.GREATEST_LOWER_BOUND = 1; | |
SourceMapConsumer.LEAST_UPPER_BOUND = 2; | |
/** | |
* Iterate over each mapping between an original source/line/column and a | |
* generated line/column in this source map. | |
* | |
* @param Function aCallback | |
* The function that is called with each mapping. | |
* @param Object aContext | |
* Optional. If specified, this object will be the value of `this` every | |
* time that `aCallback` is called. | |
* @param aOrder | |
* Either `SourceMapConsumer.GENERATED_ORDER` or | |
* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to | |
* iterate over the mappings sorted by the generated file's line/column | |
* order or the original's source/line/column order, respectively. Defaults to | |
* `SourceMapConsumer.GENERATED_ORDER`. | |
*/ | |
SourceMapConsumer.prototype.eachMapping = | |
function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { | |
var context = aContext || null; | |
var order = aOrder || SourceMapConsumer.GENERATED_ORDER; | |
var mappings; | |
switch (order) { | |
case SourceMapConsumer.GENERATED_ORDER: | |
mappings = this._generatedMappings; | |
break; | |
case SourceMapConsumer.ORIGINAL_ORDER: | |
mappings = this._originalMappings; | |
break; | |
default: | |
throw new Error("Unknown order of iteration."); | |
} | |
var sourceRoot = this.sourceRoot; | |
mappings.map(function (mapping) { | |
var source = mapping.source === null ? null : this._sources.at(mapping.source); | |
if (source != null && sourceRoot != null) { | |
source = util.join(sourceRoot, source); | |
} | |
return { | |
source: source, | |
generatedLine: mapping.generatedLine, | |
generatedColumn: mapping.generatedColumn, | |
originalLine: mapping.originalLine, | |
originalColumn: mapping.originalColumn, | |
name: mapping.name === null ? null : this._names.at(mapping.name) | |
}; | |
}, this).forEach(aCallback, context); | |
}; | |
/** | |
* Returns all generated line and column information for the original source, | |
* line, and column provided. If no column is provided, returns all mappings | |
* corresponding to a either the line we are searching for or the next | |
* closest line that has any mappings. Otherwise, returns all mappings | |
* corresponding to the given line and either the column we are searching for | |
* or the next closest column that has any offsets. | |
* | |
* The only argument is an object with the following properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* - column: Optional. the column number in the original source. | |
* | |
* and an array of objects is returned, each with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
SourceMapConsumer.prototype.allGeneratedPositionsFor = | |
function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { | |
var line = util.getArg(aArgs, 'line'); | |
// When there is no exact match, BasicSourceMapConsumer.prototype._findMapping | |
// returns the index of the closest mapping less than the needle. By | |
// setting needle.originalColumn to 0, we thus find the last mapping for | |
// the given line, provided such a mapping exists. | |
var needle = { | |
source: util.getArg(aArgs, 'source'), | |
originalLine: line, | |
originalColumn: util.getArg(aArgs, 'column', 0) | |
}; | |
if (this.sourceRoot != null) { | |
needle.source = util.relative(this.sourceRoot, needle.source); | |
} | |
if (!this._sources.has(needle.source)) { | |
return []; | |
} | |
needle.source = this._sources.indexOf(needle.source); | |
var mappings = []; | |
var index = this._findMapping(needle, | |
this._originalMappings, | |
"originalLine", | |
"originalColumn", | |
util.compareByOriginalPositions, | |
binarySearch.LEAST_UPPER_BOUND); | |
if (index >= 0) { | |
var mapping = this._originalMappings[index]; | |
if (aArgs.column === undefined) { | |
var originalLine = mapping.originalLine; | |
// Iterate until either we run out of mappings, or we run into | |
// a mapping for a different line than the one we found. Since | |
// mappings are sorted, this is guaranteed to find all mappings for | |
// the line we found. | |
while (mapping && mapping.originalLine === originalLine) { | |
mappings.push({ | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null), | |
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) | |
}); | |
mapping = this._originalMappings[++index]; | |
} | |
} else { | |
var originalColumn = mapping.originalColumn; | |
// Iterate until either we run out of mappings, or we run into | |
// a mapping for a different line than the one we were searching for. | |
// Since mappings are sorted, this is guaranteed to find all mappings for | |
// the line we are searching for. | |
while (mapping && | |
mapping.originalLine === line && | |
mapping.originalColumn == originalColumn) { | |
mappings.push({ | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null), | |
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) | |
}); | |
mapping = this._originalMappings[++index]; | |
} | |
} | |
} | |
return mappings; | |
}; | |
exports.SourceMapConsumer = SourceMapConsumer; | |
/** | |
* A BasicSourceMapConsumer instance represents a parsed source map which we can | |
* query for information about the original file positions by giving it a file | |
* position in the generated source. | |
* | |
* The only parameter is the raw source map (either as a JSON string, or | |
* already parsed to an object). According to the spec, source maps have the | |
* following attributes: | |
* | |
* - version: Which version of the source map spec this map is following. | |
* - sources: An array of URLs to the original source files. | |
* - names: An array of identifiers which can be referrenced by individual mappings. | |
* - sourceRoot: Optional. The URL root from which all sources are relative. | |
* - sourcesContent: Optional. An array of contents of the original source files. | |
* - mappings: A string of base64 VLQs which contain the actual mappings. | |
* - file: Optional. The generated file this source map is associated with. | |
* | |
* Here is an example source map, taken from the source map spec[0]: | |
* | |
* { | |
* version : 3, | |
* file: "out.js", | |
* sourceRoot : "", | |
* sources: ["foo.js", "bar.js"], | |
* names: ["src", "maps", "are", "fun"], | |
* mappings: "AA,AB;;ABCDE;" | |
* } | |
* | |
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# | |
*/ | |
function BasicSourceMapConsumer(aSourceMap) { | |
var sourceMap = aSourceMap; | |
if (typeof aSourceMap === 'string') { | |
sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); | |
} | |
var version = util.getArg(sourceMap, 'version'); | |
var sources = util.getArg(sourceMap, 'sources'); | |
// Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which | |
// requires the array) to play nice here. | |
var names = util.getArg(sourceMap, 'names', []); | |
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); | |
var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); | |
var mappings = util.getArg(sourceMap, 'mappings'); | |
var file = util.getArg(sourceMap, 'file', null); | |
// Once again, Sass deviates from the spec and supplies the version as a | |
// string rather than a number, so we use loose equality checking here. | |
if (version != this._version) { | |
throw new Error('Unsupported version: ' + version); | |
} | |
sources = sources | |
.map(String) | |
// Some source maps produce relative source paths like "./foo.js" instead of | |
// "foo.js". Normalize these first so that future comparisons will succeed. | |
// See bugzil.la/1090768. | |
.map(util.normalize) | |
// Always ensure that absolute sources are internally stored relative to | |
// the source root, if the source root is absolute. Not doing this would | |
// be particularly problematic when the source root is a prefix of the | |
// source (valid, but why??). See github issue #199 and bugzil.la/1188982. | |
.map(function (source) { | |
return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) | |
? util.relative(sourceRoot, source) | |
: source; | |
}); | |
// Pass `true` below to allow duplicate names and sources. While source maps | |
// are intended to be compressed and deduplicated, the TypeScript compiler | |
// sometimes generates source maps with duplicates in them. See Github issue | |
// #72 and bugzil.la/889492. | |
this._names = ArraySet.fromArray(names.map(String), true); | |
this._sources = ArraySet.fromArray(sources, true); | |
this.sourceRoot = sourceRoot; | |
this.sourcesContent = sourcesContent; | |
this._mappings = mappings; | |
this.file = file; | |
} | |
BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); | |
BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; | |
/** | |
* Create a BasicSourceMapConsumer from a SourceMapGenerator. | |
* | |
* @param SourceMapGenerator aSourceMap | |
* The source map that will be consumed. | |
* @returns BasicSourceMapConsumer | |
*/ | |
BasicSourceMapConsumer.fromSourceMap = | |
function SourceMapConsumer_fromSourceMap(aSourceMap) { | |
var smc = Object.create(BasicSourceMapConsumer.prototype); | |
var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); | |
var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); | |
smc.sourceRoot = aSourceMap._sourceRoot; | |
smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), | |
smc.sourceRoot); | |
smc.file = aSourceMap._file; | |
// Because we are modifying the entries (by converting string sources and | |
// names to indices into the sources and names ArraySets), we have to make | |
// a copy of the entry or else bad things happen. Shared mutable state | |
// strikes again! See github issue #191. | |
var generatedMappings = aSourceMap._mappings.toArray().slice(); | |
var destGeneratedMappings = smc.__generatedMappings = []; | |
var destOriginalMappings = smc.__originalMappings = []; | |
for (var i = 0, length = generatedMappings.length; i < length; i++) { | |
var srcMapping = generatedMappings[i]; | |
var destMapping = new Mapping; | |
destMapping.generatedLine = srcMapping.generatedLine; | |
destMapping.generatedColumn = srcMapping.generatedColumn; | |
if (srcMapping.source) { | |
destMapping.source = sources.indexOf(srcMapping.source); | |
destMapping.originalLine = srcMapping.originalLine; | |
destMapping.originalColumn = srcMapping.originalColumn; | |
if (srcMapping.name) { | |
destMapping.name = names.indexOf(srcMapping.name); | |
} | |
destOriginalMappings.push(destMapping); | |
} | |
destGeneratedMappings.push(destMapping); | |
} | |
quickSort(smc.__originalMappings, util.compareByOriginalPositions); | |
return smc; | |
}; | |
/** | |
* The version of the source mapping spec that we are consuming. | |
*/ | |
BasicSourceMapConsumer.prototype._version = 3; | |
/** | |
* The list of original sources. | |
*/ | |
Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { | |
get: function () { | |
return this._sources.toArray().map(function (s) { | |
return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; | |
}, this); | |
} | |
}); | |
/** | |
* Provide the JIT with a nice shape / hidden class. | |
*/ | |
function Mapping() { | |
this.generatedLine = 0; | |
this.generatedColumn = 0; | |
this.source = null; | |
this.originalLine = null; | |
this.originalColumn = null; | |
this.name = null; | |
} | |
/** | |
* Parse the mappings in a string in to a data structure which we can easily | |
* query (the ordered arrays in the `this.__generatedMappings` and | |
* `this.__originalMappings` properties). | |
*/ | |
BasicSourceMapConsumer.prototype._parseMappings = | |
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { | |
var generatedLine = 1; | |
var previousGeneratedColumn = 0; | |
var previousOriginalLine = 0; | |
var previousOriginalColumn = 0; | |
var previousSource = 0; | |
var previousName = 0; | |
var length = aStr.length; | |
var index = 0; | |
var cachedSegments = {}; | |
var temp = {}; | |
var originalMappings = []; | |
var generatedMappings = []; | |
var mapping, str, segment, end, value; | |
while (index < length) { | |
if (aStr.charAt(index) === ';') { | |
generatedLine++; | |
index++; | |
previousGeneratedColumn = 0; | |
} | |
else if (aStr.charAt(index) === ',') { | |
index++; | |
} | |
else { | |
mapping = new Mapping(); | |
mapping.generatedLine = generatedLine; | |
// Because each offset is encoded relative to the previous one, | |
// many segments often have the same encoding. We can exploit this | |
// fact by caching the parsed variable length fields of each segment, | |
// allowing us to avoid a second parse if we encounter the same | |
// segment again. | |
for (end = index; end < length; end++) { | |
if (this._charIsMappingSeparator(aStr, end)) { | |
break; | |
} | |
} | |
str = aStr.slice(index, end); | |
segment = cachedSegments[str]; | |
if (segment) { | |
index += str.length; | |
} else { | |
segment = []; | |
while (index < end) { | |
base64VLQ.decode(aStr, index, temp); | |
value = temp.value; | |
index = temp.rest; | |
segment.push(value); | |
} | |
if (segment.length === 2) { | |
throw new Error('Found a source, but no line and column'); | |
} | |
if (segment.length === 3) { | |
throw new Error('Found a source and line, but no column'); | |
} | |
cachedSegments[str] = segment; | |
} | |
// Generated column. | |
mapping.generatedColumn = previousGeneratedColumn + segment[0]; | |
previousGeneratedColumn = mapping.generatedColumn; | |
if (segment.length > 1) { | |
// Original source. | |
mapping.source = previousSource + segment[1]; | |
previousSource += segment[1]; | |
// Original line. | |
mapping.originalLine = previousOriginalLine + segment[2]; | |
previousOriginalLine = mapping.originalLine; | |
// Lines are stored 0-based | |
mapping.originalLine += 1; | |
// Original column. | |
mapping.originalColumn = previousOriginalColumn + segment[3]; | |
previousOriginalColumn = mapping.originalColumn; | |
if (segment.length > 4) { | |
// Original name. | |
mapping.name = previousName + segment[4]; | |
previousName += segment[4]; | |
} | |
} | |
generatedMappings.push(mapping); | |
if (typeof mapping.originalLine === 'number') { | |
originalMappings.push(mapping); | |
} | |
} | |
} | |
quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); | |
this.__generatedMappings = generatedMappings; | |
quickSort(originalMappings, util.compareByOriginalPositions); | |
this.__originalMappings = originalMappings; | |
}; | |
/** | |
* Find the mapping that best matches the hypothetical "needle" mapping that | |
* we are searching for in the given "haystack" of mappings. | |
*/ | |
BasicSourceMapConsumer.prototype._findMapping = | |
function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, | |
aColumnName, aComparator, aBias) { | |
// To return the position we are searching for, we must first find the | |
// mapping for the given position and then return the opposite position it | |
// points to. Because the mappings are sorted, we can use binary search to | |
// find the best mapping. | |
if (aNeedle[aLineName] <= 0) { | |
throw new TypeError('Line must be greater than or equal to 1, got ' | |
+ aNeedle[aLineName]); | |
} | |
if (aNeedle[aColumnName] < 0) { | |
throw new TypeError('Column must be greater than or equal to 0, got ' | |
+ aNeedle[aColumnName]); | |
} | |
return binarySearch.search(aNeedle, aMappings, aComparator, aBias); | |
}; | |
/** | |
* Compute the last column for each generated mapping. The last column is | |
* inclusive. | |
*/ | |
BasicSourceMapConsumer.prototype.computeColumnSpans = | |
function SourceMapConsumer_computeColumnSpans() { | |
for (var index = 0; index < this._generatedMappings.length; ++index) { | |
var mapping = this._generatedMappings[index]; | |
// Mappings do not contain a field for the last generated columnt. We | |
// can come up with an optimistic estimate, however, by assuming that | |
// mappings are contiguous (i.e. given two consecutive mappings, the | |
// first mapping ends where the second one starts). | |
if (index + 1 < this._generatedMappings.length) { | |
var nextMapping = this._generatedMappings[index + 1]; | |
if (mapping.generatedLine === nextMapping.generatedLine) { | |
mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; | |
continue; | |
} | |
} | |
// The last mapping for each line spans the entire line. | |
mapping.lastGeneratedColumn = Infinity; | |
} | |
}; | |
/** | |
* Returns the original source, line, and column information for the generated | |
* source's line and column positions provided. The only argument is an object | |
* with the following properties: | |
* | |
* - line: The line number in the generated source. | |
* - column: The column number in the generated source. | |
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or | |
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the | |
* closest element that is smaller than or greater than the one we are | |
* searching for, respectively, if the exact element cannot be found. | |
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - source: The original source file, or null. | |
* - line: The line number in the original source, or null. | |
* - column: The column number in the original source, or null. | |
* - name: The original identifier, or null. | |
*/ | |
BasicSourceMapConsumer.prototype.originalPositionFor = | |
function SourceMapConsumer_originalPositionFor(aArgs) { | |
var needle = { | |
generatedLine: util.getArg(aArgs, 'line'), | |
generatedColumn: util.getArg(aArgs, 'column') | |
}; | |
var index = this._findMapping( | |
needle, | |
this._generatedMappings, | |
"generatedLine", | |
"generatedColumn", | |
util.compareByGeneratedPositionsDeflated, | |
util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) | |
); | |
if (index >= 0) { | |
var mapping = this._generatedMappings[index]; | |
if (mapping.generatedLine === needle.generatedLine) { | |
var source = util.getArg(mapping, 'source', null); | |
if (source !== null) { | |
source = this._sources.at(source); | |
if (this.sourceRoot != null) { | |
source = util.join(this.sourceRoot, source); | |
} | |
} | |
var name = util.getArg(mapping, 'name', null); | |
if (name !== null) { | |
name = this._names.at(name); | |
} | |
return { | |
source: source, | |
line: util.getArg(mapping, 'originalLine', null), | |
column: util.getArg(mapping, 'originalColumn', null), | |
name: name | |
}; | |
} | |
} | |
return { | |
source: null, | |
line: null, | |
column: null, | |
name: null | |
}; | |
}; | |
/** | |
* Return true if we have the source content for every source in the source | |
* map, false otherwise. | |
*/ | |
BasicSourceMapConsumer.prototype.hasContentsOfAllSources = | |
function BasicSourceMapConsumer_hasContentsOfAllSources() { | |
if (!this.sourcesContent) { | |
return false; | |
} | |
return this.sourcesContent.length >= this._sources.size() && | |
!this.sourcesContent.some(function (sc) { return sc == null; }); | |
}; | |
/** | |
* Returns the original source content. The only argument is the url of the | |
* original source file. Returns null if no original source content is | |
* available. | |
*/ | |
BasicSourceMapConsumer.prototype.sourceContentFor = | |
function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { | |
if (!this.sourcesContent) { | |
return null; | |
} | |
if (this.sourceRoot != null) { | |
aSource = util.relative(this.sourceRoot, aSource); | |
} | |
if (this._sources.has(aSource)) { | |
return this.sourcesContent[this._sources.indexOf(aSource)]; | |
} | |
var url; | |
if (this.sourceRoot != null | |
&& (url = util.urlParse(this.sourceRoot))) { | |
// XXX: file:// URIs and absolute paths lead to unexpected behavior for | |
// many users. We can help them out when they expect file:// URIs to | |
// behave like it would if they were running a local HTTP server. See | |
// https://bugzilla.mozilla.org/show_bug.cgi?id=885597. | |
var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); | |
if (url.scheme == "file" | |
&& this._sources.has(fileUriAbsPath)) { | |
return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] | |
} | |
if ((!url.path || url.path == "/") | |
&& this._sources.has("/" + aSource)) { | |
return this.sourcesContent[this._sources.indexOf("/" + aSource)]; | |
} | |
} | |
// This function is used recursively from | |
// IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we | |
// don't want to throw if we can't find the source - we just want to | |
// return null, so we provide a flag to exit gracefully. | |
if (nullOnMissing) { | |
return null; | |
} | |
else { | |
throw new Error('"' + aSource + '" is not in the SourceMap.'); | |
} | |
}; | |
/** | |
* Returns the generated line and column information for the original source, | |
* line, and column positions provided. The only argument is an object with | |
* the following properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* - column: The column number in the original source. | |
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or | |
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the | |
* closest element that is smaller than or greater than the one we are | |
* searching for, respectively, if the exact element cannot be found. | |
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
BasicSourceMapConsumer.prototype.generatedPositionFor = | |
function SourceMapConsumer_generatedPositionFor(aArgs) { | |
var source = util.getArg(aArgs, 'source'); | |
if (this.sourceRoot != null) { | |
source = util.relative(this.sourceRoot, source); | |
} | |
if (!this._sources.has(source)) { | |
return { | |
line: null, | |
column: null, | |
lastColumn: null | |
}; | |
} | |
source = this._sources.indexOf(source); | |
var needle = { | |
source: source, | |
originalLine: util.getArg(aArgs, 'line'), | |
originalColumn: util.getArg(aArgs, 'column') | |
}; | |
var index = this._findMapping( | |
needle, | |
this._originalMappings, | |
"originalLine", | |
"originalColumn", | |
util.compareByOriginalPositions, | |
util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) | |
); | |
if (index >= 0) { | |
var mapping = this._originalMappings[index]; | |
if (mapping.source === needle.source) { | |
return { | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null), | |
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) | |
}; | |
} | |
} | |
return { | |
line: null, | |
column: null, | |
lastColumn: null | |
}; | |
}; | |
exports.BasicSourceMapConsumer = BasicSourceMapConsumer; | |
/** | |
* An IndexedSourceMapConsumer instance represents a parsed source map which | |
* we can query for information. It differs from BasicSourceMapConsumer in | |
* that it takes "indexed" source maps (i.e. ones with a "sections" field) as | |
* input. | |
* | |
* The only parameter is a raw source map (either as a JSON string, or already | |
* parsed to an object). According to the spec for indexed source maps, they | |
* have the following attributes: | |
* | |
* - version: Which version of the source map spec this map is following. | |
* - file: Optional. The generated file this source map is associated with. | |
* - sections: A list of section definitions. | |
* | |
* Each value under the "sections" field has two fields: | |
* - offset: The offset into the original specified at which this section | |
* begins to apply, defined as an object with a "line" and "column" | |
* field. | |
* - map: A source map definition. This source map could also be indexed, | |
* but doesn't have to be. | |
* | |
* Instead of the "map" field, it's also possible to have a "url" field | |
* specifying a URL to retrieve a source map from, but that's currently | |
* unsupported. | |
* | |
* Here's an example source map, taken from the source map spec[0], but | |
* modified to omit a section which uses the "url" field. | |
* | |
* { | |
* version : 3, | |
* file: "app.js", | |
* sections: [{ | |
* offset: {line:100, column:10}, | |
* map: { | |
* version : 3, | |
* file: "section.js", | |
* sources: ["foo.js", "bar.js"], | |
* names: ["src", "maps", "are", "fun"], | |
* mappings: "AAAA,E;;ABCDE;" | |
* } | |
* }], | |
* } | |
* | |
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt | |
*/ | |
function IndexedSourceMapConsumer(aSourceMap) { | |
var sourceMap = aSourceMap; | |
if (typeof aSourceMap === 'string') { | |
sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); | |
} | |
var version = util.getArg(sourceMap, 'version'); | |
var sections = util.getArg(sourceMap, 'sections'); | |
if (version != this._version) { | |
throw new Error('Unsupported version: ' + version); | |
} | |
this._sources = new ArraySet(); | |
this._names = new ArraySet(); | |
var lastOffset = { | |
line: -1, | |
column: 0 | |
}; | |
this._sections = sections.map(function (s) { | |
if (s.url) { | |
// The url field will require support for asynchronicity. | |
// See https://github.com/mozilla/source-map/issues/16 | |
throw new Error('Support for url field in sections not implemented.'); | |
} | |
var offset = util.getArg(s, 'offset'); | |
var offsetLine = util.getArg(offset, 'line'); | |
var offsetColumn = util.getArg(offset, 'column'); | |
if (offsetLine < lastOffset.line || | |
(offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { | |
throw new Error('Section offsets must be ordered and non-overlapping.'); | |
} | |
lastOffset = offset; | |
return { | |
generatedOffset: { | |
// The offset fields are 0-based, but we use 1-based indices when | |
// encoding/decoding from VLQ. | |
generatedLine: offsetLine + 1, | |
generatedColumn: offsetColumn + 1 | |
}, | |
consumer: new SourceMapConsumer(util.getArg(s, 'map')) | |
} | |
}); | |
} | |
IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); | |
IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; | |
/** | |
* The version of the source mapping spec that we are consuming. | |
*/ | |
IndexedSourceMapConsumer.prototype._version = 3; | |
/** | |
* The list of original sources. | |
*/ | |
Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { | |
get: function () { | |
var sources = []; | |
for (var i = 0; i < this._sections.length; i++) { | |
for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { | |
sources.push(this._sections[i].consumer.sources[j]); | |
} | |
} | |
return sources; | |
} | |
}); | |
/** | |
* Returns the original source, line, and column information for the generated | |
* source's line and column positions provided. The only argument is an object | |
* with the following properties: | |
* | |
* - line: The line number in the generated source. | |
* - column: The column number in the generated source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - source: The original source file, or null. | |
* - line: The line number in the original source, or null. | |
* - column: The column number in the original source, or null. | |
* - name: The original identifier, or null. | |
*/ | |
IndexedSourceMapConsumer.prototype.originalPositionFor = | |
function IndexedSourceMapConsumer_originalPositionFor(aArgs) { | |
var needle = { | |
generatedLine: util.getArg(aArgs, 'line'), | |
generatedColumn: util.getArg(aArgs, 'column') | |
}; | |
// Find the section containing the generated position we're trying to map | |
// to an original position. | |
var sectionIndex = binarySearch.search(needle, this._sections, | |
function(needle, section) { | |
var cmp = needle.generatedLine - section.generatedOffset.generatedLine; | |
if (cmp) { | |
return cmp; | |
} | |
return (needle.generatedColumn - | |
section.generatedOffset.generatedColumn); | |
}); | |
var section = this._sections[sectionIndex]; | |
if (!section) { | |
return { | |
source: null, | |
line: null, | |
column: null, | |
name: null | |
}; | |
} | |
return section.consumer.originalPositionFor({ | |
line: needle.generatedLine - | |
(section.generatedOffset.generatedLine - 1), | |
column: needle.generatedColumn - | |
(section.generatedOffset.generatedLine === needle.generatedLine | |
? section.generatedOffset.generatedColumn - 1 | |
: 0), | |
bias: aArgs.bias | |
}); | |
}; | |
/** | |
* Return true if we have the source content for every source in the source | |
* map, false otherwise. | |
*/ | |
IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = | |
function IndexedSourceMapConsumer_hasContentsOfAllSources() { | |
return this._sections.every(function (s) { | |
return s.consumer.hasContentsOfAllSources(); | |
}); | |
}; | |
/** | |
* Returns the original source content. The only argument is the url of the | |
* original source file. Returns null if no original source content is | |
* available. | |
*/ | |
IndexedSourceMapConsumer.prototype.sourceContentFor = | |
function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { | |
for (var i = 0; i < this._sections.length; i++) { | |
var section = this._sections[i]; | |
var content = section.consumer.sourceContentFor(aSource, true); | |
if (content) { | |
return content; | |
} | |
} | |
if (nullOnMissing) { | |
return null; | |
} | |
else { | |
throw new Error('"' + aSource + '" is not in the SourceMap.'); | |
} | |
}; | |
/** | |
* Returns the generated line and column information for the original source, | |
* line, and column positions provided. The only argument is an object with | |
* the following properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* - column: The column number in the original source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
IndexedSourceMapConsumer.prototype.generatedPositionFor = | |
function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { | |
for (var i = 0; i < this._sections.length; i++) { | |
var section = this._sections[i]; | |
// Only consider this section if the requested source is in the list of | |
// sources of the consumer. | |
if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { | |
continue; | |
} | |
var generatedPosition = section.consumer.generatedPositionFor(aArgs); | |
if (generatedPosition) { | |
var ret = { | |
line: generatedPosition.line + | |
(section.generatedOffset.generatedLine - 1), | |
column: generatedPosition.column + | |
(section.generatedOffset.generatedLine === generatedPosition.line | |
? section.generatedOffset.generatedColumn - 1 | |
: 0) | |
}; | |
return ret; | |
} | |
} | |
return { | |
line: null, | |
column: null | |
}; | |
}; | |
/** | |
* Parse the mappings in a string in to a data structure which we can easily | |
* query (the ordered arrays in the `this.__generatedMappings` and | |
* `this.__originalMappings` properties). | |
*/ | |
IndexedSourceMapConsumer.prototype._parseMappings = | |
function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { | |
this.__generatedMappings = []; | |
this.__originalMappings = []; | |
for (var i = 0; i < this._sections.length; i++) { | |
var section = this._sections[i]; | |
var sectionMappings = section.consumer._generatedMappings; | |
for (var j = 0; j < sectionMappings.length; j++) { | |
var mapping = sectionMappings[j]; | |
var source = section.consumer._sources.at(mapping.source); | |
if (section.consumer.sourceRoot !== null) { | |
source = util.join(section.consumer.sourceRoot, source); | |
} | |
this._sources.add(source); | |
source = this._sources.indexOf(source); | |
var name = section.consumer._names.at(mapping.name); | |
this._names.add(name); | |
name = this._names.indexOf(name); | |
// The mappings coming from the consumer for the section have | |
// generated positions relative to the start of the section, so we | |
// need to offset them to be relative to the start of the concatenated | |
// generated file. | |
var adjustedMapping = { | |
source: source, | |
generatedLine: mapping.generatedLine + | |
(section.generatedOffset.generatedLine - 1), | |
generatedColumn: mapping.generatedColumn + | |
(section.generatedOffset.generatedLine === mapping.generatedLine | |
? section.generatedOffset.generatedColumn - 1 | |
: 0), | |
originalLine: mapping.originalLine, | |
originalColumn: mapping.originalColumn, | |
name: name | |
}; | |
this.__generatedMappings.push(adjustedMapping); | |
if (typeof adjustedMapping.originalLine === 'number') { | |
this.__originalMappings.push(adjustedMapping); | |
} | |
} | |
} | |
quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); | |
quickSort(this.__originalMappings, util.compareByOriginalPositions); | |
}; | |
exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; | |
},{"./array-set":145,"./base64-vlq":146,"./binary-search":148,"./quick-sort":150,"./util":154}],152:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var base64VLQ = require('./base64-vlq'); | |
var util = require('./util'); | |
var ArraySet = require('./array-set').ArraySet; | |
var MappingList = require('./mapping-list').MappingList; | |
/** | |
* An instance of the SourceMapGenerator represents a source map which is | |
* being built incrementally. You may pass an object with the following | |
* properties: | |
* | |
* - file: The filename of the generated source. | |
* - sourceRoot: A root for all relative URLs in this source map. | |
*/ | |
function SourceMapGenerator(aArgs) { | |
if (!aArgs) { | |
aArgs = {}; | |
} | |
this._file = util.getArg(aArgs, 'file', null); | |
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); | |
this._skipValidation = util.getArg(aArgs, 'skipValidation', false); | |
this._sources = new ArraySet(); | |
this._names = new ArraySet(); | |
this._mappings = new MappingList(); | |
this._sourcesContents = null; | |
} | |
SourceMapGenerator.prototype._version = 3; | |
/** | |
* Creates a new SourceMapGenerator based on a SourceMapConsumer | |
* | |
* @param aSourceMapConsumer The SourceMap. | |
*/ | |
SourceMapGenerator.fromSourceMap = | |
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { | |
var sourceRoot = aSourceMapConsumer.sourceRoot; | |
var generator = new SourceMapGenerator({ | |
file: aSourceMapConsumer.file, | |
sourceRoot: sourceRoot | |
}); | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
var newMapping = { | |
generated: { | |
line: mapping.generatedLine, | |
column: mapping.generatedColumn | |
} | |
}; | |
if (mapping.source != null) { | |
newMapping.source = mapping.source; | |
if (sourceRoot != null) { | |
newMapping.source = util.relative(sourceRoot, newMapping.source); | |
} | |
newMapping.original = { | |
line: mapping.originalLine, | |
column: mapping.originalColumn | |
}; | |
if (mapping.name != null) { | |
newMapping.name = mapping.name; | |
} | |
} | |
generator.addMapping(newMapping); | |
}); | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
generator.setSourceContent(sourceFile, content); | |
} | |
}); | |
return generator; | |
}; | |
/** | |
* Add a single mapping from original source line and column to the generated | |
* source's line and column for this source map being created. The mapping | |
* object should have the following properties: | |
* | |
* - generated: An object with the generated line and column positions. | |
* - original: An object with the original line and column positions. | |
* - source: The original source file (relative to the sourceRoot). | |
* - name: An optional original token name for this mapping. | |
*/ | |
SourceMapGenerator.prototype.addMapping = | |
function SourceMapGenerator_addMapping(aArgs) { | |
var generated = util.getArg(aArgs, 'generated'); | |
var original = util.getArg(aArgs, 'original', null); | |
var source = util.getArg(aArgs, 'source', null); | |
var name = util.getArg(aArgs, 'name', null); | |
if (!this._skipValidation) { | |
this._validateMapping(generated, original, source, name); | |
} | |
if (source != null) { | |
source = String(source); | |
if (!this._sources.has(source)) { | |
this._sources.add(source); | |
} | |
} | |
if (name != null) { | |
name = String(name); | |
if (!this._names.has(name)) { | |
this._names.add(name); | |
} | |
} | |
this._mappings.add({ | |
generatedLine: generated.line, | |
generatedColumn: generated.column, | |
originalLine: original != null && original.line, | |
originalColumn: original != null && original.column, | |
source: source, | |
name: name | |
}); | |
}; | |
/** | |
* Set the source content for a source file. | |
*/ | |
SourceMapGenerator.prototype.setSourceContent = | |
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { | |
var source = aSourceFile; | |
if (this._sourceRoot != null) { | |
source = util.relative(this._sourceRoot, source); | |
} | |
if (aSourceContent != null) { | |
// Add the source content to the _sourcesContents map. | |
// Create a new _sourcesContents map if the property is null. | |
if (!this._sourcesContents) { | |
this._sourcesContents = Object.create(null); | |
} | |
this._sourcesContents[util.toSetString(source)] = aSourceContent; | |
} else if (this._sourcesContents) { | |
// Remove the source file from the _sourcesContents map. | |
// If the _sourcesContents map is empty, set the property to null. | |
delete this._sourcesContents[util.toSetString(source)]; | |
if (Object.keys(this._sourcesContents).length === 0) { | |
this._sourcesContents = null; | |
} | |
} | |
}; | |
/** | |
* Applies the mappings of a sub-source-map for a specific source file to the | |
* source map being generated. Each mapping to the supplied source file is | |
* rewritten using the supplied source map. Note: The resolution for the | |
* resulting mappings is the minimium of this map and the supplied map. | |
* | |
* @param aSourceMapConsumer The source map to be applied. | |
* @param aSourceFile Optional. The filename of the source file. | |
* If omitted, SourceMapConsumer's file property will be used. | |
* @param aSourceMapPath Optional. The dirname of the path to the source map | |
* to be applied. If relative, it is relative to the SourceMapConsumer. | |
* This parameter is needed when the two source maps aren't in the same | |
* directory, and the source map to be applied contains relative source | |
* paths. If so, those relative source paths need to be rewritten | |
* relative to the SourceMapGenerator. | |
*/ | |
SourceMapGenerator.prototype.applySourceMap = | |
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { | |
var sourceFile = aSourceFile; | |
// If aSourceFile is omitted, we will use the file property of the SourceMap | |
if (aSourceFile == null) { | |
if (aSourceMapConsumer.file == null) { | |
throw new Error( | |
'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + | |
'or the source map\'s "file" property. Both were omitted.' | |
); | |
} | |
sourceFile = aSourceMapConsumer.file; | |
} | |
var sourceRoot = this._sourceRoot; | |
// Make "sourceFile" relative if an absolute Url is passed. | |
if (sourceRoot != null) { | |
sourceFile = util.relative(sourceRoot, sourceFile); | |
} | |
// Applying the SourceMap can add and remove items from the sources and | |
// the names array. | |
var newSources = new ArraySet(); | |
var newNames = new ArraySet(); | |
// Find mappings for the "sourceFile" | |
this._mappings.unsortedForEach(function (mapping) { | |
if (mapping.source === sourceFile && mapping.originalLine != null) { | |
// Check if it can be mapped by the source map, then update the mapping. | |
var original = aSourceMapConsumer.originalPositionFor({ | |
line: mapping.originalLine, | |
column: mapping.originalColumn | |
}); | |
if (original.source != null) { | |
// Copy mapping | |
mapping.source = original.source; | |
if (aSourceMapPath != null) { | |
mapping.source = util.join(aSourceMapPath, mapping.source) | |
} | |
if (sourceRoot != null) { | |
mapping.source = util.relative(sourceRoot, mapping.source); | |
} | |
mapping.originalLine = original.line; | |
mapping.originalColumn = original.column; | |
if (original.name != null) { | |
mapping.name = original.name; | |
} | |
} | |
} | |
var source = mapping.source; | |
if (source != null && !newSources.has(source)) { | |
newSources.add(source); | |
} | |
var name = mapping.name; | |
if (name != null && !newNames.has(name)) { | |
newNames.add(name); | |
} | |
}, this); | |
this._sources = newSources; | |
this._names = newNames; | |
// Copy sourcesContents of applied map. | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
if (aSourceMapPath != null) { | |
sourceFile = util.join(aSourceMapPath, sourceFile); | |
} | |
if (sourceRoot != null) { | |
sourceFile = util.relative(sourceRoot, sourceFile); | |
} | |
this.setSourceContent(sourceFile, content); | |
} | |
}, this); | |
}; | |
/** | |
* A mapping can have one of the three levels of data: | |
* | |
* 1. Just the generated position. | |
* 2. The Generated position, original position, and original source. | |
* 3. Generated and original position, original source, as well as a name | |
* token. | |
* | |
* To maintain consistency, we validate that any new mapping being added falls | |
* in to one of these categories. | |
*/ | |
SourceMapGenerator.prototype._validateMapping = | |
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, | |
aName) { | |
// When aOriginal is truthy but has empty values for .line and .column, | |
// it is most likely a programmer error. In this case we throw a very | |
// specific error message to try to guide them the right way. | |
// For example: https://github.com/Polymer/polymer-bundler/pull/519 | |
if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { | |
throw new Error( | |
'original.line and original.column are not numbers -- you probably meant to omit ' + | |
'the original mapping entirely and only map the generated position. If so, pass ' + | |
'null for the original mapping instead of an object with empty or null values.' | |
); | |
} | |
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& !aOriginal && !aSource && !aName) { | |
// Case 1. | |
return; | |
} | |
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& aOriginal.line > 0 && aOriginal.column >= 0 | |
&& aSource) { | |
// Cases 2 and 3. | |
return; | |
} | |
else { | |
throw new Error('Invalid mapping: ' + JSON.stringify({ | |
generated: aGenerated, | |
source: aSource, | |
original: aOriginal, | |
name: aName | |
})); | |
} | |
}; | |
/** | |
* Serialize the accumulated mappings in to the stream of base 64 VLQs | |
* specified by the source map format. | |
*/ | |
SourceMapGenerator.prototype._serializeMappings = | |
function SourceMapGenerator_serializeMappings() { | |
var previousGeneratedColumn = 0; | |
var previousGeneratedLine = 1; | |
var previousOriginalColumn = 0; | |
var previousOriginalLine = 0; | |
var previousName = 0; | |
var previousSource = 0; | |
var result = ''; | |
var next; | |
var mapping; | |
var nameIdx; | |
var sourceIdx; | |
var mappings = this._mappings.toArray(); | |
for (var i = 0, len = mappings.length; i < len; i++) { | |
mapping = mappings[i]; | |
next = '' | |
if (mapping.generatedLine !== previousGeneratedLine) { | |
previousGeneratedColumn = 0; | |
while (mapping.generatedLine !== previousGeneratedLine) { | |
next += ';'; | |
previousGeneratedLine++; | |
} | |
} | |
else { | |
if (i > 0) { | |
if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { | |
continue; | |
} | |
next += ','; | |
} | |
} | |
next += base64VLQ.encode(mapping.generatedColumn | |
- previousGeneratedColumn); | |
previousGeneratedColumn = mapping.generatedColumn; | |
if (mapping.source != null) { | |
sourceIdx = this._sources.indexOf(mapping.source); | |
next += base64VLQ.encode(sourceIdx - previousSource); | |
previousSource = sourceIdx; | |
// lines are stored 0-based in SourceMap spec version 3 | |
next += base64VLQ.encode(mapping.originalLine - 1 | |
- previousOriginalLine); | |
previousOriginalLine = mapping.originalLine - 1; | |
next += base64VLQ.encode(mapping.originalColumn | |
- previousOriginalColumn); | |
previousOriginalColumn = mapping.originalColumn; | |
if (mapping.name != null) { | |
nameIdx = this._names.indexOf(mapping.name); | |
next += base64VLQ.encode(nameIdx - previousName); | |
previousName = nameIdx; | |
} | |
} | |
result += next; | |
} | |
return result; | |
}; | |
SourceMapGenerator.prototype._generateSourcesContent = | |
function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { | |
return aSources.map(function (source) { | |
if (!this._sourcesContents) { | |
return null; | |
} | |
if (aSourceRoot != null) { | |
source = util.relative(aSourceRoot, source); | |
} | |
var key = util.toSetString(source); | |
return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) | |
? this._sourcesContents[key] | |
: null; | |
}, this); | |
}; | |
/** | |
* Externalize the source map. | |
*/ | |
SourceMapGenerator.prototype.toJSON = | |
function SourceMapGenerator_toJSON() { | |
var map = { | |
version: this._version, | |
sources: this._sources.toArray(), | |
names: this._names.toArray(), | |
mappings: this._serializeMappings() | |
}; | |
if (this._file != null) { | |
map.file = this._file; | |
} | |
if (this._sourceRoot != null) { | |
map.sourceRoot = this._sourceRoot; | |
} | |
if (this._sourcesContents) { | |
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); | |
} | |
return map; | |
}; | |
/** | |
* Render the source map being generated to a string. | |
*/ | |
SourceMapGenerator.prototype.toString = | |
function SourceMapGenerator_toString() { | |
return JSON.stringify(this.toJSON()); | |
}; | |
exports.SourceMapGenerator = SourceMapGenerator; | |
},{"./array-set":145,"./base64-vlq":146,"./mapping-list":149,"./util":154}],153:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; | |
var util = require('./util'); | |
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other | |
// operating systems these days (capturing the result). | |
var REGEX_NEWLINE = /(\r?\n)/; | |
// Newline character code for charCodeAt() comparisons | |
var NEWLINE_CODE = 10; | |
// Private symbol for identifying `SourceNode`s when multiple versions of | |
// the source-map library are loaded. This MUST NOT CHANGE across | |
// versions! | |
var isSourceNode = "$$$isSourceNode$$$"; | |
/** | |
* SourceNodes provide a way to abstract over interpolating/concatenating | |
* snippets of generated JavaScript source code while maintaining the line and | |
* column information associated with the original source code. | |
* | |
* @param aLine The original line number. | |
* @param aColumn The original column number. | |
* @param aSource The original source's filename. | |
* @param aChunks Optional. An array of strings which are snippets of | |
* generated JS, or other SourceNodes. | |
* @param aName The original identifier. | |
*/ | |
function SourceNode(aLine, aColumn, aSource, aChunks, aName) { | |
this.children = []; | |
this.sourceContents = {}; | |
this.line = aLine == null ? null : aLine; | |
this.column = aColumn == null ? null : aColumn; | |
this.source = aSource == null ? null : aSource; | |
this.name = aName == null ? null : aName; | |
this[isSourceNode] = true; | |
if (aChunks != null) this.add(aChunks); | |
} | |
/** | |
* Creates a SourceNode from generated code and a SourceMapConsumer. | |
* | |
* @param aGeneratedCode The generated code | |
* @param aSourceMapConsumer The SourceMap for the generated code | |
* @param aRelativePath Optional. The path that relative sources in the | |
* SourceMapConsumer should be relative to. | |
*/ | |
SourceNode.fromStringWithSourceMap = | |
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { | |
// The SourceNode we want to fill with the generated code | |
// and the SourceMap | |
var node = new SourceNode(); | |
// All even indices of this array are one line of the generated code, | |
// while all odd indices are the newlines between two adjacent lines | |
// (since `REGEX_NEWLINE` captures its match). | |
// Processed fragments are accessed by calling `shiftNextLine`. | |
var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); | |
var remainingLinesIndex = 0; | |
var shiftNextLine = function() { | |
var lineContents = getNextLine(); | |
// The last line of a file might not have a newline. | |
var newLine = getNextLine() || ""; | |
return lineContents + newLine; | |
function getNextLine() { | |
return remainingLinesIndex < remainingLines.length ? | |
remainingLines[remainingLinesIndex++] : undefined; | |
} | |
}; | |
// We need to remember the position of "remainingLines" | |
var lastGeneratedLine = 1, lastGeneratedColumn = 0; | |
// The generate SourceNodes we need a code range. | |
// To extract it current and last mapping is used. | |
// Here we store the last mapping. | |
var lastMapping = null; | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
if (lastMapping !== null) { | |
// We add the code from "lastMapping" to "mapping": | |
// First check if there is a new line in between. | |
if (lastGeneratedLine < mapping.generatedLine) { | |
// Associate first line with "lastMapping" | |
addMappingWithCode(lastMapping, shiftNextLine()); | |
lastGeneratedLine++; | |
lastGeneratedColumn = 0; | |
// The remaining code is added without mapping | |
} else { | |
// There is no new line in between. | |
// Associate the code between "lastGeneratedColumn" and | |
// "mapping.generatedColumn" with "lastMapping" | |
var nextLine = remainingLines[remainingLinesIndex]; | |
var code = nextLine.substr(0, mapping.generatedColumn - | |
lastGeneratedColumn); | |
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - | |
lastGeneratedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
addMappingWithCode(lastMapping, code); | |
// No more remaining code, continue | |
lastMapping = mapping; | |
return; | |
} | |
} | |
// We add the generated code until the first mapping | |
// to the SourceNode without any mapping. | |
// Each line is added as separate string. | |
while (lastGeneratedLine < mapping.generatedLine) { | |
node.add(shiftNextLine()); | |
lastGeneratedLine++; | |
} | |
if (lastGeneratedColumn < mapping.generatedColumn) { | |
var nextLine = remainingLines[remainingLinesIndex]; | |
node.add(nextLine.substr(0, mapping.generatedColumn)); | |
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
} | |
lastMapping = mapping; | |
}, this); | |
// We have processed all mappings. | |
if (remainingLinesIndex < remainingLines.length) { | |
if (lastMapping) { | |
// Associate the remaining code in the current line with "lastMapping" | |
addMappingWithCode(lastMapping, shiftNextLine()); | |
} | |
// and add the remaining lines without any mapping | |
node.add(remainingLines.splice(remainingLinesIndex).join("")); | |
} | |
// Copy sourcesContent into SourceNode | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
if (aRelativePath != null) { | |
sourceFile = util.join(aRelativePath, sourceFile); | |
} | |
node.setSourceContent(sourceFile, content); | |
} | |
}); | |
return node; | |
function addMappingWithCode(mapping, code) { | |
if (mapping === null || mapping.source === undefined) { | |
node.add(code); | |
} else { | |
var source = aRelativePath | |
? util.join(aRelativePath, mapping.source) | |
: mapping.source; | |
node.add(new SourceNode(mapping.originalLine, | |
mapping.originalColumn, | |
source, | |
code, | |
mapping.name)); | |
} | |
} | |
}; | |
/** | |
* Add a chunk of generated JS to this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.add = function SourceNode_add(aChunk) { | |
if (Array.isArray(aChunk)) { | |
aChunk.forEach(function (chunk) { | |
this.add(chunk); | |
}, this); | |
} | |
else if (aChunk[isSourceNode] || typeof aChunk === "string") { | |
if (aChunk) { | |
this.children.push(aChunk); | |
} | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Add a chunk of generated JS to the beginning of this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { | |
if (Array.isArray(aChunk)) { | |
for (var i = aChunk.length-1; i >= 0; i--) { | |
this.prepend(aChunk[i]); | |
} | |
} | |
else if (aChunk[isSourceNode] || typeof aChunk === "string") { | |
this.children.unshift(aChunk); | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Walk over the tree of JS snippets in this node and its children. The | |
* walking function is called once for each snippet of JS and is passed that | |
* snippet and the its original associated source's line/column location. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walk = function SourceNode_walk(aFn) { | |
var chunk; | |
for (var i = 0, len = this.children.length; i < len; i++) { | |
chunk = this.children[i]; | |
if (chunk[isSourceNode]) { | |
chunk.walk(aFn); | |
} | |
else { | |
if (chunk !== '') { | |
aFn(chunk, { source: this.source, | |
line: this.line, | |
column: this.column, | |
name: this.name }); | |
} | |
} | |
} | |
}; | |
/** | |
* Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between | |
* each of `this.children`. | |
* | |
* @param aSep The separator. | |
*/ | |
SourceNode.prototype.join = function SourceNode_join(aSep) { | |
var newChildren; | |
var i; | |
var len = this.children.length; | |
if (len > 0) { | |
newChildren = []; | |
for (i = 0; i < len-1; i++) { | |
newChildren.push(this.children[i]); | |
newChildren.push(aSep); | |
} | |
newChildren.push(this.children[i]); | |
this.children = newChildren; | |
} | |
return this; | |
}; | |
/** | |
* Call String.prototype.replace on the very right-most source snippet. Useful | |
* for trimming whitespace from the end of a source node, etc. | |
* | |
* @param aPattern The pattern to replace. | |
* @param aReplacement The thing to replace the pattern with. | |
*/ | |
SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { | |
var lastChild = this.children[this.children.length - 1]; | |
if (lastChild[isSourceNode]) { | |
lastChild.replaceRight(aPattern, aReplacement); | |
} | |
else if (typeof lastChild === 'string') { | |
this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); | |
} | |
else { | |
this.children.push(''.replace(aPattern, aReplacement)); | |
} | |
return this; | |
}; | |
/** | |
* Set the source content for a source file. This will be added to the SourceMapGenerator | |
* in the sourcesContent field. | |
* | |
* @param aSourceFile The filename of the source file | |
* @param aSourceContent The content of the source file | |
*/ | |
SourceNode.prototype.setSourceContent = | |
function SourceNode_setSourceContent(aSourceFile, aSourceContent) { | |
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; | |
}; | |
/** | |
* Walk over the tree of SourceNodes. The walking function is called for each | |
* source file content and is passed the filename and source content. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walkSourceContents = | |
function SourceNode_walkSourceContents(aFn) { | |
for (var i = 0, len = this.children.length; i < len; i++) { | |
if (this.children[i][isSourceNode]) { | |
this.children[i].walkSourceContents(aFn); | |
} | |
} | |
var sources = Object.keys(this.sourceContents); | |
for (var i = 0, len = sources.length; i < len; i++) { | |
aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); | |
} | |
}; | |
/** | |
* Return the string representation of this source node. Walks over the tree | |
* and concatenates all the various snippets together to one string. | |
*/ | |
SourceNode.prototype.toString = function SourceNode_toString() { | |
var str = ""; | |
this.walk(function (chunk) { | |
str += chunk; | |
}); | |
return str; | |
}; | |
/** | |
* Returns the string representation of this source node along with a source | |
* map. | |
*/ | |
SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { | |
var generated = { | |
code: "", | |
line: 1, | |
column: 0 | |
}; | |
var map = new SourceMapGenerator(aArgs); | |
var sourceMappingActive = false; | |
var lastOriginalSource = null; | |
var lastOriginalLine = null; | |
var lastOriginalColumn = null; | |
var lastOriginalName = null; | |
this.walk(function (chunk, original) { | |
generated.code += chunk; | |
if (original.source !== null | |
&& original.line !== null | |
&& original.column !== null) { | |
if(lastOriginalSource !== original.source | |
|| lastOriginalLine !== original.line | |
|| lastOriginalColumn !== original.column | |
|| lastOriginalName !== original.name) { | |
map.addMapping({ | |
source: original.source, | |
original: { | |
line: original.line, | |
column: original.column | |
}, | |
generated: { | |
line: generated.line, | |
column: generated.column | |
}, | |
name: original.name | |
}); | |
} | |
lastOriginalSource = original.source; | |
lastOriginalLine = original.line; | |
lastOriginalColumn = original.column; | |
lastOriginalName = original.name; | |
sourceMappingActive = true; | |
} else if (sourceMappingActive) { | |
map.addMapping({ | |
generated: { | |
line: generated.line, | |
column: generated.column | |
} | |
}); | |
lastOriginalSource = null; | |
sourceMappingActive = false; | |
} | |
for (var idx = 0, length = chunk.length; idx < length; idx++) { | |
if (chunk.charCodeAt(idx) === NEWLINE_CODE) { | |
generated.line++; | |
generated.column = 0; | |
// Mappings end at eol | |
if (idx + 1 === length) { | |
lastOriginalSource = null; | |
sourceMappingActive = false; | |
} else if (sourceMappingActive) { | |
map.addMapping({ | |
source: original.source, | |
original: { | |
line: original.line, | |
column: original.column | |
}, | |
generated: { | |
line: generated.line, | |
column: generated.column | |
}, | |
name: original.name | |
}); | |
} | |
} else { | |
generated.column++; | |
} | |
} | |
}); | |
this.walkSourceContents(function (sourceFile, sourceContent) { | |
map.setSourceContent(sourceFile, sourceContent); | |
}); | |
return { code: generated.code, map: map }; | |
}; | |
exports.SourceNode = SourceNode; | |
},{"./source-map-generator":152,"./util":154}],154:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
/** | |
* This is a helper function for getting values from parameter/options | |
* objects. | |
* | |
* @param args The object we are extracting values from | |
* @param name The name of the property we are getting. | |
* @param defaultValue An optional value to return if the property is missing | |
* from the object. If this is not specified and the property is missing, an | |
* error will be thrown. | |
*/ | |
function getArg(aArgs, aName, aDefaultValue) { | |
if (aName in aArgs) { | |
return aArgs[aName]; | |
} else if (arguments.length === 3) { | |
return aDefaultValue; | |
} else { | |
throw new Error('"' + aName + '" is a required argument.'); | |
} | |
} | |
exports.getArg = getArg; | |
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; | |
var dataUrlRegexp = /^data:.+\,.+$/; | |
function urlParse(aUrl) { | |
var match = aUrl.match(urlRegexp); | |
if (!match) { | |
return null; | |
} | |
return { | |
scheme: match[1], | |
auth: match[2], | |
host: match[3], | |
port: match[4], | |
path: match[5] | |
}; | |
} | |
exports.urlParse = urlParse; | |
function urlGenerate(aParsedUrl) { | |
var url = ''; | |
if (aParsedUrl.scheme) { | |
url += aParsedUrl.scheme + ':'; | |
} | |
url += '//'; | |
if (aParsedUrl.auth) { | |
url += aParsedUrl.auth + '@'; | |
} | |
if (aParsedUrl.host) { | |
url += aParsedUrl.host; | |
} | |
if (aParsedUrl.port) { | |
url += ":" + aParsedUrl.port | |
} | |
if (aParsedUrl.path) { | |
url += aParsedUrl.path; | |
} | |
return url; | |
} | |
exports.urlGenerate = urlGenerate; | |
/** | |
* Normalizes a path, or the path portion of a URL: | |
* | |
* - Replaces consecutive slashes with one slash. | |
* - Removes unnecessary '.' parts. | |
* - Removes unnecessary '<dir>/..' parts. | |
* | |
* Based on code in the Node.js 'path' core module. | |
* | |
* @param aPath The path or url to normalize. | |
*/ | |
function normalize(aPath) { | |
var path = aPath; | |
var url = urlParse(aPath); | |
if (url) { | |
if (!url.path) { | |
return aPath; | |
} | |
path = url.path; | |
} | |
var isAbsolute = exports.isAbsolute(path); | |
var parts = path.split(/\/+/); | |
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { | |
part = parts[i]; | |
if (part === '.') { | |
parts.splice(i, 1); | |
} else if (part === '..') { | |
up++; | |
} else if (up > 0) { | |
if (part === '') { | |
// The first part is blank if the path is absolute. Trying to go | |
// above the root is a no-op. Therefore we can remove all '..' parts | |
// directly after the root. | |
parts.splice(i + 1, up); | |
up = 0; | |
} else { | |
parts.splice(i, 2); | |
up--; | |
} | |
} | |
} | |
path = parts.join('/'); | |
if (path === '') { | |
path = isAbsolute ? '/' : '.'; | |
} | |
if (url) { | |
url.path = path; | |
return urlGenerate(url); | |
} | |
return path; | |
} | |
exports.normalize = normalize; | |
/** | |
* Joins two paths/URLs. | |
* | |
* @param aRoot The root path or URL. | |
* @param aPath The path or URL to be joined with the root. | |
* | |
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a | |
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended | |
* first. | |
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion | |
* is updated with the result and aRoot is returned. Otherwise the result | |
* is returned. | |
* - If aPath is absolute, the result is aPath. | |
* - Otherwise the two paths are joined with a slash. | |
* - Joining for example 'http://' and 'www.example.com' is also supported. | |
*/ | |
function join(aRoot, aPath) { | |
if (aRoot === "") { | |
aRoot = "."; | |
} | |
if (aPath === "") { | |
aPath = "."; | |
} | |
var aPathUrl = urlParse(aPath); | |
var aRootUrl = urlParse(aRoot); | |
if (aRootUrl) { | |
aRoot = aRootUrl.path || '/'; | |
} | |
// `join(foo, '//www.example.org')` | |
if (aPathUrl && !aPathUrl.scheme) { | |
if (aRootUrl) { | |
aPathUrl.scheme = aRootUrl.scheme; | |
} | |
return urlGenerate(aPathUrl); | |
} | |
if (aPathUrl || aPath.match(dataUrlRegexp)) { | |
return aPath; | |
} | |
// `join('http://', 'www.example.com')` | |
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { | |
aRootUrl.host = aPath; | |
return urlGenerate(aRootUrl); | |
} | |
var joined = aPath.charAt(0) === '/' | |
? aPath | |
: normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); | |
if (aRootUrl) { | |
aRootUrl.path = joined; | |
return urlGenerate(aRootUrl); | |
} | |
return joined; | |
} | |
exports.join = join; | |
exports.isAbsolute = function (aPath) { | |
return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); | |
}; | |
/** | |
* Make a path relative to a URL or another path. | |
* | |
* @param aRoot The root path or URL. | |
* @param aPath The path or URL to be made relative to aRoot. | |
*/ | |
function relative(aRoot, aPath) { | |
if (aRoot === "") { | |
aRoot = "."; | |
} | |
aRoot = aRoot.replace(/\/$/, ''); | |
// It is possible for the path to be above the root. In this case, simply | |
// checking whether the root is a prefix of the path won't work. Instead, we | |
// need to remove components from the root one by one, until either we find | |
// a prefix that fits, or we run out of components to remove. | |
var level = 0; | |
while (aPath.indexOf(aRoot + '/') !== 0) { | |
var index = aRoot.lastIndexOf("/"); | |
if (index < 0) { | |
return aPath; | |
} | |
// If the only part of the root that is left is the scheme (i.e. http://, | |
// file:///, etc.), one or more slashes (/), or simply nothing at all, we | |
// have exhausted all components, so the path is not relative to the root. | |
aRoot = aRoot.slice(0, index); | |
if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { | |
return aPath; | |
} | |
++level; | |
} | |
// Make sure we add a "../" for each component we removed from the root. | |
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); | |
} | |
exports.relative = relative; | |
var supportsNullProto = (function () { | |
var obj = Object.create(null); | |
return !('__proto__' in obj); | |
}()); | |
function identity (s) { | |
return s; | |
} | |
/** | |
* Because behavior goes wacky when you set `__proto__` on objects, we | |
* have to prefix all the strings in our set with an arbitrary character. | |
* | |
* See https://github.com/mozilla/source-map/pull/31 and | |
* https://github.com/mozilla/source-map/issues/30 | |
* | |
* @param String aStr | |
*/ | |
function toSetString(aStr) { | |
if (isProtoString(aStr)) { | |
return '$' + aStr; | |
} | |
return aStr; | |
} | |
exports.toSetString = supportsNullProto ? identity : toSetString; | |
function fromSetString(aStr) { | |
if (isProtoString(aStr)) { | |
return aStr.slice(1); | |
} | |
return aStr; | |
} | |
exports.fromSetString = supportsNullProto ? identity : fromSetString; | |
function isProtoString(s) { | |
if (!s) { | |
return false; | |
} | |
var length = s.length; | |
if (length < 9 /* "__proto__".length */) { | |
return false; | |
} | |
if (s.charCodeAt(length - 1) !== 95 /* '_' */ || | |
s.charCodeAt(length - 2) !== 95 /* '_' */ || | |
s.charCodeAt(length - 3) !== 111 /* 'o' */ || | |
s.charCodeAt(length - 4) !== 116 /* 't' */ || | |
s.charCodeAt(length - 5) !== 111 /* 'o' */ || | |
s.charCodeAt(length - 6) !== 114 /* 'r' */ || | |
s.charCodeAt(length - 7) !== 112 /* 'p' */ || | |
s.charCodeAt(length - 8) !== 95 /* '_' */ || | |
s.charCodeAt(length - 9) !== 95 /* '_' */) { | |
return false; | |
} | |
for (var i = length - 10; i >= 0; i--) { | |
if (s.charCodeAt(i) !== 36 /* '$' */) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* Comparator between two mappings where the original positions are compared. | |
* | |
* Optionally pass in `true` as `onlyCompareGenerated` to consider two | |
* mappings with the same original source/line/column, but different generated | |
* line and column the same. Useful when searching for a mapping with a | |
* stubbed out mapping. | |
*/ | |
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { | |
var cmp = mappingA.source - mappingB.source; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalLine - mappingB.originalLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalColumn - mappingB.originalColumn; | |
if (cmp !== 0 || onlyCompareOriginal) { | |
return cmp; | |
} | |
cmp = mappingA.generatedColumn - mappingB.generatedColumn; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.generatedLine - mappingB.generatedLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
return mappingA.name - mappingB.name; | |
} | |
exports.compareByOriginalPositions = compareByOriginalPositions; | |
/** | |
* Comparator between two mappings with deflated source and name indices where | |
* the generated positions are compared. | |
* | |
* Optionally pass in `true` as `onlyCompareGenerated` to consider two | |
* mappings with the same generated line and column, but different | |
* source/name/original line and column the same. Useful when searching for a | |
* mapping with a stubbed out mapping. | |
*/ | |
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { | |
var cmp = mappingA.generatedLine - mappingB.generatedLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.generatedColumn - mappingB.generatedColumn; | |
if (cmp !== 0 || onlyCompareGenerated) { | |
return cmp; | |
} | |
cmp = mappingA.source - mappingB.source; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalLine - mappingB.originalLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalColumn - mappingB.originalColumn; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
return mappingA.name - mappingB.name; | |
} | |
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; | |
function strcmp(aStr1, aStr2) { | |
if (aStr1 === aStr2) { | |
return 0; | |
} | |
if (aStr1 > aStr2) { | |
return 1; | |
} | |
return -1; | |
} | |
/** | |
* Comparator between two mappings with inflated source and name strings where | |
* the generated positions are compared. | |
*/ | |
function compareByGeneratedPositionsInflated(mappingA, mappingB) { | |
var cmp = mappingA.generatedLine - mappingB.generatedLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.generatedColumn - mappingB.generatedColumn; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = strcmp(mappingA.source, mappingB.source); | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalLine - mappingB.originalLine; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
cmp = mappingA.originalColumn - mappingB.originalColumn; | |
if (cmp !== 0) { | |
return cmp; | |
} | |
return strcmp(mappingA.name, mappingB.name); | |
} | |
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; | |
},{}],155:[function(require,module,exports){ | |
/* | |
* Copyright 2009-2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE.txt or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
exports.SourceMapGenerator = require('./lib/source-map-generator').SourceMapGenerator; | |
exports.SourceMapConsumer = require('./lib/source-map-consumer').SourceMapConsumer; | |
exports.SourceNode = require('./lib/source-node').SourceNode; | |
},{"./lib/source-map-consumer":151,"./lib/source-map-generator":152,"./lib/source-node":153}],156:[function(require,module,exports){ | |
exports.parse = require('./lib/parse'); | |
exports.stringify = require('./lib/stringify'); | |
},{"./lib/parse":157,"./lib/stringify":161}],157:[function(require,module,exports){ | |
// http://www.w3.org/TR/CSS21/grammar.html | |
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 | |
var commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g | |
module.exports = function(css, options){ | |
options = options || {}; | |
/** | |
* Positional. | |
*/ | |
var lineno = 1; | |
var column = 1; | |
/** | |
* Update lineno and column based on `str`. | |
*/ | |
function updatePosition(str) { | |
var lines = str.match(/\n/g); | |
if (lines) lineno += lines.length; | |
var i = str.lastIndexOf('\n'); | |
column = ~i ? str.length - i : column + str.length; | |
} | |
/** | |
* Mark position and patch `node.position`. | |
*/ | |
function position() { | |
var start = { line: lineno, column: column }; | |
return function(node){ | |
node.position = new Position(start); | |
whitespace(); | |
return node; | |
}; | |
} | |
/** | |
* Store position information for a node | |
*/ | |
function Position(start) { | |
this.start = start; | |
this.end = { line: lineno, column: column }; | |
this.source = options.source; | |
} | |
/** | |
* Non-enumerable source string | |
*/ | |
Position.prototype.content = css; | |
/** | |
* Error `msg`. | |
*/ | |
var errorsList = []; | |
function error(msg) { | |
var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); | |
err.reason = msg; | |
err.filename = options.source; | |
err.line = lineno; | |
err.column = column; | |
err.source = css; | |
if (options.silent) { | |
errorsList.push(err); | |
} else { | |
throw err; | |
} | |
} | |
/** | |
* Parse stylesheet. | |
*/ | |
function stylesheet() { | |
var rulesList = rules(); | |
return { | |
type: 'stylesheet', | |
stylesheet: { | |
source: options.source, | |
rules: rulesList, | |
parsingErrors: errorsList | |
} | |
}; | |
} | |
/** | |
* Opening brace. | |
*/ | |
function open() { | |
return match(/^{\s*/); | |
} | |
/** | |
* Closing brace. | |
*/ | |
function close() { | |
return match(/^}/); | |
} | |
/** | |
* Parse ruleset. | |
*/ | |
function rules() { | |
var node; | |
var rules = []; | |
whitespace(); | |
comments(rules); | |
while (css.length && css.charAt(0) != '}' && (node = atrule() || rule())) { | |
if (node !== false) { | |
rules.push(node); | |
comments(rules); | |
} | |
} | |
return rules; | |
} | |
/** | |
* Match `re` and return captures. | |
*/ | |
function match(re) { | |
var m = re.exec(css); | |
if (!m) return; | |
var str = m[0]; | |
updatePosition(str); | |
css = css.slice(str.length); | |
return m; | |
} | |
/** | |
* Parse whitespace. | |
*/ | |
function whitespace() { | |
match(/^\s*/); | |
} | |
/** | |
* Parse comments; | |
*/ | |
function comments(rules) { | |
var c; | |
rules = rules || []; | |
while (c = comment()) { | |
if (c !== false) { | |
rules.push(c); | |
} | |
} | |
return rules; | |
} | |
/** | |
* Parse comment. | |
*/ | |
function comment() { | |
var pos = position(); | |
if ('/' != css.charAt(0) || '*' != css.charAt(1)) return; | |
var i = 2; | |
while ("" != css.charAt(i) && ('*' != css.charAt(i) || '/' != css.charAt(i + 1))) ++i; | |
i += 2; | |
if ("" === css.charAt(i-1)) { | |
return error('End of comment missing'); | |
} | |
var str = css.slice(2, i - 2); | |
column += 2; | |
updatePosition(str); | |
css = css.slice(i); | |
column += 2; | |
return pos({ | |
type: 'comment', | |
comment: str | |
}); | |
} | |
/** | |
* Parse selector. | |
*/ | |
function selector() { | |
var m = match(/^([^{]+)/); | |
if (!m) return; | |
/* @fix Remove all comments from selectors | |
* http://ostermiller.org/findcomment.html */ | |
return trim(m[0]) | |
.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '') | |
.replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function(m) { | |
return m.replace(/,/g, '\u200C'); | |
}) | |
.split(/\s*(?![^(]*\)),\s*/) | |
.map(function(s) { | |
return s.replace(/\u200C/g, ','); | |
}); | |
} | |
/** | |
* Parse declaration. | |
*/ | |
function declaration() { | |
var pos = position(); | |
// prop | |
var prop = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); | |
if (!prop) return; | |
prop = trim(prop[0]); | |
// : | |
if (!match(/^:\s*/)) return error("property missing ':'"); | |
// val | |
var val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); | |
var ret = pos({ | |
type: 'declaration', | |
property: prop.replace(commentre, ''), | |
value: val ? trim(val[0]).replace(commentre, '') : '' | |
}); | |
// ; | |
match(/^[;\s]*/); | |
return ret; | |
} | |
/** | |
* Parse declarations. | |
*/ | |
function declarations() { | |
var decls = []; | |
if (!open()) return error("missing '{'"); | |
comments(decls); | |
// declarations | |
var decl; | |
while (decl = declaration()) { | |
if (decl !== false) { | |
decls.push(decl); | |
comments(decls); | |
} | |
} | |
if (!close()) return error("missing '}'"); | |
return decls; | |
} | |
/** | |
* Parse keyframe. | |
*/ | |
function keyframe() { | |
var m; | |
var vals = []; | |
var pos = position(); | |
while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { | |
vals.push(m[1]); | |
match(/^,\s*/); | |
} | |
if (!vals.length) return; | |
return pos({ | |
type: 'keyframe', | |
values: vals, | |
declarations: declarations() | |
}); | |
} | |
/** | |
* Parse keyframes. | |
*/ | |
function atkeyframes() { | |
var pos = position(); | |
var m = match(/^@([-\w]+)?keyframes\s*/); | |
if (!m) return; | |
var vendor = m[1]; | |
// identifier | |
var m = match(/^([-\w]+)\s*/); | |
if (!m) return error("@keyframes missing name"); | |
var name = m[1]; | |
if (!open()) return error("@keyframes missing '{'"); | |
var frame; | |
var frames = comments(); | |
while (frame = keyframe()) { | |
frames.push(frame); | |
frames = frames.concat(comments()); | |
} | |
if (!close()) return error("@keyframes missing '}'"); | |
return pos({ | |
type: 'keyframes', | |
name: name, | |
vendor: vendor, | |
keyframes: frames | |
}); | |
} | |
/** | |
* Parse supports. | |
*/ | |
function atsupports() { | |
var pos = position(); | |
var m = match(/^@supports *([^{]+)/); | |
if (!m) return; | |
var supports = trim(m[1]); | |
if (!open()) return error("@supports missing '{'"); | |
var style = comments().concat(rules()); | |
if (!close()) return error("@supports missing '}'"); | |
return pos({ | |
type: 'supports', | |
supports: supports, | |
rules: style | |
}); | |
} | |
/** | |
* Parse host. | |
*/ | |
function athost() { | |
var pos = position(); | |
var m = match(/^@host\s*/); | |
if (!m) return; | |
if (!open()) return error("@host missing '{'"); | |
var style = comments().concat(rules()); | |
if (!close()) return error("@host missing '}'"); | |
return pos({ | |
type: 'host', | |
rules: style | |
}); | |
} | |
/** | |
* Parse media. | |
*/ | |
function atmedia() { | |
var pos = position(); | |
var m = match(/^@media *([^{]+)/); | |
if (!m) return; | |
var media = trim(m[1]); | |
if (!open()) return error("@media missing '{'"); | |
var style = comments().concat(rules()); | |
if (!close()) return error("@media missing '}'"); | |
return pos({ | |
type: 'media', | |
media: media, | |
rules: style | |
}); | |
} | |
/** | |
* Parse custom-media. | |
*/ | |
function atcustommedia() { | |
var pos = position(); | |
var m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); | |
if (!m) return; | |
return pos({ | |
type: 'custom-media', | |
name: trim(m[1]), | |
media: trim(m[2]) | |
}); | |
} | |
/** | |
* Parse paged media. | |
*/ | |
function atpage() { | |
var pos = position(); | |
var m = match(/^@page */); | |
if (!m) return; | |
var sel = selector() || []; | |
if (!open()) return error("@page missing '{'"); | |
var decls = comments(); | |
// declarations | |
var decl; | |
while (decl = declaration()) { | |
decls.push(decl); | |
decls = decls.concat(comments()); | |
} | |
if (!close()) return error("@page missing '}'"); | |
return pos({ | |
type: 'page', | |
selectors: sel, | |
declarations: decls | |
}); | |
} | |
/** | |
* Parse document. | |
*/ | |
function atdocument() { | |
var pos = position(); | |
var m = match(/^@([-\w]+)?document *([^{]+)/); | |
if (!m) return; | |
var vendor = trim(m[1]); | |
var doc = trim(m[2]); | |
if (!open()) return error("@document missing '{'"); | |
var style = comments().concat(rules()); | |
if (!close()) return error("@document missing '}'"); | |
return pos({ | |
type: 'document', | |
document: doc, | |
vendor: vendor, | |
rules: style | |
}); | |
} | |
/** | |
* Parse font-face. | |
*/ | |
function atfontface() { | |
var pos = position(); | |
var m = match(/^@font-face\s*/); | |
if (!m) return; | |
if (!open()) return error("@font-face missing '{'"); | |
var decls = comments(); | |
// declarations | |
var decl; | |
while (decl = declaration()) { | |
decls.push(decl); | |
decls = decls.concat(comments()); | |
} | |
if (!close()) return error("@font-face missing '}'"); | |
return pos({ | |
type: 'font-face', | |
declarations: decls | |
}); | |
} | |
/** | |
* Parse import | |
*/ | |
var atimport = _compileAtrule('import'); | |
/** | |
* Parse charset | |
*/ | |
var atcharset = _compileAtrule('charset'); | |
/** | |
* Parse namespace | |
*/ | |
var atnamespace = _compileAtrule('namespace'); | |
/** | |
* Parse non-block at-rules | |
*/ | |
function _compileAtrule(name) { | |
var re = new RegExp('^@' + name + '\\s*([^;]+);'); | |
return function() { | |
var pos = position(); | |
var m = match(re); | |
if (!m) return; | |
var ret = { type: name }; | |
ret[name] = m[1].trim(); | |
return pos(ret); | |
} | |
} | |
/** | |
* Parse at rule. | |
*/ | |
function atrule() { | |
if (css[0] != '@') return; | |
return atkeyframes() | |
|| atmedia() | |
|| atcustommedia() | |
|| atsupports() | |
|| atimport() | |
|| atcharset() | |
|| atnamespace() | |
|| atdocument() | |
|| atpage() | |
|| athost() | |
|| atfontface(); | |
} | |
/** | |
* Parse rule. | |
*/ | |
function rule() { | |
var pos = position(); | |
var sel = selector(); | |
if (!sel) return error('selector missing'); | |
comments(); | |
return pos({ | |
type: 'rule', | |
selectors: sel, | |
declarations: declarations() | |
}); | |
} | |
return addParent(stylesheet()); | |
}; | |
/** | |
* Trim `str`. | |
*/ | |
function trim(str) { | |
return str ? str.replace(/^\s+|\s+$/g, '') : ''; | |
} | |
/** | |
* Adds non-enumerable parent node reference to each node. | |
*/ | |
function addParent(obj, parent) { | |
var isNode = obj && typeof obj.type === 'string'; | |
var childParent = isNode ? obj : parent; | |
for (var k in obj) { | |
var value = obj[k]; | |
if (Array.isArray(value)) { | |
value.forEach(function(v) { addParent(v, childParent); }); | |
} else if (value && typeof value === 'object') { | |
addParent(value, childParent); | |
} | |
} | |
if (isNode) { | |
Object.defineProperty(obj, 'parent', { | |
configurable: true, | |
writable: true, | |
enumerable: false, | |
value: parent || null | |
}); | |
} | |
return obj; | |
} | |
},{}],158:[function(require,module,exports){ | |
/** | |
* Expose `Compiler`. | |
*/ | |
module.exports = Compiler; | |
/** | |
* Initialize a compiler. | |
* | |
* @param {Type} name | |
* @return {Type} | |
* @api public | |
*/ | |
function Compiler(opts) { | |
this.options = opts || {}; | |
} | |
/** | |
* Emit `str` | |
*/ | |
Compiler.prototype.emit = function(str) { | |
return str; | |
}; | |
/** | |
* Visit `node`. | |
*/ | |
Compiler.prototype.visit = function(node){ | |
return this[node.type](node); | |
}; | |
/** | |
* Map visit over array of `nodes`, optionally using a `delim` | |
*/ | |
Compiler.prototype.mapVisit = function(nodes, delim){ | |
var buf = ''; | |
delim = delim || ''; | |
for (var i = 0, length = nodes.length; i < length; i++) { | |
buf += this.visit(nodes[i]); | |
if (delim && i < length - 1) buf += this.emit(delim); | |
} | |
return buf; | |
}; | |
},{}],159:[function(require,module,exports){ | |
/** | |
* Module dependencies. | |
*/ | |
var Base = require('./compiler'); | |
var inherits = require('inherits'); | |
/** | |
* Expose compiler. | |
*/ | |
module.exports = Compiler; | |
/** | |
* Initialize a new `Compiler`. | |
*/ | |
function Compiler(options) { | |
Base.call(this, options); | |
} | |
/** | |
* Inherit from `Base.prototype`. | |
*/ | |
inherits(Compiler, Base); | |
/** | |
* Compile `node`. | |
*/ | |
Compiler.prototype.compile = function(node){ | |
return node.stylesheet | |
.rules.map(this.visit, this) | |
.join(''); | |
}; | |
/** | |
* Visit comment node. | |
*/ | |
Compiler.prototype.comment = function(node){ | |
return this.emit('', node.position); | |
}; | |
/** | |
* Visit import node. | |
*/ | |
Compiler.prototype.import = function(node){ | |
return this.emit('@import ' + node.import + ';', node.position); | |
}; | |
/** | |
* Visit media node. | |
*/ | |
Compiler.prototype.media = function(node){ | |
return this.emit('@media ' + node.media, node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.rules) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit document node. | |
*/ | |
Compiler.prototype.document = function(node){ | |
var doc = '@' + (node.vendor || '') + 'document ' + node.document; | |
return this.emit(doc, node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.rules) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit charset node. | |
*/ | |
Compiler.prototype.charset = function(node){ | |
return this.emit('@charset ' + node.charset + ';', node.position); | |
}; | |
/** | |
* Visit namespace node. | |
*/ | |
Compiler.prototype.namespace = function(node){ | |
return this.emit('@namespace ' + node.namespace + ';', node.position); | |
}; | |
/** | |
* Visit supports node. | |
*/ | |
Compiler.prototype.supports = function(node){ | |
return this.emit('@supports ' + node.supports, node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.rules) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit keyframes node. | |
*/ | |
Compiler.prototype.keyframes = function(node){ | |
return this.emit('@' | |
+ (node.vendor || '') | |
+ 'keyframes ' | |
+ node.name, node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.keyframes) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit keyframe node. | |
*/ | |
Compiler.prototype.keyframe = function(node){ | |
var decls = node.declarations; | |
return this.emit(node.values.join(','), node.position) | |
+ this.emit('{') | |
+ this.mapVisit(decls) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit page node. | |
*/ | |
Compiler.prototype.page = function(node){ | |
var sel = node.selectors.length | |
? node.selectors.join(', ') | |
: ''; | |
return this.emit('@page ' + sel, node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.declarations) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit font-face node. | |
*/ | |
Compiler.prototype['font-face'] = function(node){ | |
return this.emit('@font-face', node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.declarations) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit host node. | |
*/ | |
Compiler.prototype.host = function(node){ | |
return this.emit('@host', node.position) | |
+ this.emit('{') | |
+ this.mapVisit(node.rules) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit custom-media node. | |
*/ | |
Compiler.prototype['custom-media'] = function(node){ | |
return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); | |
}; | |
/** | |
* Visit rule node. | |
*/ | |
Compiler.prototype.rule = function(node){ | |
var decls = node.declarations; | |
if (!decls.length) return ''; | |
return this.emit(node.selectors.join(','), node.position) | |
+ this.emit('{') | |
+ this.mapVisit(decls) | |
+ this.emit('}'); | |
}; | |
/** | |
* Visit declaration node. | |
*/ | |
Compiler.prototype.declaration = function(node){ | |
return this.emit(node.property + ':' + node.value, node.position) + this.emit(';'); | |
}; | |
},{"./compiler":158,"inherits":216}],160:[function(require,module,exports){ | |
/** | |
* Module dependencies. | |
*/ | |
var Base = require('./compiler'); | |
var inherits = require('inherits'); | |
/** | |
* Expose compiler. | |
*/ | |
module.exports = Compiler; | |
/** | |
* Initialize a new `Compiler`. | |
*/ | |
function Compiler(options) { | |
options = options || {}; | |
Base.call(this, options); | |
this.indentation = options.indent; | |
} | |
/** | |
* Inherit from `Base.prototype`. | |
*/ | |
inherits(Compiler, Base); | |
/** | |
* Compile `node`. | |
*/ | |
Compiler.prototype.compile = function(node){ | |
return this.stylesheet(node); | |
}; | |
/** | |
* Visit stylesheet node. | |
*/ | |
Compiler.prototype.stylesheet = function(node){ | |
return this.mapVisit(node.stylesheet.rules, '\n\n'); | |
}; | |
/** | |
* Visit comment node. | |
*/ | |
Compiler.prototype.comment = function(node){ | |
return this.emit(this.indent() + '/*' + node.comment + '*/', node.position); | |
}; | |
/** | |
* Visit import node. | |
*/ | |
Compiler.prototype.import = function(node){ | |
return this.emit('@import ' + node.import + ';', node.position); | |
}; | |
/** | |
* Visit media node. | |
*/ | |
Compiler.prototype.media = function(node){ | |
return this.emit('@media ' + node.media, node.position) | |
+ this.emit( | |
' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(node.rules, '\n\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '\n}'); | |
}; | |
/** | |
* Visit document node. | |
*/ | |
Compiler.prototype.document = function(node){ | |
var doc = '@' + (node.vendor || '') + 'document ' + node.document; | |
return this.emit(doc, node.position) | |
+ this.emit( | |
' ' | |
+ ' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(node.rules, '\n\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '\n}'); | |
}; | |
/** | |
* Visit charset node. | |
*/ | |
Compiler.prototype.charset = function(node){ | |
return this.emit('@charset ' + node.charset + ';', node.position); | |
}; | |
/** | |
* Visit namespace node. | |
*/ | |
Compiler.prototype.namespace = function(node){ | |
return this.emit('@namespace ' + node.namespace + ';', node.position); | |
}; | |
/** | |
* Visit supports node. | |
*/ | |
Compiler.prototype.supports = function(node){ | |
return this.emit('@supports ' + node.supports, node.position) | |
+ this.emit( | |
' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(node.rules, '\n\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '\n}'); | |
}; | |
/** | |
* Visit keyframes node. | |
*/ | |
Compiler.prototype.keyframes = function(node){ | |
return this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position) | |
+ this.emit( | |
' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(node.keyframes, '\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '}'); | |
}; | |
/** | |
* Visit keyframe node. | |
*/ | |
Compiler.prototype.keyframe = function(node){ | |
var decls = node.declarations; | |
return this.emit(this.indent()) | |
+ this.emit(node.values.join(', '), node.position) | |
+ this.emit( | |
' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(decls, '\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '\n' | |
+ this.indent() + '}\n'); | |
}; | |
/** | |
* Visit page node. | |
*/ | |
Compiler.prototype.page = function(node){ | |
var sel = node.selectors.length | |
? node.selectors.join(', ') + ' ' | |
: ''; | |
return this.emit('@page ' + sel, node.position) | |
+ this.emit('{\n') | |
+ this.emit(this.indent(1)) | |
+ this.mapVisit(node.declarations, '\n') | |
+ this.emit(this.indent(-1)) | |
+ this.emit('\n}'); | |
}; | |
/** | |
* Visit font-face node. | |
*/ | |
Compiler.prototype['font-face'] = function(node){ | |
return this.emit('@font-face ', node.position) | |
+ this.emit('{\n') | |
+ this.emit(this.indent(1)) | |
+ this.mapVisit(node.declarations, '\n') | |
+ this.emit(this.indent(-1)) | |
+ this.emit('\n}'); | |
}; | |
/** | |
* Visit host node. | |
*/ | |
Compiler.prototype.host = function(node){ | |
return this.emit('@host', node.position) | |
+ this.emit( | |
' {\n' | |
+ this.indent(1)) | |
+ this.mapVisit(node.rules, '\n\n') | |
+ this.emit( | |
this.indent(-1) | |
+ '\n}'); | |
}; | |
/** | |
* Visit custom-media node. | |
*/ | |
Compiler.prototype['custom-media'] = function(node){ | |
return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); | |
}; | |
/** | |
* Visit rule node. | |
*/ | |
Compiler.prototype.rule = function(node){ | |
var indent = this.indent(); | |
var decls = node.declarations; | |
if (!decls.length) return ''; | |
return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position) | |
+ this.emit(' {\n') | |
+ this.emit(this.indent(1)) | |
+ this.mapVisit(decls, '\n') | |
+ this.emit(this.indent(-1)) | |
+ this.emit('\n' + this.indent() + '}'); | |
}; | |
/** | |
* Visit declaration node. | |
*/ | |
Compiler.prototype.declaration = function(node){ | |
return this.emit(this.indent()) | |
+ this.emit(node.property + ': ' + node.value, node.position) | |
+ this.emit(';'); | |
}; | |
/** | |
* Increase, decrease or return current indentation. | |
*/ | |
Compiler.prototype.indent = function(level) { | |
this.level = this.level || 1; | |
if (null != level) { | |
this.level += level; | |
return ''; | |
} | |
return Array(this.level).join(this.indentation || ' '); | |
}; | |
},{"./compiler":158,"inherits":216}],161:[function(require,module,exports){ | |
/** | |
* Module dependencies. | |
*/ | |
var Compressed = require('./compress'); | |
var Identity = require('./identity'); | |
/** | |
* Stringfy the given AST `node`. | |
* | |
* Options: | |
* | |
* - `compress` space-optimized output | |
* - `sourcemap` return an object with `.code` and `.map` | |
* | |
* @param {Object} node | |
* @param {Object} [options] | |
* @return {String} | |
* @api public | |
*/ | |
module.exports = function(node, options){ | |
options = options || {}; | |
var compiler = options.compress | |
? new Compressed(options) | |
: new Identity(options); | |
// source maps | |
if (options.sourcemap) { | |
var sourcemaps = require('./source-map-support'); | |
sourcemaps(compiler); | |
var code = compiler.compile(node); | |
compiler.applySourceMaps(); | |
var map = options.sourcemap === 'generator' | |
? compiler.map | |
: compiler.map.toJSON(); | |
return { code: code, map: map }; | |
} | |
var code = compiler.compile(node); | |
return code; | |
}; | |
},{"./compress":159,"./identity":160,"./source-map-support":162}],162:[function(require,module,exports){ | |
/** | |
* Module dependencies. | |
*/ | |
var SourceMap = require('source-map').SourceMapGenerator; | |
var SourceMapConsumer = require('source-map').SourceMapConsumer; | |
var sourceMapResolve = require('source-map-resolve'); | |
var urix = require('urix'); | |
var fs = require('fs'); | |
var path = require('path'); | |
/** | |
* Expose `mixin()`. | |
*/ | |
module.exports = mixin; | |
/** | |
* Mixin source map support into `compiler`. | |
* | |
* @param {Compiler} compiler | |
* @api public | |
*/ | |
function mixin(compiler) { | |
compiler._comment = compiler.comment; | |
compiler.map = new SourceMap(); | |
compiler.position = { line: 1, column: 1 }; | |
compiler.files = {}; | |
for (var k in exports) compiler[k] = exports[k]; | |
} | |
/** | |
* Update position. | |
* | |
* @param {String} str | |
* @api private | |
*/ | |
exports.updatePosition = function(str) { | |
var lines = str.match(/\n/g); | |
if (lines) this.position.line += lines.length; | |
var i = str.lastIndexOf('\n'); | |
this.position.column = ~i ? str.length - i : this.position.column + str.length; | |
}; | |
/** | |
* Emit `str`. | |
* | |
* @param {String} str | |
* @param {Object} [pos] | |
* @return {String} | |
* @api private | |
*/ | |
exports.emit = function(str, pos) { | |
if (pos) { | |
var sourceFile = urix(pos.source || 'source.css'); | |
this.map.addMapping({ | |
source: sourceFile, | |
generated: { | |
line: this.position.line, | |
column: Math.max(this.position.column - 1, 0) | |
}, | |
original: { | |
line: pos.start.line, | |
column: pos.start.column - 1 | |
} | |
}); | |
this.addFile(sourceFile, pos); | |
} | |
this.updatePosition(str); | |
return str; | |
}; | |
/** | |
* Adds a file to the source map output if it has not already been added | |
* @param {String} file | |
* @param {Object} pos | |
*/ | |
exports.addFile = function(file, pos) { | |
if (typeof pos.content !== 'string') return; | |
if (Object.prototype.hasOwnProperty.call(this.files, file)) return; | |
this.files[file] = pos.content; | |
}; | |
/** | |
* Applies any original source maps to the output and embeds the source file | |
* contents in the source map. | |
*/ | |
exports.applySourceMaps = function() { | |
Object.keys(this.files).forEach(function(file) { | |
var content = this.files[file]; | |
this.map.setSourceContent(file, content); | |
if (this.options.inputSourcemaps !== false) { | |
var originalMap = sourceMapResolve.resolveSync( | |
content, file, fs.readFileSync); | |
if (originalMap) { | |
var map = new SourceMapConsumer(originalMap.map); | |
var relativeTo = originalMap.sourcesRelativeTo; | |
this.map.applySourceMap(map, file, urix(path.dirname(relativeTo))); | |
} | |
} | |
}, this); | |
}; | |
/** | |
* Process comments, drops sourceMap comments. | |
* @param {Object} node | |
*/ | |
exports.comment = function(node) { | |
if (/^# sourceMappingURL=/.test(node.comment)) | |
return this.emit('', node.position); | |
else | |
return this._comment(node); | |
}; | |
},{"fs":394,"path":397,"source-map":163,"source-map-resolve":328,"urix":391}],163:[function(require,module,exports){ | |
/* | |
* Copyright 2009-2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE.txt or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; | |
exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; | |
exports.SourceNode = require('./source-map/source-node').SourceNode; | |
},{"./source-map/source-map-consumer":169,"./source-map/source-map-generator":170,"./source-map/source-node":171}],164:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var util = require('./util'); | |
/** | |
* A data structure which is a combination of an array and a set. Adding a new | |
* member is O(1), testing for membership is O(1), and finding the index of an | |
* element is O(1). Removing elements from the set is not supported. Only | |
* strings are supported for membership. | |
*/ | |
function ArraySet() { | |
this._array = []; | |
this._set = {}; | |
} | |
/** | |
* Static method for creating ArraySet instances from an existing array. | |
*/ | |
ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { | |
var set = new ArraySet(); | |
for (var i = 0, len = aArray.length; i < len; i++) { | |
set.add(aArray[i], aAllowDuplicates); | |
} | |
return set; | |
}; | |
/** | |
* Add the given string to this set. | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { | |
var isDuplicate = this.has(aStr); | |
var idx = this._array.length; | |
if (!isDuplicate || aAllowDuplicates) { | |
this._array.push(aStr); | |
} | |
if (!isDuplicate) { | |
this._set[util.toSetString(aStr)] = idx; | |
} | |
}; | |
/** | |
* Is the given string a member of this set? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.has = function ArraySet_has(aStr) { | |
return Object.prototype.hasOwnProperty.call(this._set, | |
util.toSetString(aStr)); | |
}; | |
/** | |
* What is the index of the given string in the array? | |
* | |
* @param String aStr | |
*/ | |
ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { | |
if (this.has(aStr)) { | |
return this._set[util.toSetString(aStr)]; | |
} | |
throw new Error('"' + aStr + '" is not in the set.'); | |
}; | |
/** | |
* What is the element at the given index? | |
* | |
* @param Number aIdx | |
*/ | |
ArraySet.prototype.at = function ArraySet_at(aIdx) { | |
if (aIdx >= 0 && aIdx < this._array.length) { | |
return this._array[aIdx]; | |
} | |
throw new Error('No element indexed by ' + aIdx); | |
}; | |
/** | |
* Returns the array representation of this set (which has the proper indices | |
* indicated by indexOf). Note that this is a copy of the internal array used | |
* for storing the members so that no one can mess with internal state. | |
*/ | |
ArraySet.prototype.toArray = function ArraySet_toArray() { | |
return this._array.slice(); | |
}; | |
exports.ArraySet = ArraySet; | |
}); | |
},{"./util":172,"amdefine":2}],165:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
* | |
* Based on the Base 64 VLQ implementation in Closure Compiler: | |
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java | |
* | |
* Copyright 2011 The Closure Compiler Authors. All rights reserved. | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* * Redistributions in binary form must reproduce the above | |
* copyright notice, this list of conditions and the following | |
* disclaimer in the documentation and/or other materials provided | |
* with the distribution. | |
* * Neither the name of Google Inc. nor the names of its | |
* contributors may be used to endorse or promote products derived | |
* from this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var base64 = require('./base64'); | |
// A single base 64 digit can contain 6 bits of data. For the base 64 variable | |
// length quantities we use in the source map spec, the first bit is the sign, | |
// the next four bits are the actual value, and the 6th bit is the | |
// continuation bit. The continuation bit tells us whether there are more | |
// digits in this value following this digit. | |
// | |
// Continuation | |
// | Sign | |
// | | | |
// V V | |
// 101011 | |
var VLQ_BASE_SHIFT = 5; | |
// binary: 100000 | |
var VLQ_BASE = 1 << VLQ_BASE_SHIFT; | |
// binary: 011111 | |
var VLQ_BASE_MASK = VLQ_BASE - 1; | |
// binary: 100000 | |
var VLQ_CONTINUATION_BIT = VLQ_BASE; | |
/** | |
* Converts from a two-complement value to a value where the sign bit is | |
* placed in the least significant bit. For example, as decimals: | |
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) | |
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) | |
*/ | |
function toVLQSigned(aValue) { | |
return aValue < 0 | |
? ((-aValue) << 1) + 1 | |
: (aValue << 1) + 0; | |
} | |
/** | |
* Converts to a two-complement value from a value where the sign bit is | |
* placed in the least significant bit. For example, as decimals: | |
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 | |
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 | |
*/ | |
function fromVLQSigned(aValue) { | |
var isNegative = (aValue & 1) === 1; | |
var shifted = aValue >> 1; | |
return isNegative | |
? -shifted | |
: shifted; | |
} | |
/** | |
* Returns the base 64 VLQ encoded value. | |
*/ | |
exports.encode = function base64VLQ_encode(aValue) { | |
var encoded = ""; | |
var digit; | |
var vlq = toVLQSigned(aValue); | |
do { | |
digit = vlq & VLQ_BASE_MASK; | |
vlq >>>= VLQ_BASE_SHIFT; | |
if (vlq > 0) { | |
// There are still more digits in this value, so we must make sure the | |
// continuation bit is marked. | |
digit |= VLQ_CONTINUATION_BIT; | |
} | |
encoded += base64.encode(digit); | |
} while (vlq > 0); | |
return encoded; | |
}; | |
/** | |
* Decodes the next base 64 VLQ value from the given string and returns the | |
* value and the rest of the string via the out parameter. | |
*/ | |
exports.decode = function base64VLQ_decode(aStr, aOutParam) { | |
var i = 0; | |
var strLen = aStr.length; | |
var result = 0; | |
var shift = 0; | |
var continuation, digit; | |
do { | |
if (i >= strLen) { | |
throw new Error("Expected more digits in base 64 VLQ value."); | |
} | |
digit = base64.decode(aStr.charAt(i++)); | |
continuation = !!(digit & VLQ_CONTINUATION_BIT); | |
digit &= VLQ_BASE_MASK; | |
result = result + (digit << shift); | |
shift += VLQ_BASE_SHIFT; | |
} while (continuation); | |
aOutParam.value = fromVLQSigned(result); | |
aOutParam.rest = aStr.slice(i); | |
}; | |
}); | |
},{"./base64":166,"amdefine":2}],166:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var charToIntMap = {}; | |
var intToCharMap = {}; | |
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
.split('') | |
.forEach(function (ch, index) { | |
charToIntMap[ch] = index; | |
intToCharMap[index] = ch; | |
}); | |
/** | |
* Encode an integer in the range of 0 to 63 to a single base 64 digit. | |
*/ | |
exports.encode = function base64_encode(aNumber) { | |
if (aNumber in intToCharMap) { | |
return intToCharMap[aNumber]; | |
} | |
throw new TypeError("Must be between 0 and 63: " + aNumber); | |
}; | |
/** | |
* Decode a single base 64 digit to an integer. | |
*/ | |
exports.decode = function base64_decode(aChar) { | |
if (aChar in charToIntMap) { | |
return charToIntMap[aChar]; | |
} | |
throw new TypeError("Not a valid base 64 digit: " + aChar); | |
}; | |
}); | |
},{"amdefine":2}],167:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
/** | |
* Recursive implementation of binary search. | |
* | |
* @param aLow Indices here and lower do not contain the needle. | |
* @param aHigh Indices here and higher do not contain the needle. | |
* @param aNeedle The element being searched for. | |
* @param aHaystack The non-empty array being searched. | |
* @param aCompare Function which takes two elements and returns -1, 0, or 1. | |
*/ | |
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { | |
// This function terminates when one of the following is true: | |
// | |
// 1. We find the exact element we are looking for. | |
// | |
// 2. We did not find the exact element, but we can return the index of | |
// the next closest element that is less than that element. | |
// | |
// 3. We did not find the exact element, and there is no next-closest | |
// element which is less than the one we are searching for, so we | |
// return -1. | |
var mid = Math.floor((aHigh - aLow) / 2) + aLow; | |
var cmp = aCompare(aNeedle, aHaystack[mid], true); | |
if (cmp === 0) { | |
// Found the element we are looking for. | |
return mid; | |
} | |
else if (cmp > 0) { | |
// aHaystack[mid] is greater than our needle. | |
if (aHigh - mid > 1) { | |
// The element is in the upper half. | |
return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); | |
} | |
// We did not find an exact match, return the next closest one | |
// (termination case 2). | |
return mid; | |
} | |
else { | |
// aHaystack[mid] is less than our needle. | |
if (mid - aLow > 1) { | |
// The element is in the lower half. | |
return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); | |
} | |
// The exact needle element was not found in this haystack. Determine if | |
// we are in termination case (2) or (3) and return the appropriate thing. | |
return aLow < 0 ? -1 : aLow; | |
} | |
} | |
/** | |
* This is an implementation of binary search which will always try and return | |
* the index of next lowest value checked if there is no exact hit. This is | |
* because mappings between original and generated line/col pairs are single | |
* points, and there is an implicit region between each of them, so a miss | |
* just means that you aren't on the very start of a region. | |
* | |
* @param aNeedle The element you are looking for. | |
* @param aHaystack The array that is being searched. | |
* @param aCompare A function which takes the needle and an element in the | |
* array and returns -1, 0, or 1 depending on whether the needle is less | |
* than, equal to, or greater than the element, respectively. | |
*/ | |
exports.search = function search(aNeedle, aHaystack, aCompare) { | |
if (aHaystack.length === 0) { | |
return -1; | |
} | |
return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) | |
}; | |
}); | |
},{"amdefine":2}],168:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2014 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var util = require('./util'); | |
/** | |
* Determine whether mappingB is after mappingA with respect to generated | |
* position. | |
*/ | |
function generatedPositionAfter(mappingA, mappingB) { | |
// Optimized for most common case | |
var lineA = mappingA.generatedLine; | |
var lineB = mappingB.generatedLine; | |
var columnA = mappingA.generatedColumn; | |
var columnB = mappingB.generatedColumn; | |
return lineB > lineA || lineB == lineA && columnB >= columnA || | |
util.compareByGeneratedPositions(mappingA, mappingB) <= 0; | |
} | |
/** | |
* A data structure to provide a sorted view of accumulated mappings in a | |
* performance conscious manner. It trades a neglibable overhead in general | |
* case for a large speedup in case of mappings being added in order. | |
*/ | |
function MappingList() { | |
this._array = []; | |
this._sorted = true; | |
// Serves as infimum | |
this._last = {generatedLine: -1, generatedColumn: 0}; | |
} | |
/** | |
* Iterate through internal items. This method takes the same arguments that | |
* `Array.prototype.forEach` takes. | |
* | |
* NOTE: The order of the mappings is NOT guaranteed. | |
*/ | |
MappingList.prototype.unsortedForEach = | |
function MappingList_forEach(aCallback, aThisArg) { | |
this._array.forEach(aCallback, aThisArg); | |
}; | |
/** | |
* Add the given source mapping. | |
* | |
* @param Object aMapping | |
*/ | |
MappingList.prototype.add = function MappingList_add(aMapping) { | |
var mapping; | |
if (generatedPositionAfter(this._last, aMapping)) { | |
this._last = aMapping; | |
this._array.push(aMapping); | |
} else { | |
this._sorted = false; | |
this._array.push(aMapping); | |
} | |
}; | |
/** | |
* Returns the flat, sorted array of mappings. The mappings are sorted by | |
* generated position. | |
* | |
* WARNING: This method returns internal data without copying, for | |
* performance. The return value must NOT be mutated, and should be treated as | |
* an immutable borrow. If you want to take ownership, you must make your own | |
* copy. | |
*/ | |
MappingList.prototype.toArray = function MappingList_toArray() { | |
if (!this._sorted) { | |
this._array.sort(util.compareByGeneratedPositions); | |
this._sorted = true; | |
} | |
return this._array; | |
}; | |
exports.MappingList = MappingList; | |
}); | |
},{"./util":172,"amdefine":2}],169:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var util = require('./util'); | |
var binarySearch = require('./binary-search'); | |
var ArraySet = require('./array-set').ArraySet; | |
var base64VLQ = require('./base64-vlq'); | |
/** | |
* A SourceMapConsumer instance represents a parsed source map which we can | |
* query for information about the original file positions by giving it a file | |
* position in the generated source. | |
* | |
* The only parameter is the raw source map (either as a JSON string, or | |
* already parsed to an object). According to the spec, source maps have the | |
* following attributes: | |
* | |
* - version: Which version of the source map spec this map is following. | |
* - sources: An array of URLs to the original source files. | |
* - names: An array of identifiers which can be referrenced by individual mappings. | |
* - sourceRoot: Optional. The URL root from which all sources are relative. | |
* - sourcesContent: Optional. An array of contents of the original source files. | |
* - mappings: A string of base64 VLQs which contain the actual mappings. | |
* - file: Optional. The generated file this source map is associated with. | |
* | |
* Here is an example source map, taken from the source map spec[0]: | |
* | |
* { | |
* version : 3, | |
* file: "out.js", | |
* sourceRoot : "", | |
* sources: ["foo.js", "bar.js"], | |
* names: ["src", "maps", "are", "fun"], | |
* mappings: "AA,AB;;ABCDE;" | |
* } | |
* | |
* [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# | |
*/ | |
function SourceMapConsumer(aSourceMap) { | |
var sourceMap = aSourceMap; | |
if (typeof aSourceMap === 'string') { | |
sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); | |
} | |
var version = util.getArg(sourceMap, 'version'); | |
var sources = util.getArg(sourceMap, 'sources'); | |
// Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which | |
// requires the array) to play nice here. | |
var names = util.getArg(sourceMap, 'names', []); | |
var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); | |
var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); | |
var mappings = util.getArg(sourceMap, 'mappings'); | |
var file = util.getArg(sourceMap, 'file', null); | |
// Once again, Sass deviates from the spec and supplies the version as a | |
// string rather than a number, so we use loose equality checking here. | |
if (version != this._version) { | |
throw new Error('Unsupported version: ' + version); | |
} | |
// Some source maps produce relative source paths like "./foo.js" instead of | |
// "foo.js". Normalize these first so that future comparisons will succeed. | |
// See bugzil.la/1090768. | |
sources = sources.map(util.normalize); | |
// Pass `true` below to allow duplicate names and sources. While source maps | |
// are intended to be compressed and deduplicated, the TypeScript compiler | |
// sometimes generates source maps with duplicates in them. See Github issue | |
// #72 and bugzil.la/889492. | |
this._names = ArraySet.fromArray(names, true); | |
this._sources = ArraySet.fromArray(sources, true); | |
this.sourceRoot = sourceRoot; | |
this.sourcesContent = sourcesContent; | |
this._mappings = mappings; | |
this.file = file; | |
} | |
/** | |
* Create a SourceMapConsumer from a SourceMapGenerator. | |
* | |
* @param SourceMapGenerator aSourceMap | |
* The source map that will be consumed. | |
* @returns SourceMapConsumer | |
*/ | |
SourceMapConsumer.fromSourceMap = | |
function SourceMapConsumer_fromSourceMap(aSourceMap) { | |
var smc = Object.create(SourceMapConsumer.prototype); | |
smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); | |
smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); | |
smc.sourceRoot = aSourceMap._sourceRoot; | |
smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), | |
smc.sourceRoot); | |
smc.file = aSourceMap._file; | |
smc.__generatedMappings = aSourceMap._mappings.toArray().slice(); | |
smc.__originalMappings = aSourceMap._mappings.toArray().slice() | |
.sort(util.compareByOriginalPositions); | |
return smc; | |
}; | |
/** | |
* The version of the source mapping spec that we are consuming. | |
*/ | |
SourceMapConsumer.prototype._version = 3; | |
/** | |
* The list of original sources. | |
*/ | |
Object.defineProperty(SourceMapConsumer.prototype, 'sources', { | |
get: function () { | |
return this._sources.toArray().map(function (s) { | |
return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; | |
}, this); | |
} | |
}); | |
// `__generatedMappings` and `__originalMappings` are arrays that hold the | |
// parsed mapping coordinates from the source map's "mappings" attribute. They | |
// are lazily instantiated, accessed via the `_generatedMappings` and | |
// `_originalMappings` getters respectively, and we only parse the mappings | |
// and create these arrays once queried for a source location. We jump through | |
// these hoops because there can be many thousands of mappings, and parsing | |
// them is expensive, so we only want to do it if we must. | |
// | |
// Each object in the arrays is of the form: | |
// | |
// { | |
// generatedLine: The line number in the generated code, | |
// generatedColumn: The column number in the generated code, | |
// source: The path to the original source file that generated this | |
// chunk of code, | |
// originalLine: The line number in the original source that | |
// corresponds to this chunk of generated code, | |
// originalColumn: The column number in the original source that | |
// corresponds to this chunk of generated code, | |
// name: The name of the original symbol which generated this chunk of | |
// code. | |
// } | |
// | |
// All properties except for `generatedLine` and `generatedColumn` can be | |
// `null`. | |
// | |
// `_generatedMappings` is ordered by the generated positions. | |
// | |
// `_originalMappings` is ordered by the original positions. | |
SourceMapConsumer.prototype.__generatedMappings = null; | |
Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { | |
get: function () { | |
if (!this.__generatedMappings) { | |
this.__generatedMappings = []; | |
this.__originalMappings = []; | |
this._parseMappings(this._mappings, this.sourceRoot); | |
} | |
return this.__generatedMappings; | |
} | |
}); | |
SourceMapConsumer.prototype.__originalMappings = null; | |
Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { | |
get: function () { | |
if (!this.__originalMappings) { | |
this.__generatedMappings = []; | |
this.__originalMappings = []; | |
this._parseMappings(this._mappings, this.sourceRoot); | |
} | |
return this.__originalMappings; | |
} | |
}); | |
SourceMapConsumer.prototype._nextCharIsMappingSeparator = | |
function SourceMapConsumer_nextCharIsMappingSeparator(aStr) { | |
var c = aStr.charAt(0); | |
return c === ";" || c === ","; | |
}; | |
/** | |
* Parse the mappings in a string in to a data structure which we can easily | |
* query (the ordered arrays in the `this.__generatedMappings` and | |
* `this.__originalMappings` properties). | |
*/ | |
SourceMapConsumer.prototype._parseMappings = | |
function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { | |
var generatedLine = 1; | |
var previousGeneratedColumn = 0; | |
var previousOriginalLine = 0; | |
var previousOriginalColumn = 0; | |
var previousSource = 0; | |
var previousName = 0; | |
var str = aStr; | |
var temp = {}; | |
var mapping; | |
while (str.length > 0) { | |
if (str.charAt(0) === ';') { | |
generatedLine++; | |
str = str.slice(1); | |
previousGeneratedColumn = 0; | |
} | |
else if (str.charAt(0) === ',') { | |
str = str.slice(1); | |
} | |
else { | |
mapping = {}; | |
mapping.generatedLine = generatedLine; | |
// Generated column. | |
base64VLQ.decode(str, temp); | |
mapping.generatedColumn = previousGeneratedColumn + temp.value; | |
previousGeneratedColumn = mapping.generatedColumn; | |
str = temp.rest; | |
if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { | |
// Original source. | |
base64VLQ.decode(str, temp); | |
mapping.source = this._sources.at(previousSource + temp.value); | |
previousSource += temp.value; | |
str = temp.rest; | |
if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { | |
throw new Error('Found a source, but no line and column'); | |
} | |
// Original line. | |
base64VLQ.decode(str, temp); | |
mapping.originalLine = previousOriginalLine + temp.value; | |
previousOriginalLine = mapping.originalLine; | |
// Lines are stored 0-based | |
mapping.originalLine += 1; | |
str = temp.rest; | |
if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { | |
throw new Error('Found a source and line, but no column'); | |
} | |
// Original column. | |
base64VLQ.decode(str, temp); | |
mapping.originalColumn = previousOriginalColumn + temp.value; | |
previousOriginalColumn = mapping.originalColumn; | |
str = temp.rest; | |
if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { | |
// Original name. | |
base64VLQ.decode(str, temp); | |
mapping.name = this._names.at(previousName + temp.value); | |
previousName += temp.value; | |
str = temp.rest; | |
} | |
} | |
this.__generatedMappings.push(mapping); | |
if (typeof mapping.originalLine === 'number') { | |
this.__originalMappings.push(mapping); | |
} | |
} | |
} | |
this.__generatedMappings.sort(util.compareByGeneratedPositions); | |
this.__originalMappings.sort(util.compareByOriginalPositions); | |
}; | |
/** | |
* Find the mapping that best matches the hypothetical "needle" mapping that | |
* we are searching for in the given "haystack" of mappings. | |
*/ | |
SourceMapConsumer.prototype._findMapping = | |
function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, | |
aColumnName, aComparator) { | |
// To return the position we are searching for, we must first find the | |
// mapping for the given position and then return the opposite position it | |
// points to. Because the mappings are sorted, we can use binary search to | |
// find the best mapping. | |
if (aNeedle[aLineName] <= 0) { | |
throw new TypeError('Line must be greater than or equal to 1, got ' | |
+ aNeedle[aLineName]); | |
} | |
if (aNeedle[aColumnName] < 0) { | |
throw new TypeError('Column must be greater than or equal to 0, got ' | |
+ aNeedle[aColumnName]); | |
} | |
return binarySearch.search(aNeedle, aMappings, aComparator); | |
}; | |
/** | |
* Compute the last column for each generated mapping. The last column is | |
* inclusive. | |
*/ | |
SourceMapConsumer.prototype.computeColumnSpans = | |
function SourceMapConsumer_computeColumnSpans() { | |
for (var index = 0; index < this._generatedMappings.length; ++index) { | |
var mapping = this._generatedMappings[index]; | |
// Mappings do not contain a field for the last generated columnt. We | |
// can come up with an optimistic estimate, however, by assuming that | |
// mappings are contiguous (i.e. given two consecutive mappings, the | |
// first mapping ends where the second one starts). | |
if (index + 1 < this._generatedMappings.length) { | |
var nextMapping = this._generatedMappings[index + 1]; | |
if (mapping.generatedLine === nextMapping.generatedLine) { | |
mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; | |
continue; | |
} | |
} | |
// The last mapping for each line spans the entire line. | |
mapping.lastGeneratedColumn = Infinity; | |
} | |
}; | |
/** | |
* Returns the original source, line, and column information for the generated | |
* source's line and column positions provided. The only argument is an object | |
* with the following properties: | |
* | |
* - line: The line number in the generated source. | |
* - column: The column number in the generated source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - source: The original source file, or null. | |
* - line: The line number in the original source, or null. | |
* - column: The column number in the original source, or null. | |
* - name: The original identifier, or null. | |
*/ | |
SourceMapConsumer.prototype.originalPositionFor = | |
function SourceMapConsumer_originalPositionFor(aArgs) { | |
var needle = { | |
generatedLine: util.getArg(aArgs, 'line'), | |
generatedColumn: util.getArg(aArgs, 'column') | |
}; | |
var index = this._findMapping(needle, | |
this._generatedMappings, | |
"generatedLine", | |
"generatedColumn", | |
util.compareByGeneratedPositions); | |
if (index >= 0) { | |
var mapping = this._generatedMappings[index]; | |
if (mapping.generatedLine === needle.generatedLine) { | |
var source = util.getArg(mapping, 'source', null); | |
if (source != null && this.sourceRoot != null) { | |
source = util.join(this.sourceRoot, source); | |
} | |
return { | |
source: source, | |
line: util.getArg(mapping, 'originalLine', null), | |
column: util.getArg(mapping, 'originalColumn', null), | |
name: util.getArg(mapping, 'name', null) | |
}; | |
} | |
} | |
return { | |
source: null, | |
line: null, | |
column: null, | |
name: null | |
}; | |
}; | |
/** | |
* Returns the original source content. The only argument is the url of the | |
* original source file. Returns null if no original source content is | |
* availible. | |
*/ | |
SourceMapConsumer.prototype.sourceContentFor = | |
function SourceMapConsumer_sourceContentFor(aSource) { | |
if (!this.sourcesContent) { | |
return null; | |
} | |
if (this.sourceRoot != null) { | |
aSource = util.relative(this.sourceRoot, aSource); | |
} | |
if (this._sources.has(aSource)) { | |
return this.sourcesContent[this._sources.indexOf(aSource)]; | |
} | |
var url; | |
if (this.sourceRoot != null | |
&& (url = util.urlParse(this.sourceRoot))) { | |
// XXX: file:// URIs and absolute paths lead to unexpected behavior for | |
// many users. We can help them out when they expect file:// URIs to | |
// behave like it would if they were running a local HTTP server. See | |
// https://bugzilla.mozilla.org/show_bug.cgi?id=885597. | |
var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); | |
if (url.scheme == "file" | |
&& this._sources.has(fileUriAbsPath)) { | |
return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] | |
} | |
if ((!url.path || url.path == "/") | |
&& this._sources.has("/" + aSource)) { | |
return this.sourcesContent[this._sources.indexOf("/" + aSource)]; | |
} | |
} | |
throw new Error('"' + aSource + '" is not in the SourceMap.'); | |
}; | |
/** | |
* Returns the generated line and column information for the original source, | |
* line, and column positions provided. The only argument is an object with | |
* the following properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* - column: The column number in the original source. | |
* | |
* and an object is returned with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
SourceMapConsumer.prototype.generatedPositionFor = | |
function SourceMapConsumer_generatedPositionFor(aArgs) { | |
var needle = { | |
source: util.getArg(aArgs, 'source'), | |
originalLine: util.getArg(aArgs, 'line'), | |
originalColumn: util.getArg(aArgs, 'column') | |
}; | |
if (this.sourceRoot != null) { | |
needle.source = util.relative(this.sourceRoot, needle.source); | |
} | |
var index = this._findMapping(needle, | |
this._originalMappings, | |
"originalLine", | |
"originalColumn", | |
util.compareByOriginalPositions); | |
if (index >= 0) { | |
var mapping = this._originalMappings[index]; | |
return { | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null), | |
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) | |
}; | |
} | |
return { | |
line: null, | |
column: null, | |
lastColumn: null | |
}; | |
}; | |
/** | |
* Returns all generated line and column information for the original source | |
* and line provided. The only argument is an object with the following | |
* properties: | |
* | |
* - source: The filename of the original source. | |
* - line: The line number in the original source. | |
* | |
* and an array of objects is returned, each with the following properties: | |
* | |
* - line: The line number in the generated source, or null. | |
* - column: The column number in the generated source, or null. | |
*/ | |
SourceMapConsumer.prototype.allGeneratedPositionsFor = | |
function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { | |
// When there is no exact match, SourceMapConsumer.prototype._findMapping | |
// returns the index of the closest mapping less than the needle. By | |
// setting needle.originalColumn to Infinity, we thus find the last | |
// mapping for the given line, provided such a mapping exists. | |
var needle = { | |
source: util.getArg(aArgs, 'source'), | |
originalLine: util.getArg(aArgs, 'line'), | |
originalColumn: Infinity | |
}; | |
if (this.sourceRoot != null) { | |
needle.source = util.relative(this.sourceRoot, needle.source); | |
} | |
var mappings = []; | |
var index = this._findMapping(needle, | |
this._originalMappings, | |
"originalLine", | |
"originalColumn", | |
util.compareByOriginalPositions); | |
if (index >= 0) { | |
var mapping = this._originalMappings[index]; | |
while (mapping && mapping.originalLine === needle.originalLine) { | |
mappings.push({ | |
line: util.getArg(mapping, 'generatedLine', null), | |
column: util.getArg(mapping, 'generatedColumn', null), | |
lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) | |
}); | |
mapping = this._originalMappings[--index]; | |
} | |
} | |
return mappings.reverse(); | |
}; | |
SourceMapConsumer.GENERATED_ORDER = 1; | |
SourceMapConsumer.ORIGINAL_ORDER = 2; | |
/** | |
* Iterate over each mapping between an original source/line/column and a | |
* generated line/column in this source map. | |
* | |
* @param Function aCallback | |
* The function that is called with each mapping. | |
* @param Object aContext | |
* Optional. If specified, this object will be the value of `this` every | |
* time that `aCallback` is called. | |
* @param aOrder | |
* Either `SourceMapConsumer.GENERATED_ORDER` or | |
* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to | |
* iterate over the mappings sorted by the generated file's line/column | |
* order or the original's source/line/column order, respectively. Defaults to | |
* `SourceMapConsumer.GENERATED_ORDER`. | |
*/ | |
SourceMapConsumer.prototype.eachMapping = | |
function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { | |
var context = aContext || null; | |
var order = aOrder || SourceMapConsumer.GENERATED_ORDER; | |
var mappings; | |
switch (order) { | |
case SourceMapConsumer.GENERATED_ORDER: | |
mappings = this._generatedMappings; | |
break; | |
case SourceMapConsumer.ORIGINAL_ORDER: | |
mappings = this._originalMappings; | |
break; | |
default: | |
throw new Error("Unknown order of iteration."); | |
} | |
var sourceRoot = this.sourceRoot; | |
mappings.map(function (mapping) { | |
var source = mapping.source; | |
if (source != null && sourceRoot != null) { | |
source = util.join(sourceRoot, source); | |
} | |
return { | |
source: source, | |
generatedLine: mapping.generatedLine, | |
generatedColumn: mapping.generatedColumn, | |
originalLine: mapping.originalLine, | |
originalColumn: mapping.originalColumn, | |
name: mapping.name | |
}; | |
}).forEach(aCallback, context); | |
}; | |
exports.SourceMapConsumer = SourceMapConsumer; | |
}); | |
},{"./array-set":164,"./base64-vlq":165,"./binary-search":167,"./util":172,"amdefine":2}],170:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var base64VLQ = require('./base64-vlq'); | |
var util = require('./util'); | |
var ArraySet = require('./array-set').ArraySet; | |
var MappingList = require('./mapping-list').MappingList; | |
/** | |
* An instance of the SourceMapGenerator represents a source map which is | |
* being built incrementally. You may pass an object with the following | |
* properties: | |
* | |
* - file: The filename of the generated source. | |
* - sourceRoot: A root for all relative URLs in this source map. | |
*/ | |
function SourceMapGenerator(aArgs) { | |
if (!aArgs) { | |
aArgs = {}; | |
} | |
this._file = util.getArg(aArgs, 'file', null); | |
this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); | |
this._skipValidation = util.getArg(aArgs, 'skipValidation', false); | |
this._sources = new ArraySet(); | |
this._names = new ArraySet(); | |
this._mappings = new MappingList(); | |
this._sourcesContents = null; | |
} | |
SourceMapGenerator.prototype._version = 3; | |
/** | |
* Creates a new SourceMapGenerator based on a SourceMapConsumer | |
* | |
* @param aSourceMapConsumer The SourceMap. | |
*/ | |
SourceMapGenerator.fromSourceMap = | |
function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { | |
var sourceRoot = aSourceMapConsumer.sourceRoot; | |
var generator = new SourceMapGenerator({ | |
file: aSourceMapConsumer.file, | |
sourceRoot: sourceRoot | |
}); | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
var newMapping = { | |
generated: { | |
line: mapping.generatedLine, | |
column: mapping.generatedColumn | |
} | |
}; | |
if (mapping.source != null) { | |
newMapping.source = mapping.source; | |
if (sourceRoot != null) { | |
newMapping.source = util.relative(sourceRoot, newMapping.source); | |
} | |
newMapping.original = { | |
line: mapping.originalLine, | |
column: mapping.originalColumn | |
}; | |
if (mapping.name != null) { | |
newMapping.name = mapping.name; | |
} | |
} | |
generator.addMapping(newMapping); | |
}); | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
generator.setSourceContent(sourceFile, content); | |
} | |
}); | |
return generator; | |
}; | |
/** | |
* Add a single mapping from original source line and column to the generated | |
* source's line and column for this source map being created. The mapping | |
* object should have the following properties: | |
* | |
* - generated: An object with the generated line and column positions. | |
* - original: An object with the original line and column positions. | |
* - source: The original source file (relative to the sourceRoot). | |
* - name: An optional original token name for this mapping. | |
*/ | |
SourceMapGenerator.prototype.addMapping = | |
function SourceMapGenerator_addMapping(aArgs) { | |
var generated = util.getArg(aArgs, 'generated'); | |
var original = util.getArg(aArgs, 'original', null); | |
var source = util.getArg(aArgs, 'source', null); | |
var name = util.getArg(aArgs, 'name', null); | |
if (!this._skipValidation) { | |
this._validateMapping(generated, original, source, name); | |
} | |
if (source != null && !this._sources.has(source)) { | |
this._sources.add(source); | |
} | |
if (name != null && !this._names.has(name)) { | |
this._names.add(name); | |
} | |
this._mappings.add({ | |
generatedLine: generated.line, | |
generatedColumn: generated.column, | |
originalLine: original != null && original.line, | |
originalColumn: original != null && original.column, | |
source: source, | |
name: name | |
}); | |
}; | |
/** | |
* Set the source content for a source file. | |
*/ | |
SourceMapGenerator.prototype.setSourceContent = | |
function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { | |
var source = aSourceFile; | |
if (this._sourceRoot != null) { | |
source = util.relative(this._sourceRoot, source); | |
} | |
if (aSourceContent != null) { | |
// Add the source content to the _sourcesContents map. | |
// Create a new _sourcesContents map if the property is null. | |
if (!this._sourcesContents) { | |
this._sourcesContents = {}; | |
} | |
this._sourcesContents[util.toSetString(source)] = aSourceContent; | |
} else if (this._sourcesContents) { | |
// Remove the source file from the _sourcesContents map. | |
// If the _sourcesContents map is empty, set the property to null. | |
delete this._sourcesContents[util.toSetString(source)]; | |
if (Object.keys(this._sourcesContents).length === 0) { | |
this._sourcesContents = null; | |
} | |
} | |
}; | |
/** | |
* Applies the mappings of a sub-source-map for a specific source file to the | |
* source map being generated. Each mapping to the supplied source file is | |
* rewritten using the supplied source map. Note: The resolution for the | |
* resulting mappings is the minimium of this map and the supplied map. | |
* | |
* @param aSourceMapConsumer The source map to be applied. | |
* @param aSourceFile Optional. The filename of the source file. | |
* If omitted, SourceMapConsumer's file property will be used. | |
* @param aSourceMapPath Optional. The dirname of the path to the source map | |
* to be applied. If relative, it is relative to the SourceMapConsumer. | |
* This parameter is needed when the two source maps aren't in the same | |
* directory, and the source map to be applied contains relative source | |
* paths. If so, those relative source paths need to be rewritten | |
* relative to the SourceMapGenerator. | |
*/ | |
SourceMapGenerator.prototype.applySourceMap = | |
function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { | |
var sourceFile = aSourceFile; | |
// If aSourceFile is omitted, we will use the file property of the SourceMap | |
if (aSourceFile == null) { | |
if (aSourceMapConsumer.file == null) { | |
throw new Error( | |
'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + | |
'or the source map\'s "file" property. Both were omitted.' | |
); | |
} | |
sourceFile = aSourceMapConsumer.file; | |
} | |
var sourceRoot = this._sourceRoot; | |
// Make "sourceFile" relative if an absolute Url is passed. | |
if (sourceRoot != null) { | |
sourceFile = util.relative(sourceRoot, sourceFile); | |
} | |
// Applying the SourceMap can add and remove items from the sources and | |
// the names array. | |
var newSources = new ArraySet(); | |
var newNames = new ArraySet(); | |
// Find mappings for the "sourceFile" | |
this._mappings.unsortedForEach(function (mapping) { | |
if (mapping.source === sourceFile && mapping.originalLine != null) { | |
// Check if it can be mapped by the source map, then update the mapping. | |
var original = aSourceMapConsumer.originalPositionFor({ | |
line: mapping.originalLine, | |
column: mapping.originalColumn | |
}); | |
if (original.source != null) { | |
// Copy mapping | |
mapping.source = original.source; | |
if (aSourceMapPath != null) { | |
mapping.source = util.join(aSourceMapPath, mapping.source) | |
} | |
if (sourceRoot != null) { | |
mapping.source = util.relative(sourceRoot, mapping.source); | |
} | |
mapping.originalLine = original.line; | |
mapping.originalColumn = original.column; | |
if (original.name != null) { | |
mapping.name = original.name; | |
} | |
} | |
} | |
var source = mapping.source; | |
if (source != null && !newSources.has(source)) { | |
newSources.add(source); | |
} | |
var name = mapping.name; | |
if (name != null && !newNames.has(name)) { | |
newNames.add(name); | |
} | |
}, this); | |
this._sources = newSources; | |
this._names = newNames; | |
// Copy sourcesContents of applied map. | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
if (aSourceMapPath != null) { | |
sourceFile = util.join(aSourceMapPath, sourceFile); | |
} | |
if (sourceRoot != null) { | |
sourceFile = util.relative(sourceRoot, sourceFile); | |
} | |
this.setSourceContent(sourceFile, content); | |
} | |
}, this); | |
}; | |
/** | |
* A mapping can have one of the three levels of data: | |
* | |
* 1. Just the generated position. | |
* 2. The Generated position, original position, and original source. | |
* 3. Generated and original position, original source, as well as a name | |
* token. | |
* | |
* To maintain consistency, we validate that any new mapping being added falls | |
* in to one of these categories. | |
*/ | |
SourceMapGenerator.prototype._validateMapping = | |
function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, | |
aName) { | |
if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& !aOriginal && !aSource && !aName) { | |
// Case 1. | |
return; | |
} | |
else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated | |
&& aOriginal && 'line' in aOriginal && 'column' in aOriginal | |
&& aGenerated.line > 0 && aGenerated.column >= 0 | |
&& aOriginal.line > 0 && aOriginal.column >= 0 | |
&& aSource) { | |
// Cases 2 and 3. | |
return; | |
} | |
else { | |
throw new Error('Invalid mapping: ' + JSON.stringify({ | |
generated: aGenerated, | |
source: aSource, | |
original: aOriginal, | |
name: aName | |
})); | |
} | |
}; | |
/** | |
* Serialize the accumulated mappings in to the stream of base 64 VLQs | |
* specified by the source map format. | |
*/ | |
SourceMapGenerator.prototype._serializeMappings = | |
function SourceMapGenerator_serializeMappings() { | |
var previousGeneratedColumn = 0; | |
var previousGeneratedLine = 1; | |
var previousOriginalColumn = 0; | |
var previousOriginalLine = 0; | |
var previousName = 0; | |
var previousSource = 0; | |
var result = ''; | |
var mapping; | |
var mappings = this._mappings.toArray(); | |
for (var i = 0, len = mappings.length; i < len; i++) { | |
mapping = mappings[i]; | |
if (mapping.generatedLine !== previousGeneratedLine) { | |
previousGeneratedColumn = 0; | |
while (mapping.generatedLine !== previousGeneratedLine) { | |
result += ';'; | |
previousGeneratedLine++; | |
} | |
} | |
else { | |
if (i > 0) { | |
if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) { | |
continue; | |
} | |
result += ','; | |
} | |
} | |
result += base64VLQ.encode(mapping.generatedColumn | |
- previousGeneratedColumn); | |
previousGeneratedColumn = mapping.generatedColumn; | |
if (mapping.source != null) { | |
result += base64VLQ.encode(this._sources.indexOf(mapping.source) | |
- previousSource); | |
previousSource = this._sources.indexOf(mapping.source); | |
// lines are stored 0-based in SourceMap spec version 3 | |
result += base64VLQ.encode(mapping.originalLine - 1 | |
- previousOriginalLine); | |
previousOriginalLine = mapping.originalLine - 1; | |
result += base64VLQ.encode(mapping.originalColumn | |
- previousOriginalColumn); | |
previousOriginalColumn = mapping.originalColumn; | |
if (mapping.name != null) { | |
result += base64VLQ.encode(this._names.indexOf(mapping.name) | |
- previousName); | |
previousName = this._names.indexOf(mapping.name); | |
} | |
} | |
} | |
return result; | |
}; | |
SourceMapGenerator.prototype._generateSourcesContent = | |
function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { | |
return aSources.map(function (source) { | |
if (!this._sourcesContents) { | |
return null; | |
} | |
if (aSourceRoot != null) { | |
source = util.relative(aSourceRoot, source); | |
} | |
var key = util.toSetString(source); | |
return Object.prototype.hasOwnProperty.call(this._sourcesContents, | |
key) | |
? this._sourcesContents[key] | |
: null; | |
}, this); | |
}; | |
/** | |
* Externalize the source map. | |
*/ | |
SourceMapGenerator.prototype.toJSON = | |
function SourceMapGenerator_toJSON() { | |
var map = { | |
version: this._version, | |
sources: this._sources.toArray(), | |
names: this._names.toArray(), | |
mappings: this._serializeMappings() | |
}; | |
if (this._file != null) { | |
map.file = this._file; | |
} | |
if (this._sourceRoot != null) { | |
map.sourceRoot = this._sourceRoot; | |
} | |
if (this._sourcesContents) { | |
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); | |
} | |
return map; | |
}; | |
/** | |
* Render the source map being generated to a string. | |
*/ | |
SourceMapGenerator.prototype.toString = | |
function SourceMapGenerator_toString() { | |
return JSON.stringify(this); | |
}; | |
exports.SourceMapGenerator = SourceMapGenerator; | |
}); | |
},{"./array-set":164,"./base64-vlq":165,"./mapping-list":168,"./util":172,"amdefine":2}],171:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; | |
var util = require('./util'); | |
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other | |
// operating systems these days (capturing the result). | |
var REGEX_NEWLINE = /(\r?\n)/; | |
// Newline character code for charCodeAt() comparisons | |
var NEWLINE_CODE = 10; | |
// Private symbol for identifying `SourceNode`s when multiple versions of | |
// the source-map library are loaded. This MUST NOT CHANGE across | |
// versions! | |
var isSourceNode = "$$$isSourceNode$$$"; | |
/** | |
* SourceNodes provide a way to abstract over interpolating/concatenating | |
* snippets of generated JavaScript source code while maintaining the line and | |
* column information associated with the original source code. | |
* | |
* @param aLine The original line number. | |
* @param aColumn The original column number. | |
* @param aSource The original source's filename. | |
* @param aChunks Optional. An array of strings which are snippets of | |
* generated JS, or other SourceNodes. | |
* @param aName The original identifier. | |
*/ | |
function SourceNode(aLine, aColumn, aSource, aChunks, aName) { | |
this.children = []; | |
this.sourceContents = {}; | |
this.line = aLine == null ? null : aLine; | |
this.column = aColumn == null ? null : aColumn; | |
this.source = aSource == null ? null : aSource; | |
this.name = aName == null ? null : aName; | |
this[isSourceNode] = true; | |
if (aChunks != null) this.add(aChunks); | |
} | |
/** | |
* Creates a SourceNode from generated code and a SourceMapConsumer. | |
* | |
* @param aGeneratedCode The generated code | |
* @param aSourceMapConsumer The SourceMap for the generated code | |
* @param aRelativePath Optional. The path that relative sources in the | |
* SourceMapConsumer should be relative to. | |
*/ | |
SourceNode.fromStringWithSourceMap = | |
function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { | |
// The SourceNode we want to fill with the generated code | |
// and the SourceMap | |
var node = new SourceNode(); | |
// All even indices of this array are one line of the generated code, | |
// while all odd indices are the newlines between two adjacent lines | |
// (since `REGEX_NEWLINE` captures its match). | |
// Processed fragments are removed from this array, by calling `shiftNextLine`. | |
var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); | |
var shiftNextLine = function() { | |
var lineContents = remainingLines.shift(); | |
// The last line of a file might not have a newline. | |
var newLine = remainingLines.shift() || ""; | |
return lineContents + newLine; | |
}; | |
// We need to remember the position of "remainingLines" | |
var lastGeneratedLine = 1, lastGeneratedColumn = 0; | |
// The generate SourceNodes we need a code range. | |
// To extract it current and last mapping is used. | |
// Here we store the last mapping. | |
var lastMapping = null; | |
aSourceMapConsumer.eachMapping(function (mapping) { | |
if (lastMapping !== null) { | |
// We add the code from "lastMapping" to "mapping": | |
// First check if there is a new line in between. | |
if (lastGeneratedLine < mapping.generatedLine) { | |
var code = ""; | |
// Associate first line with "lastMapping" | |
addMappingWithCode(lastMapping, shiftNextLine()); | |
lastGeneratedLine++; | |
lastGeneratedColumn = 0; | |
// The remaining code is added without mapping | |
} else { | |
// There is no new line in between. | |
// Associate the code between "lastGeneratedColumn" and | |
// "mapping.generatedColumn" with "lastMapping" | |
var nextLine = remainingLines[0]; | |
var code = nextLine.substr(0, mapping.generatedColumn - | |
lastGeneratedColumn); | |
remainingLines[0] = nextLine.substr(mapping.generatedColumn - | |
lastGeneratedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
addMappingWithCode(lastMapping, code); | |
// No more remaining code, continue | |
lastMapping = mapping; | |
return; | |
} | |
} | |
// We add the generated code until the first mapping | |
// to the SourceNode without any mapping. | |
// Each line is added as separate string. | |
while (lastGeneratedLine < mapping.generatedLine) { | |
node.add(shiftNextLine()); | |
lastGeneratedLine++; | |
} | |
if (lastGeneratedColumn < mapping.generatedColumn) { | |
var nextLine = remainingLines[0]; | |
node.add(nextLine.substr(0, mapping.generatedColumn)); | |
remainingLines[0] = nextLine.substr(mapping.generatedColumn); | |
lastGeneratedColumn = mapping.generatedColumn; | |
} | |
lastMapping = mapping; | |
}, this); | |
// We have processed all mappings. | |
if (remainingLines.length > 0) { | |
if (lastMapping) { | |
// Associate the remaining code in the current line with "lastMapping" | |
addMappingWithCode(lastMapping, shiftNextLine()); | |
} | |
// and add the remaining lines without any mapping | |
node.add(remainingLines.join("")); | |
} | |
// Copy sourcesContent into SourceNode | |
aSourceMapConsumer.sources.forEach(function (sourceFile) { | |
var content = aSourceMapConsumer.sourceContentFor(sourceFile); | |
if (content != null) { | |
if (aRelativePath != null) { | |
sourceFile = util.join(aRelativePath, sourceFile); | |
} | |
node.setSourceContent(sourceFile, content); | |
} | |
}); | |
return node; | |
function addMappingWithCode(mapping, code) { | |
if (mapping === null || mapping.source === undefined) { | |
node.add(code); | |
} else { | |
var source = aRelativePath | |
? util.join(aRelativePath, mapping.source) | |
: mapping.source; | |
node.add(new SourceNode(mapping.originalLine, | |
mapping.originalColumn, | |
source, | |
code, | |
mapping.name)); | |
} | |
} | |
}; | |
/** | |
* Add a chunk of generated JS to this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.add = function SourceNode_add(aChunk) { | |
if (Array.isArray(aChunk)) { | |
aChunk.forEach(function (chunk) { | |
this.add(chunk); | |
}, this); | |
} | |
else if (aChunk[isSourceNode] || typeof aChunk === "string") { | |
if (aChunk) { | |
this.children.push(aChunk); | |
} | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Add a chunk of generated JS to the beginning of this source node. | |
* | |
* @param aChunk A string snippet of generated JS code, another instance of | |
* SourceNode, or an array where each member is one of those things. | |
*/ | |
SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { | |
if (Array.isArray(aChunk)) { | |
for (var i = aChunk.length-1; i >= 0; i--) { | |
this.prepend(aChunk[i]); | |
} | |
} | |
else if (aChunk[isSourceNode] || typeof aChunk === "string") { | |
this.children.unshift(aChunk); | |
} | |
else { | |
throw new TypeError( | |
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk | |
); | |
} | |
return this; | |
}; | |
/** | |
* Walk over the tree of JS snippets in this node and its children. The | |
* walking function is called once for each snippet of JS and is passed that | |
* snippet and the its original associated source's line/column location. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walk = function SourceNode_walk(aFn) { | |
var chunk; | |
for (var i = 0, len = this.children.length; i < len; i++) { | |
chunk = this.children[i]; | |
if (chunk[isSourceNode]) { | |
chunk.walk(aFn); | |
} | |
else { | |
if (chunk !== '') { | |
aFn(chunk, { source: this.source, | |
line: this.line, | |
column: this.column, | |
name: this.name }); | |
} | |
} | |
} | |
}; | |
/** | |
* Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between | |
* each of `this.children`. | |
* | |
* @param aSep The separator. | |
*/ | |
SourceNode.prototype.join = function SourceNode_join(aSep) { | |
var newChildren; | |
var i; | |
var len = this.children.length; | |
if (len > 0) { | |
newChildren = []; | |
for (i = 0; i < len-1; i++) { | |
newChildren.push(this.children[i]); | |
newChildren.push(aSep); | |
} | |
newChildren.push(this.children[i]); | |
this.children = newChildren; | |
} | |
return this; | |
}; | |
/** | |
* Call String.prototype.replace on the very right-most source snippet. Useful | |
* for trimming whitespace from the end of a source node, etc. | |
* | |
* @param aPattern The pattern to replace. | |
* @param aReplacement The thing to replace the pattern with. | |
*/ | |
SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { | |
var lastChild = this.children[this.children.length - 1]; | |
if (lastChild[isSourceNode]) { | |
lastChild.replaceRight(aPattern, aReplacement); | |
} | |
else if (typeof lastChild === 'string') { | |
this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); | |
} | |
else { | |
this.children.push(''.replace(aPattern, aReplacement)); | |
} | |
return this; | |
}; | |
/** | |
* Set the source content for a source file. This will be added to the SourceMapGenerator | |
* in the sourcesContent field. | |
* | |
* @param aSourceFile The filename of the source file | |
* @param aSourceContent The content of the source file | |
*/ | |
SourceNode.prototype.setSourceContent = | |
function SourceNode_setSourceContent(aSourceFile, aSourceContent) { | |
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; | |
}; | |
/** | |
* Walk over the tree of SourceNodes. The walking function is called for each | |
* source file content and is passed the filename and source content. | |
* | |
* @param aFn The traversal function. | |
*/ | |
SourceNode.prototype.walkSourceContents = | |
function SourceNode_walkSourceContents(aFn) { | |
for (var i = 0, len = this.children.length; i < len; i++) { | |
if (this.children[i][isSourceNode]) { | |
this.children[i].walkSourceContents(aFn); | |
} | |
} | |
var sources = Object.keys(this.sourceContents); | |
for (var i = 0, len = sources.length; i < len; i++) { | |
aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); | |
} | |
}; | |
/** | |
* Return the string representation of this source node. Walks over the tree | |
* and concatenates all the various snippets together to one string. | |
*/ | |
SourceNode.prototype.toString = function SourceNode_toString() { | |
var str = ""; | |
this.walk(function (chunk) { | |
str += chunk; | |
}); | |
return str; | |
}; | |
/** | |
* Returns the string representation of this source node along with a source | |
* map. | |
*/ | |
SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { | |
var generated = { | |
code: "", | |
line: 1, | |
column: 0 | |
}; | |
var map = new SourceMapGenerator(aArgs); | |
var sourceMappingActive = false; | |
var lastOriginalSource = null; | |
var lastOriginalLine = null; | |
var lastOriginalColumn = null; | |
var lastOriginalName = null; | |
this.walk(function (chunk, original) { | |
generated.code += chunk; | |
if (original.source !== null | |
&& original.line !== null | |
&& original.column !== null) { | |
if(lastOriginalSource !== original.source | |
|| lastOriginalLine !== original.line | |
|| lastOriginalColumn !== original.column | |
|| lastOriginalName !== original.name) { | |
map.addMapping({ | |
source: original.source, | |
original: { | |
line: original.line, | |
column: original.column | |
}, | |
generated: { | |
line: generated.line, | |
column: generated.column | |
}, | |
name: original.name | |
}); | |
} | |
lastOriginalSource = original.source; | |
lastOriginalLine = original.line; | |
lastOriginalColumn = original.column; | |
lastOriginalName = original.name; | |
sourceMappingActive = true; | |
} else if (sourceMappingActive) { | |
map.addMapping({ | |
generated: { | |
line: generated.line, | |
column: generated.column | |
} | |
}); | |
lastOriginalSource = null; | |
sourceMappingActive = false; | |
} | |
for (var idx = 0, length = chunk.length; idx < length; idx++) { | |
if (chunk.charCodeAt(idx) === NEWLINE_CODE) { | |
generated.line++; | |
generated.column = 0; | |
// Mappings end at eol | |
if (idx + 1 === length) { | |
lastOriginalSource = null; | |
sourceMappingActive = false; | |
} else if (sourceMappingActive) { | |
map.addMapping({ | |
source: original.source, | |
original: { | |
line: original.line, | |
column: original.column | |
}, | |
generated: { | |
line: generated.line, | |
column: generated.column | |
}, | |
name: original.name | |
}); | |
} | |
} else { | |
generated.column++; | |
} | |
} | |
}); | |
this.walkSourceContents(function (sourceFile, sourceContent) { | |
map.setSourceContent(sourceFile, sourceContent); | |
}); | |
return { code: generated.code, map: map }; | |
}; | |
exports.SourceNode = SourceNode; | |
}); | |
},{"./source-map-generator":170,"./util":172,"amdefine":2}],172:[function(require,module,exports){ | |
/* -*- Mode: js; js-indent-level: 2; -*- */ | |
/* | |
* Copyright 2011 Mozilla Foundation and contributors | |
* Licensed under the New BSD license. See LICENSE or: | |
* http://opensource.org/licenses/BSD-3-Clause | |
*/ | |
if (typeof define !== 'function') { | |
var define = require('amdefine')(module, require); | |
} | |
define(function (require, exports, module) { | |
/** | |
* This is a helper function for getting values from parameter/options | |
* objects. | |
* | |
* @param args The object we are extracting values from | |
* @param name The name of the property we are getting. | |
* @param defaultValue An optional value to return if the property is missing | |
* from the object. If this is not specified and the property is missing, an | |
* error will be thrown. | |
*/ | |
function getArg(aArgs, aName, aDefaultValue) { | |
if (aName in aArgs) { | |
return aArgs[aName]; | |
} else if (arguments.length === 3) { | |
return aDefaultValue; | |
} else { | |
throw new Error('"' + aName + '" is a required argument.'); | |
} | |
} | |
exports.getArg = getArg; | |
var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; | |
var dataUrlRegexp = /^data:.+\,.+$/; | |
function urlParse(aUrl) { | |
var match = aUrl.match(urlRegexp); | |
if (!match) { | |
return null; | |
} | |
return { | |
scheme: match[1], | |
auth: match[2], | |
host: match[3], | |
port: match[4], | |
path: match[5] | |
}; | |
} | |
exports.urlParse = urlParse; | |
function urlGenerate(aParsedUrl) { | |
var url = ''; | |
if (aParsedUrl.scheme) { | |
url += aParsedUrl.scheme + ':'; | |
} | |
url += '//'; | |
if (aParsedUrl.auth) { | |
url += aParsedUrl.auth + '@'; | |
} | |
if (aParsedUrl.host) { | |
url += aParsedUrl.host; | |
} | |
if (aParsedUrl.port) { | |
url += ":" + aParsedUrl.port | |
} | |
if (aParsedUrl.path) { | |
url += aParsedUrl.path; | |
} | |
return url; | |
} | |
exports.urlGenerate = urlGenerate; | |
/** | |
* Normalizes a path, or the path portion of a URL: | |
* | |
* - Replaces consequtive slashes with one slash. | |
* - Removes unnecessary '.' parts. | |
* - Removes unnecessary '<dir>/..' parts. | |
* | |
* Based on code in the Node.js 'path' core module. | |
* | |
* @param aPath The path or url to normalize. | |
*/ | |
function normalize(aPath) { | |
var path = aPath; | |
var url = urlParse(aPath); | |
if (url) { | |
if (!url.path) { | |
return aPath; | |
} | |
path = url.path; | |
} | |
var isAbsolute = (path.charAt(0) === '/'); | |
var parts = path.split(/\/+/); | |
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { | |
part = parts[i]; | |
if (part === '.') { | |
parts.splice(i, 1); | |
} else if (part === '..') { | |
up++; | |
} else if (up > 0) { | |
if (part === '') { | |
// The first part is blank if the path is absolute. Trying to go | |
// above the root is a no-op. Therefore we can remove all '..' parts | |
// directly after the root. | |
parts.splice(i + 1, up); | |
up = 0; | |
} else { | |
parts.splice(i, 2); | |
up--; | |
} | |
} | |
} | |
path = parts.join('/'); | |
if (path === '') { | |
path = isAbsolute ? '/' : '.'; | |
} | |
if (url) { | |
url.path = path; | |
return urlGenerate(url); | |
} | |
return path; | |
} | |
exports.normalize = normalize; | |
/** | |
* Joins two paths/URLs. | |
* | |
* @param aRoot The root path or URL. | |
* @param aPath The path or URL to be joined with the root. | |
* | |
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a | |
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended | |
* first. | |
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion | |
* is updated with the result and aRoot is returned. Otherwise the result | |
* is returned. | |
* - If aPath is absolute, the result is aPath. | |
* - Otherwise the two paths are joined with a slash. | |
* - Joining for example 'http://' and 'www.example.com' is also supported. | |
*/ | |
function join(aRoot, aPath) { | |
if (aRoot === "") { | |
aRoot = "."; | |
} | |
if (aPath === "") { | |
aPath = "."; | |
} | |
var aPathUrl = urlParse(aPath); | |
var aRootUrl = urlParse(aRoot); | |
if (aRootUrl) { | |
aRoot = aRootUrl.path || '/'; | |
} | |
// `join(foo, '//www.example.org')` | |
if (aPathUrl && !aPathUrl.scheme) { | |
if (aRootUrl) { | |
aPathUrl.scheme = aRootUrl.scheme; | |
} | |
return urlGenerate(aPathUrl); | |
} | |
if (aPathUrl || aPath.match(dataUrlRegexp)) { | |
return aPath; | |
} | |
// `join('http://', 'www.example.com')` | |
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { | |
aRootUrl.host = aPath; | |
return urlGenerate(aRootUrl); | |
} | |
var joined = aPath.charAt(0) === '/' | |
? aPath | |
: normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); | |
if (aRootUrl) { | |
aRootUrl.path = joined; | |
return urlGenerate(aRootUrl); | |
} | |
return joined; | |
} | |
exports.join = join; | |
/** | |
* Make a path relative to a URL or another path. | |
* | |
* @param aRoot The root path or URL. | |
* @param aPath The path or URL to be made relative to aRoot. | |
*/ | |
function relative(aRoot, aPath) { | |
if (aRoot === "") { | |
aRoot = "."; | |
} | |
aRoot = aRoot.replace(/\/$/, ''); | |
// XXX: It is possible to remove this block, and the tests still pass! | |
var url = urlParse(aRoot); | |
if (aPath.charAt(0) == "/" && url && url.path == "/") { | |
return aPath.slice(1); | |
} | |
return aPath.indexOf(aRoot + '/') === 0 | |
? aPath.substr(aRoot.length + 1) | |
: aPath; | |
} | |
exports.relative = relative; | |
/** | |
* Because behavior goes wacky when you set `__proto__` on objects, we | |
* have to prefix all the strings in our set with an arbitrary character. | |
* | |
* See https://github.com/mozilla/source-map/pull/31 and | |
* https://github.com/mozilla/source-map/issues/30 | |
* | |
* @param String aStr | |
*/ | |
function toSetString(aStr) { | |
return '$' + aStr; | |
} | |
exports.toSetString = toSetString; | |
function fromSetString(aStr) { | |
return aStr.substr(1); | |
} | |
exports.fromSetString = fromSetString; | |
function strcmp(aStr1, aStr2) { | |
var s1 = aStr1 || ""; | |
var s2 = aStr2 || ""; | |
return (s1 > s2) - (s1 < s2); | |
} | |
/** | |
* Comparator between two mappings where the original positions are compared. | |
* | |
* Optionally pass in `true` as `onlyCompareGenerated` to consider two | |
* mappings with the same original source/line/column, but different generated | |
* line and column the same. Useful when searching for a mapping with a | |
* stubbed out mapping. | |
*/ | |
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { | |
var cmp; | |
cmp = strcmp(mappingA.source, mappingB.source); | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.originalLine - mappingB.originalLine; | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.originalColumn - mappingB.originalColumn; | |
if (cmp || onlyCompareOriginal) { | |
return cmp; | |
} | |
cmp = strcmp(mappingA.name, mappingB.name); | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.generatedLine - mappingB.generatedLine; | |
if (cmp) { | |
return cmp; | |
} | |
return mappingA.generatedColumn - mappingB.generatedColumn; | |
}; | |
exports.compareByOriginalPositions = compareByOriginalPositions; | |
/** | |
* Comparator between two mappings where the generated positions are | |
* compared. | |
* | |
* Optionally pass in `true` as `onlyCompareGenerated` to consider two | |
* mappings with the same generated line and column, but different | |
* source/name/original line and column the same. Useful when searching for a | |
* mapping with a stubbed out mapping. | |
*/ | |
function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { | |
var cmp; | |
cmp = mappingA.generatedLine - mappingB.generatedLine; | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.generatedColumn - mappingB.generatedColumn; | |
if (cmp || onlyCompareGenerated) { | |
return cmp; | |
} | |
cmp = strcmp(mappingA.source, mappingB.source); | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.originalLine - mappingB.originalLine; | |
if (cmp) { | |
return cmp; | |
} | |
cmp = mappingA.originalColumn - mappingB.originalColumn; | |
if (cmp) { | |
return cmp; | |
} | |
return strcmp(mappingA.name, mappingB.name); | |
}; | |
exports.compareByGeneratedPositions = compareByGeneratedPositions; | |
}); | |
},{"amdefine":2}],173:[function(require,module,exports){ | |
var resolveKeyword = require('css-tree').keyword; | |
module.exports = function cleanAtrule(node, item, list) { | |
if (node.block) { | |
// otherwise removed at-rule don't prevent @import for removal | |
if (this.stylesheet !== null) { | |
this.stylesheet.firstAtrulesAllowed = false; | |
} | |
if (node.block.children.isEmpty()) { | |
list.remove(item); | |
return; | |
} | |
} | |
switch (node.name) { | |
case 'charset': | |
if (!node.prelude || node.prelude.children.isEmpty()) { | |
list.remove(item); | |
return; | |
} | |
// if there is any rule before @charset -> remove it | |
if (item.prev) { | |
list.remove(item); | |
return; | |
} | |
break; | |
case 'import': | |
if (this.stylesheet === null || !this.stylesheet.firstAtrulesAllowed) { | |
list.remove(item); | |
return; | |
} | |
// if there are some rules that not an @import or @charset before @import | |
// remove it | |
list.prevUntil(item.prev, function(rule) { | |
if (rule.type === 'Atrule') { | |
if (rule.name === 'import' || rule.name === 'charset') { | |
return; | |
} | |
} | |
this.root.firstAtrulesAllowed = false; | |
list.remove(item); | |
return true; | |
}, this); | |
break; | |
default: | |
var name = resolveKeyword(node.name).basename; | |
if (name === 'keyframes' || | |
name === 'media' || | |
name === 'supports') { | |
// drop at-rule with no prelude | |
if (!node.prelude || node.prelude.children.isEmpty()) { | |
list.remove(item); | |
} | |
} | |
} | |
}; | |
},{"css-tree":42}],174:[function(require,module,exports){ | |
module.exports = function cleanComment(data, item, list) { | |
list.remove(item); | |
}; | |
},{}],175:[function(require,module,exports){ | |
module.exports = function cleanDeclartion(node, item, list) { | |
if (node.value.children && node.value.children.isEmpty()) { | |
list.remove(item); | |
} | |
}; | |
},{}],176:[function(require,module,exports){ | |
// remove white spaces around operators when safe | |
module.exports = function cleanWhitespace(node, item, list) { | |
if (node.value === '+' || node.value === '-') { | |
return; | |
} | |
if (item.prev !== null && item.prev.data.type === 'WhiteSpace') { | |
list.remove(item.prev); | |
} | |
if (item.next !== null && item.next.data.type === 'WhiteSpace') { | |
list.remove(item.next); | |
} | |
}; | |
},{}],177:[function(require,module,exports){ | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var walk = require('css-tree').walk; | |
function cleanUnused(selectorList, usageData) { | |
selectorList.children.each(function(selector, item, list) { | |
var shouldRemove = false; | |
walk(selector, function(node) { | |
// ignore nodes in nested selectors | |
if (this.selector === null || this.selector === selectorList) { | |
switch (node.type) { | |
case 'SelectorList': | |
// TODO: remove toLowerCase when pseudo selectors will be normalized | |
// ignore selectors inside :not() | |
if (this['function'] === null || this['function'].name.toLowerCase() !== 'not') { | |
if (cleanUnused(node, usageData)) { | |
shouldRemove = true; | |
} | |
} | |
break; | |
case 'ClassSelector': | |
if (usageData.whitelist !== null && | |
usageData.whitelist.classes !== null && | |
!hasOwnProperty.call(usageData.whitelist.classes, node.name)) { | |
shouldRemove = true; | |
} | |
if (usageData.blacklist !== null && | |
usageData.blacklist.classes !== null && | |
hasOwnProperty.call(usageData.blacklist.classes, node.name)) { | |
shouldRemove = true; | |
} | |
break; | |
case 'IdSelector': | |
if (usageData.whitelist !== null && | |
usageData.whitelist.ids !== null && | |
!hasOwnProperty.call(usageData.whitelist.ids, node.name)) { | |
shouldRemove = true; | |
} | |
if (usageData.blacklist !== null && | |
usageData.blacklist.ids !== null && | |
hasOwnProperty.call(usageData.blacklist.ids, node.name)) { | |
shouldRemove = true; | |
} | |
break; | |
case 'TypeSelector': | |
// TODO: remove toLowerCase when type selectors will be normalized | |
// ignore universal selectors | |
if (node.name.charAt(node.name.length - 1) !== '*') { | |
if (usageData.whitelist !== null && | |
usageData.whitelist.tags !== null && | |
!hasOwnProperty.call(usageData.whitelist.tags, node.name.toLowerCase())) { | |
shouldRemove = true; | |
} | |
if (usageData.blacklist !== null && | |
usageData.blacklist.tags !== null && | |
hasOwnProperty.call(usageData.blacklist.tags, node.name.toLowerCase())) { | |
shouldRemove = true; | |
} | |
} | |
break; | |
} | |
} | |
}); | |
if (shouldRemove) { | |
list.remove(item); | |
} | |
}); | |
return selectorList.children.isEmpty(); | |
} | |
module.exports = function cleanRuleset(node, item, list, options) { | |
var usageData = options.usage; | |
if (usageData && (usageData.whitelist !== null || usageData.blacklist !== null)) { | |
cleanUnused(node.prelude, usageData); | |
} | |
if (node.prelude.children.isEmpty() || | |
node.block.children.isEmpty()) { | |
list.remove(item); | |
} | |
}; | |
},{"css-tree":42}],178:[function(require,module,exports){ | |
// remove useless universal selector | |
module.exports = function cleanType(node, item, list) { | |
var name = item.data.name; | |
// check it's a non-namespaced universal selector | |
if (name !== '*') { | |
return; | |
} | |
// remove when universal selector before other selectors | |
var nextType = item.next && item.next.data.type; | |
if (nextType === 'IdSelector' || | |
nextType === 'ClassSelector' || | |
nextType === 'AttributeSelector' || | |
nextType === 'PseudoClassSelector' || | |
nextType === 'PseudoElementSelector') { | |
list.remove(item); | |
} | |
}; | |
},{}],179:[function(require,module,exports){ | |
module.exports = function cleanWhitespace(node, item, list) { | |
// remove when first or last item in sequence | |
if (item.next === null || item.prev === null) { | |
list.remove(item); | |
return; | |
} | |
// remove when previous node is whitespace | |
if (item.prev.data.type === 'WhiteSpace') { | |
list.remove(item); | |
return; | |
} | |
if ((this.stylesheet !== null && this.stylesheet.children === list) || | |
(this.block !== null && this.block.children === list)) { | |
list.remove(item); | |
return; | |
} | |
}; | |
},{}],180:[function(require,module,exports){ | |
var walk = require('css-tree').walk; | |
var handlers = { | |
Atrule: require('./Atrule'), | |
Rule: require('./Rule'), | |
Declaration: require('./Declaration'), | |
TypeSelector: require('./TypeSelector'), | |
Comment: require('./Comment'), | |
Operator: require('./Operator'), | |
WhiteSpace: require('./WhiteSpace') | |
}; | |
module.exports = function(ast, options) { | |
walk(ast, { | |
leave: function(node, item, list) { | |
if (handlers.hasOwnProperty(node.type)) { | |
handlers[node.type].call(this, node, item, list, options); | |
} | |
} | |
}); | |
}; | |
},{"./Atrule":173,"./Comment":174,"./Declaration":175,"./Operator":176,"./Rule":177,"./TypeSelector":178,"./WhiteSpace":179,"css-tree":42}],181:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
var clone = require('css-tree').clone; | |
var usageUtils = require('./usage'); | |
var clean = require('./clean'); | |
var replace = require('./replace'); | |
var restructure = require('./restructure'); | |
var walk = require('css-tree').walk; | |
function readChunk(children, specialComments) { | |
var buffer = new List(); | |
var nonSpaceTokenInBuffer = false; | |
var protectedComment; | |
children.nextUntil(children.head, function(node, item, list) { | |
if (node.type === 'Comment') { | |
if (!specialComments || node.value.charAt(0) !== '!') { | |
list.remove(item); | |
return; | |
} | |
if (nonSpaceTokenInBuffer || protectedComment) { | |
return true; | |
} | |
list.remove(item); | |
protectedComment = node; | |
return; | |
} | |
if (node.type !== 'WhiteSpace') { | |
nonSpaceTokenInBuffer = true; | |
} | |
buffer.insert(list.remove(item)); | |
}); | |
return { | |
comment: protectedComment, | |
stylesheet: { | |
type: 'StyleSheet', | |
loc: null, | |
children: buffer | |
} | |
}; | |
} | |
function compressChunk(ast, firstAtrulesAllowed, num, options) { | |
options.logger('Compress block #' + num, null, true); | |
var seed = 1; | |
if (ast.type === 'StyleSheet') { | |
ast.firstAtrulesAllowed = firstAtrulesAllowed; | |
ast.id = seed++; | |
} | |
walk(ast, { | |
visit: 'Atrule', | |
enter: function markScopes(node) { | |
if (node.block !== null) { | |
node.block.id = seed++; | |
} | |
} | |
}); | |
options.logger('init', ast); | |
// remove redundant | |
clean(ast, options); | |
options.logger('clean', ast); | |
// replace nodes for shortened forms | |
replace(ast, options); | |
options.logger('replace', ast); | |
// structure optimisations | |
if (options.restructuring) { | |
restructure(ast, options); | |
} | |
return ast; | |
} | |
function getCommentsOption(options) { | |
var comments = 'comments' in options ? options.comments : 'exclamation'; | |
if (typeof comments === 'boolean') { | |
comments = comments ? 'exclamation' : false; | |
} else if (comments !== 'exclamation' && comments !== 'first-exclamation') { | |
comments = false; | |
} | |
return comments; | |
} | |
function getRestructureOption(options) { | |
return 'restructure' in options ? options.restructure : | |
'restructuring' in options ? options.restructuring : | |
true; | |
} | |
function wrapBlock(block) { | |
return new List().appendData({ | |
type: 'Rule', | |
loc: null, | |
prelude: { | |
type: 'SelectorList', | |
loc: null, | |
children: new List().appendData({ | |
type: 'Selector', | |
loc: null, | |
children: new List().appendData({ | |
type: 'TypeSelector', | |
loc: null, | |
name: 'x' | |
}) | |
}) | |
}, | |
block: block | |
}); | |
} | |
module.exports = function compress(ast, options) { | |
ast = ast || { type: 'StyleSheet', loc: null, children: new List() }; | |
options = options || {}; | |
var compressOptions = { | |
logger: typeof options.logger === 'function' ? options.logger : function() {}, | |
restructuring: getRestructureOption(options), | |
forceMediaMerge: Boolean(options.forceMediaMerge), | |
usage: options.usage ? usageUtils.buildIndex(options.usage) : false | |
}; | |
var specialComments = getCommentsOption(options); | |
var firstAtrulesAllowed = true; | |
var input; | |
var output = new List(); | |
var chunk; | |
var chunkNum = 1; | |
var chunkChildren; | |
if (options.clone) { | |
ast = clone(ast); | |
} | |
if (ast.type === 'StyleSheet') { | |
input = ast.children; | |
ast.children = output; | |
} else { | |
input = wrapBlock(ast); | |
} | |
do { | |
chunk = readChunk(input, Boolean(specialComments)); | |
compressChunk(chunk.stylesheet, firstAtrulesAllowed, chunkNum++, compressOptions); | |
chunkChildren = chunk.stylesheet.children; | |
if (chunk.comment) { | |
// add \n before comment if there is another content in output | |
if (!output.isEmpty()) { | |
output.insert(List.createItem({ | |
type: 'Raw', | |
value: '\n' | |
})); | |
} | |
output.insert(List.createItem(chunk.comment)); | |
// add \n after comment if chunk is not empty | |
if (!chunkChildren.isEmpty()) { | |
output.insert(List.createItem({ | |
type: 'Raw', | |
value: '\n' | |
})); | |
} | |
} | |
if (firstAtrulesAllowed && !chunkChildren.isEmpty()) { | |
var lastRule = chunkChildren.last(); | |
if (lastRule.type !== 'Atrule' || | |
(lastRule.name !== 'import' && lastRule.name !== 'charset')) { | |
firstAtrulesAllowed = false; | |
} | |
} | |
if (specialComments !== 'exclamation') { | |
specialComments = false; | |
} | |
output.appendList(chunkChildren); | |
} while (!input.isEmpty()); | |
return { | |
ast: ast | |
}; | |
}; | |
},{"./clean":180,"./replace":193,"./restructure":205,"./usage":211,"css-tree":42}],182:[function(require,module,exports){ | |
var csstree = require('css-tree'); | |
var parse = csstree.parse; | |
var compress = require('./compress'); | |
var generate = csstree.generate; | |
function debugOutput(name, options, startTime, data) { | |
if (options.debug) { | |
console.error('## ' + name + ' done in %d ms\n', Date.now() - startTime); | |
} | |
return data; | |
} | |
function createDefaultLogger(level) { | |
var lastDebug; | |
return function logger(title, ast) { | |
var line = title; | |
if (ast) { | |
line = '[' + ((Date.now() - lastDebug) / 1000).toFixed(3) + 's] ' + line; | |
} | |
if (level > 1 && ast) { | |
var css = generate(ast); | |
// when level 2, limit css to 256 symbols | |
if (level === 2 && css.length > 256) { | |
css = css.substr(0, 256) + '...'; | |
} | |
line += '\n ' + css + '\n'; | |
} | |
console.error(line); | |
lastDebug = Date.now(); | |
}; | |
} | |
function copy(obj) { | |
var result = {}; | |
for (var key in obj) { | |
result[key] = obj[key]; | |
} | |
return result; | |
} | |
function buildCompressOptions(options) { | |
options = copy(options); | |
if (typeof options.logger !== 'function' && options.debug) { | |
options.logger = createDefaultLogger(options.debug); | |
} | |
return options; | |
} | |
function runHandler(ast, options, handlers) { | |
if (!Array.isArray(handlers)) { | |
handlers = [handlers]; | |
} | |
handlers.forEach(function(fn) { | |
fn(ast, options); | |
}); | |
} | |
function minify(context, source, options) { | |
options = options || {}; | |
var filename = options.filename || '<unknown>'; | |
var result; | |
// parse | |
var ast = debugOutput('parsing', options, Date.now(), | |
parse(source, { | |
context: context, | |
filename: filename, | |
positions: Boolean(options.sourceMap) | |
}) | |
); | |
// before compress handlers | |
if (options.beforeCompress) { | |
debugOutput('beforeCompress', options, Date.now(), | |
runHandler(ast, options, options.beforeCompress) | |
); | |
} | |
// compress | |
var compressResult = debugOutput('compress', options, Date.now(), | |
compress(ast, buildCompressOptions(options)) | |
); | |
// after compress handlers | |
if (options.afterCompress) { | |
debugOutput('afterCompress', options, Date.now(), | |
runHandler(compressResult, options, options.afterCompress) | |
); | |
} | |
// generate | |
if (options.sourceMap) { | |
result = debugOutput('generate(sourceMap: true)', options, Date.now(), (function() { | |
var tmp = generate(compressResult.ast, { sourceMap: true }); | |
tmp.map._file = filename; // since other tools can relay on file in source map transform chain | |
tmp.map.setSourceContent(filename, source); | |
return tmp; | |
})()); | |
} else { | |
result = debugOutput('generate', options, Date.now(), { | |
css: generate(compressResult.ast), | |
map: null | |
}); | |
} | |
return result; | |
} | |
function minifyStylesheet(source, options) { | |
return minify('stylesheet', source, options); | |
} | |
function minifyBlock(source, options) { | |
return minify('declarationList', source, options); | |
} | |
module.exports = { | |
version: require('../package.json').version, | |
// main methods | |
minify: minifyStylesheet, | |
minifyBlock: minifyBlock, | |
// compress an AST | |
compress: compress, | |
// css syntax parser/walkers/generator/etc | |
syntax: csstree | |
}; | |
},{"../package.json":212,"./compress":181,"css-tree":42}],183:[function(require,module,exports){ | |
var resolveKeyword = require('css-tree').keyword; | |
var compressKeyframes = require('./atrule/keyframes'); | |
module.exports = function(node) { | |
// compress @keyframe selectors | |
if (resolveKeyword(node.name).basename === 'keyframes') { | |
compressKeyframes(node); | |
} | |
}; | |
},{"./atrule/keyframes":191,"css-tree":42}],184:[function(require,module,exports){ | |
// Can unquote attribute detection | |
// Adopted implementation of Mathias Bynens | |
// https://github.com/mathiasbynens/mothereff.in/blob/master/unquoted-attributes/eff.js | |
var escapesRx = /\\([0-9A-Fa-f]{1,6})(\r\n|[ \t\n\f\r])?|\\./g; | |
var blockUnquoteRx = /^(-?\d|--)|[\u0000-\u002c\u002e\u002f\u003A-\u0040\u005B-\u005E\u0060\u007B-\u009f]/; | |
function canUnquote(value) { | |
if (value === '' || value === '-') { | |
return; | |
} | |
// Escapes are valid, so replace them with a valid non-empty string | |
value = value.replace(escapesRx, 'a'); | |
return !blockUnquoteRx.test(value); | |
} | |
module.exports = function(node) { | |
var attrValue = node.value; | |
if (!attrValue || attrValue.type !== 'String') { | |
return; | |
} | |
var unquotedValue = attrValue.value.replace(/^(.)(.*)\1$/, '$2'); | |
if (canUnquote(unquotedValue)) { | |
node.value = { | |
type: 'Identifier', | |
loc: attrValue.loc, | |
name: unquotedValue | |
}; | |
} | |
}; | |
},{}],185:[function(require,module,exports){ | |
var packNumber = require('./Number').pack; | |
var LENGTH_UNIT = { | |
// absolute length units | |
'px': true, | |
'mm': true, | |
'cm': true, | |
'in': true, | |
'pt': true, | |
'pc': true, | |
// relative length units | |
'em': true, | |
'ex': true, | |
'ch': true, | |
'rem': true, | |
// viewport-percentage lengths | |
'vh': true, | |
'vw': true, | |
'vmin': true, | |
'vmax': true, | |
'vm': true | |
}; | |
module.exports = function compressDimension(node, item) { | |
var value = packNumber(node.value, item); | |
node.value = value; | |
if (value === '0' && this.declaration !== null && this.atrulePrelude === null) { | |
var unit = node.unit.toLowerCase(); | |
// only length values can be compressed | |
if (!LENGTH_UNIT.hasOwnProperty(unit)) { | |
return; | |
} | |
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11 | |
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11 | |
if (this.declaration.property === '-ms-flex' || | |
this.declaration.property === 'flex') { | |
return; | |
} | |
// issue #222: don't remove units inside calc | |
if (this['function'] && this['function'].name === 'calc') { | |
return; | |
} | |
item.data = { | |
type: 'Number', | |
loc: node.loc, | |
value: value | |
}; | |
} | |
}; | |
},{"./Number":186}],186:[function(require,module,exports){ | |
var OMIT_PLUSSIGN = /^(?:\+|(-))?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/; | |
var KEEP_PLUSSIGN = /^([\+\-])?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/; | |
var unsafeToRemovePlusSignAfter = { | |
Dimension: true, | |
HexColor: true, | |
Identifier: true, | |
Number: true, | |
Raw: true, | |
UnicodeRange: true | |
}; | |
function packNumber(value, item) { | |
// omit plus sign only if no prev or prev is safe type | |
var regexp = item && item.prev !== null && unsafeToRemovePlusSignAfter.hasOwnProperty(item.prev.data.type) | |
? KEEP_PLUSSIGN | |
: OMIT_PLUSSIGN; | |
// 100 -> '100' | |
// 00100 -> '100' | |
// +100 -> '100' (only when safe, e.g. omitting plus sign for 1px+1px leads to single dimension instead of two) | |
// -100 -> '-100' | |
// 0.123 -> '.123' | |
// 0.12300 -> '.123' | |
// 0.0 -> '' | |
// 0 -> '' | |
// -0 -> '-' | |
value = String(value).replace(regexp, '$1$2$3'); | |
if (value === '' || value === '-') { | |
value = '0'; | |
} | |
return value; | |
} | |
module.exports = function(node, item) { | |
node.value = packNumber(node.value, item); | |
}; | |
module.exports.pack = packNumber; | |
},{}],187:[function(require,module,exports){ | |
var packNumber = require('./Number').pack; | |
var PERCENTAGE_LENGTH_PROPERTY = { | |
'margin': true, | |
'margin-top': true, | |
'margin-left': true, | |
'margin-bottom': true, | |
'margin-right': true, | |
'padding': true, | |
'padding-top': true, | |
'padding-left': true, | |
'padding-bottom': true, | |
'padding-right': true, | |
'top': true, | |
'left': true, | |
'bottom': true, | |
'right': true, | |
'background-position': true, | |
'background-position-x': true, | |
'background-position-y': true, | |
'background-size': true, | |
'border': true, | |
'border-width': true, | |
'border-top-width': true, | |
'border-left-width': true, | |
'border-bottom-width': true, | |
'border-right-width': true, | |
'border-image-width': true, | |
'border-radius': true, | |
'border-bottom-left-radius': true, | |
'border-bottom-right-radius': true, | |
'border-top-left-radius': true, | |
'border-top-right-radius': true | |
}; | |
module.exports = function compressPercentage(node, item) { | |
var value = packNumber(node.value, item); | |
var property = this.declaration !== null ? this.declaration.property : null; | |
node.value = value; | |
if (property !== null && PERCENTAGE_LENGTH_PROPERTY.hasOwnProperty(property)) { | |
if (value === '0') { | |
item.data = { | |
type: 'Number', | |
loc: node.loc, | |
value: value | |
}; | |
} | |
} | |
}; | |
},{"./Number":186}],188:[function(require,module,exports){ | |
module.exports = function(node) { | |
var value = node.value; | |
// remove escaped newlines, i.e. | |
// .a { content: "foo\ | |
// bar"} | |
// -> | |
// .a { content: "foobar" } | |
value = value.replace(/\\(\r\n|\r|\n|\f)/g, ''); | |
node.value = value; | |
}; | |
},{}],189:[function(require,module,exports){ | |
var UNICODE = '\\\\[0-9a-f]{1,6}(\\r\\n|[ \\n\\r\\t\\f])?'; | |
var ESCAPE = '(' + UNICODE + '|\\\\[^\\n\\r\\f0-9a-fA-F])'; | |
var NONPRINTABLE = '\u0000\u0008\u000b\u000e-\u001f\u007f'; | |
var SAFE_URL = new RegExp('^(' + ESCAPE + '|[^\"\'\\(\\)\\\\\\s' + NONPRINTABLE + '])*$', 'i'); | |
module.exports = function(node) { | |
var value = node.value; | |
if (value.type !== 'String') { | |
return; | |
} | |
var quote = value.value[0]; | |
var url = value.value.substr(1, value.value.length - 2); | |
// convert `\\` to `/` | |
url = url.replace(/\\\\/g, '/'); | |
// remove quotes when safe | |
// https://www.w3.org/TR/css-syntax-3/#url-unquoted-diagram | |
if (SAFE_URL.test(url)) { | |
node.value = { | |
type: 'Raw', | |
loc: node.value.loc, | |
value: url | |
}; | |
} else { | |
// use double quotes if string has no double quotes | |
// otherwise use original quotes | |
// TODO: make better quote type selection | |
node.value.value = url.indexOf('"') === -1 ? '"' + url + '"' : quote + url + quote; | |
} | |
}; | |
},{}],190:[function(require,module,exports){ | |
var resolveName = require('css-tree').property; | |
var handlers = { | |
'font': require('./property/font'), | |
'font-weight': require('./property/font-weight'), | |
'background': require('./property/background'), | |
'border': require('./property/border'), | |
'outline': require('./property/border') | |
}; | |
module.exports = function compressValue(node) { | |
if (!this.declaration) { | |
return; | |
} | |
var property = resolveName(this.declaration.property); | |
if (handlers.hasOwnProperty(property.basename)) { | |
handlers[property.basename](node); | |
} | |
}; | |
},{"./property/background":194,"./property/border":195,"./property/font":197,"./property/font-weight":196,"css-tree":42}],191:[function(require,module,exports){ | |
module.exports = function(node) { | |
node.block.children.each(function(rule) { | |
rule.prelude.children.each(function(simpleselector) { | |
simpleselector.children.each(function(data, item) { | |
if (data.type === 'Percentage' && data.value === '100') { | |
item.data = { | |
type: 'TypeSelector', | |
loc: data.loc, | |
name: 'to' | |
}; | |
} else if (data.type === 'TypeSelector' && data.name === 'from') { | |
item.data = { | |
type: 'Percentage', | |
loc: data.loc, | |
value: '0' | |
}; | |
} | |
}); | |
}); | |
}); | |
}; | |
},{}],192:[function(require,module,exports){ | |
var lexer = require('css-tree').lexer; | |
var packNumber = require('./Number').pack; | |
// http://www.w3.org/TR/css3-color/#svg-color | |
var NAME_TO_HEX = { | |
'aliceblue': 'f0f8ff', | |
'antiquewhite': 'faebd7', | |
'aqua': '0ff', | |
'aquamarine': '7fffd4', | |
'azure': 'f0ffff', | |
'beige': 'f5f5dc', | |
'bisque': 'ffe4c4', | |
'black': '000', | |
'blanchedalmond': 'ffebcd', | |
'blue': '00f', | |
'blueviolet': '8a2be2', | |
'brown': 'a52a2a', | |
'burlywood': 'deb887', | |
'cadetblue': '5f9ea0', | |
'chartreuse': '7fff00', | |
'chocolate': 'd2691e', | |
'coral': 'ff7f50', | |
'cornflowerblue': '6495ed', | |
'cornsilk': 'fff8dc', | |
'crimson': 'dc143c', | |
'cyan': '0ff', | |
'darkblue': '00008b', | |
'darkcyan': '008b8b', | |
'darkgoldenrod': 'b8860b', | |
'darkgray': 'a9a9a9', | |
'darkgrey': 'a9a9a9', | |
'darkgreen': '006400', | |
'darkkhaki': 'bdb76b', | |
'darkmagenta': '8b008b', | |
'darkolivegreen': '556b2f', | |
'darkorange': 'ff8c00', | |
'darkorchid': '9932cc', | |
'darkred': '8b0000', | |
'darksalmon': 'e9967a', | |
'darkseagreen': '8fbc8f', | |
'darkslateblue': '483d8b', | |
'darkslategray': '2f4f4f', | |
'darkslategrey': '2f4f4f', | |
'darkturquoise': '00ced1', | |
'darkviolet': '9400d3', | |
'deeppink': 'ff1493', | |
'deepskyblue': '00bfff', | |
'dimgray': '696969', | |
'dimgrey': '696969', | |
'dodgerblue': '1e90ff', | |
'firebrick': 'b22222', | |
'floralwhite': 'fffaf0', | |
'forestgreen': '228b22', | |
'fuchsia': 'f0f', | |
'gainsboro': 'dcdcdc', | |
'ghostwhite': 'f8f8ff', | |
'gold': 'ffd700', | |
'goldenrod': 'daa520', | |
'gray': '808080', | |
'grey': '808080', | |
'green': '008000', | |
'greenyellow': 'adff2f', | |
'honeydew': 'f0fff0', | |
'hotpink': 'ff69b4', | |
'indianred': 'cd5c5c', | |
'indigo': '4b0082', | |
'ivory': 'fffff0', | |
'khaki': 'f0e68c', | |
'lavender': 'e6e6fa', | |
'lavenderblush': 'fff0f5', | |
'lawngreen': '7cfc00', | |
'lemonchiffon': 'fffacd', | |
'lightblue': 'add8e6', | |
'lightcoral': 'f08080', | |
'lightcyan': 'e0ffff', | |
'lightgoldenrodyellow': 'fafad2', | |
'lightgray': 'd3d3d3', | |
'lightgrey': 'd3d3d3', | |
'lightgreen': '90ee90', | |
'lightpink': 'ffb6c1', | |
'lightsalmon': 'ffa07a', | |
'lightseagreen': '20b2aa', | |
'lightskyblue': '87cefa', | |
'lightslategray': '789', | |
'lightslategrey': '789', | |
'lightsteelblue': 'b0c4de', | |
'lightyellow': 'ffffe0', | |
'lime': '0f0', | |
'limegreen': '32cd32', | |
'linen': 'faf0e6', | |
'magenta': 'f0f', | |
'maroon': '800000', | |
'mediumaquamarine': '66cdaa', | |
'mediumblue': '0000cd', | |
'mediumorchid': 'ba55d3', | |
'mediumpurple': '9370db', | |
'mediumseagreen': '3cb371', | |
'mediumslateblue': '7b68ee', | |
'mediumspringgreen': '00fa9a', | |
'mediumturquoise': '48d1cc', | |
'mediumvioletred': 'c71585', | |
'midnightblue': '191970', | |
'mintcream': 'f5fffa', | |
'mistyrose': 'ffe4e1', | |
'moccasin': 'ffe4b5', | |
'navajowhite': 'ffdead', | |
'navy': '000080', | |
'oldlace': 'fdf5e6', | |
'olive': '808000', | |
'olivedrab': '6b8e23', | |
'orange': 'ffa500', | |
'orangered': 'ff4500', | |
'orchid': 'da70d6', | |
'palegoldenrod': 'eee8aa', | |
'palegreen': '98fb98', | |
'paleturquoise': 'afeeee', | |
'palevioletred': 'db7093', | |
'papayawhip': 'ffefd5', | |
'peachpuff': 'ffdab9', | |
'peru': 'cd853f', | |
'pink': 'ffc0cb', | |
'plum': 'dda0dd', | |
'powderblue': 'b0e0e6', | |
'purple': '800080', | |
'rebeccapurple': '639', | |
'red': 'f00', | |
'rosybrown': 'bc8f8f', | |
'royalblue': '4169e1', | |
'saddlebrown': '8b4513', | |
'salmon': 'fa8072', | |
'sandybrown': 'f4a460', | |
'seagreen': '2e8b57', | |
'seashell': 'fff5ee', | |
'sienna': 'a0522d', | |
'silver': 'c0c0c0', | |
'skyblue': '87ceeb', | |
'slateblue': '6a5acd', | |
'slategray': '708090', | |
'slategrey': '708090', | |
'snow': 'fffafa', | |
'springgreen': '00ff7f', | |
'steelblue': '4682b4', | |
'tan': 'd2b48c', | |
'teal': '008080', | |
'thistle': 'd8bfd8', | |
'tomato': 'ff6347', | |
'turquoise': '40e0d0', | |
'violet': 'ee82ee', | |
'wheat': 'f5deb3', | |
'white': 'fff', | |
'whitesmoke': 'f5f5f5', | |
'yellow': 'ff0', | |
'yellowgreen': '9acd32' | |
}; | |
var HEX_TO_NAME = { | |
'800000': 'maroon', | |
'800080': 'purple', | |
'808000': 'olive', | |
'808080': 'gray', | |
'00ffff': 'cyan', | |
'f0ffff': 'azure', | |
'f5f5dc': 'beige', | |
'ffe4c4': 'bisque', | |
'000000': 'black', | |
'0000ff': 'blue', | |
'a52a2a': 'brown', | |
'ff7f50': 'coral', | |
'ffd700': 'gold', | |
'008000': 'green', | |
'4b0082': 'indigo', | |
'fffff0': 'ivory', | |
'f0e68c': 'khaki', | |
'00ff00': 'lime', | |
'faf0e6': 'linen', | |
'000080': 'navy', | |
'ffa500': 'orange', | |
'da70d6': 'orchid', | |
'cd853f': 'peru', | |
'ffc0cb': 'pink', | |
'dda0dd': 'plum', | |
'f00': 'red', | |
'ff0000': 'red', | |
'fa8072': 'salmon', | |
'a0522d': 'sienna', | |
'c0c0c0': 'silver', | |
'fffafa': 'snow', | |
'd2b48c': 'tan', | |
'008080': 'teal', | |
'ff6347': 'tomato', | |
'ee82ee': 'violet', | |
'f5deb3': 'wheat', | |
'ffffff': 'white', | |
'ffff00': 'yellow' | |
}; | |
function hueToRgb(p, q, t) { | |
if (t < 0) { | |
t += 1; | |
} | |
if (t > 1) { | |
t -= 1; | |
} | |
if (t < 1 / 6) { | |
return p + (q - p) * 6 * t; | |
} | |
if (t < 1 / 2) { | |
return q; | |
} | |
if (t < 2 / 3) { | |
return p + (q - p) * (2 / 3 - t) * 6; | |
} | |
return p; | |
} | |
function hslToRgb(h, s, l, a) { | |
var r; | |
var g; | |
var b; | |
if (s === 0) { | |
r = g = b = l; // achromatic | |
} else { | |
var q = l < 0.5 ? l * (1 + s) : l + s - l * s; | |
var p = 2 * l - q; | |
r = hueToRgb(p, q, h + 1 / 3); | |
g = hueToRgb(p, q, h); | |
b = hueToRgb(p, q, h - 1 / 3); | |
} | |
return [ | |
Math.round(r * 255), | |
Math.round(g * 255), | |
Math.round(b * 255), | |
a | |
]; | |
} | |
function toHex(value) { | |
value = value.toString(16); | |
return value.length === 1 ? '0' + value : value; | |
} | |
function parseFunctionArgs(functionArgs, count, rgb) { | |
var cursor = functionArgs.head; | |
var args = []; | |
var wasValue = false; | |
while (cursor !== null) { | |
var node = cursor.data; | |
var type = node.type; | |
switch (type) { | |
case 'Number': | |
case 'Percentage': | |
if (wasValue) { | |
return; | |
} | |
wasValue = true; | |
args.push({ | |
type: type, | |
value: Number(node.value) | |
}); | |
break; | |
case 'Operator': | |
if (node.value === ',') { | |
if (!wasValue) { | |
return; | |
} | |
wasValue = false; | |
} else if (wasValue || node.value !== '+') { | |
return; | |
} | |
break; | |
default: | |
// something we couldn't understand | |
return; | |
} | |
cursor = cursor.next; | |
} | |
if (args.length !== count) { | |
// invalid arguments count | |
// TODO: remove those tokens | |
return; | |
} | |
if (args.length === 4) { | |
if (args[3].type !== 'Number') { | |
// 4th argument should be a number | |
// TODO: remove those tokens | |
return; | |
} | |
args[3].type = 'Alpha'; | |
} | |
if (rgb) { | |
if (args[0].type !== args[1].type || args[0].type !== args[2].type) { | |
// invalid color, numbers and percentage shouldn't be mixed | |
// TODO: remove those tokens | |
return; | |
} | |
} else { | |
if (args[0].type !== 'Number' || | |
args[1].type !== 'Percentage' || | |
args[2].type !== 'Percentage') { | |
// invalid color, for hsl values should be: number, percentage, percentage | |
// TODO: remove those tokens | |
return; | |
} | |
args[0].type = 'Angle'; | |
} | |
return args.map(function(arg) { | |
var value = Math.max(0, arg.value); | |
switch (arg.type) { | |
case 'Number': | |
// fit value to [0..255] range | |
value = Math.min(value, 255); | |
break; | |
case 'Percentage': | |
// convert 0..100% to value in [0..255] range | |
value = Math.min(value, 100) / 100; | |
if (!rgb) { | |
return value; | |
} | |
value = 255 * value; | |
break; | |
case 'Angle': | |
// fit value to (-360..360) range | |
return (((value % 360) + 360) % 360) / 360; | |
case 'Alpha': | |
// fit value to [0..1] range | |
return Math.min(value, 1); | |
} | |
return Math.round(value); | |
}); | |
} | |
function compressFunction(node, item, list) { | |
var functionName = node.name; | |
var args; | |
if (functionName === 'rgba' || functionName === 'hsla') { | |
args = parseFunctionArgs(node.children, 4, functionName === 'rgba'); | |
if (!args) { | |
// something went wrong | |
return; | |
} | |
if (functionName === 'hsla') { | |
args = hslToRgb.apply(null, args); | |
node.name = 'rgba'; | |
} | |
if (args[3] === 0) { | |
// try to replace `rgba(x, x, x, 0)` to `transparent` | |
// always replace `rgba(0, 0, 0, 0)` to `transparent` | |
// otherwise avoid replacement in gradients since it may break color transition | |
// http://stackoverflow.com/questions/11829410/css3-gradient-rendering-issues-from-transparent-to-white | |
var scopeFunctionName = this['function'] && this['function'].name; | |
if ((args[0] === 0 && args[1] === 0 && args[2] === 0) || | |
!/^(?:to|from|color-stop)$|gradient$/i.test(scopeFunctionName)) { | |
item.data = { | |
type: 'Identifier', | |
loc: node.loc, | |
name: 'transparent' | |
}; | |
return; | |
} | |
} | |
if (args[3] !== 1) { | |
// replace argument values for normalized/interpolated | |
node.children.each(function(node, item, list) { | |
if (node.type === 'Operator') { | |
if (node.value !== ',') { | |
list.remove(item); | |
} | |
return; | |
} | |
item.data = { | |
type: 'Number', | |
loc: node.loc, | |
value: packNumber(args.shift(), null) | |
}; | |
}); | |
return; | |
} | |
// otherwise convert to rgb, i.e. rgba(255, 0, 0, 1) -> rgb(255, 0, 0) | |
functionName = 'rgb'; | |
} | |
if (functionName === 'hsl') { | |
args = args || parseFunctionArgs(node.children, 3, false); | |
if (!args) { | |
// something went wrong | |
return; | |
} | |
// convert to rgb | |
args = hslToRgb.apply(null, args); | |
functionName = 'rgb'; | |
} | |
if (functionName === 'rgb') { | |
args = args || parseFunctionArgs(node.children, 3, true); | |
if (!args) { | |
// something went wrong | |
return; | |
} | |
// check if color is not at the end and not followed by space | |
var next = item.next; | |
if (next && next.data.type !== 'WhiteSpace') { | |
list.insert(list.createItem({ | |
type: 'WhiteSpace', | |
value: ' ' | |
}), next); | |
} | |
item.data = { | |
type: 'HexColor', | |
loc: node.loc, | |
value: toHex(args[0]) + toHex(args[1]) + toHex(args[2]) | |
}; | |
compressHex(item.data, item); | |
} | |
} | |
function compressIdent(node, item) { | |
if (this.declaration === null) { | |
return; | |
} | |
var color = node.name.toLowerCase(); | |
if (NAME_TO_HEX.hasOwnProperty(color) && | |
lexer.matchDeclaration(this.declaration).isType(node, 'color')) { | |
var hex = NAME_TO_HEX[color]; | |
if (hex.length + 1 <= color.length) { | |
// replace for shorter hex value | |
item.data = { | |
type: 'HexColor', | |
loc: node.loc, | |
value: hex | |
}; | |
} else { | |
// special case for consistent colors | |
if (color === 'grey') { | |
color = 'gray'; | |
} | |
// just replace value for lower cased name | |
node.name = color; | |
} | |
} | |
} | |
function compressHex(node, item) { | |
var color = node.value.toLowerCase(); | |
// #112233 -> #123 | |
if (color.length === 6 && | |
color[0] === color[1] && | |
color[2] === color[3] && | |
color[4] === color[5]) { | |
color = color[0] + color[2] + color[4]; | |
} | |
if (HEX_TO_NAME[color]) { | |
item.data = { | |
type: 'Identifier', | |
loc: node.loc, | |
name: HEX_TO_NAME[color] | |
}; | |
} else { | |
node.value = color; | |
} | |
} | |
module.exports = { | |
compressFunction: compressFunction, | |
compressIdent: compressIdent, | |
compressHex: compressHex | |
}; | |
},{"./Number":186,"css-tree":42}],193:[function(require,module,exports){ | |
var walk = require('css-tree').walk; | |
var handlers = { | |
Atrule: require('./Atrule'), | |
AttributeSelector: require('./AttributeSelector'), | |
Value: require('./Value'), | |
Dimension: require('./Dimension'), | |
Percentage: require('./Percentage'), | |
Number: require('./Number'), | |
String: require('./String'), | |
Url: require('./Url'), | |
HexColor: require('./color').compressHex, | |
Identifier: require('./color').compressIdent, | |
Function: require('./color').compressFunction | |
}; | |
module.exports = function(ast) { | |
walk(ast, { | |
leave: function(node, item, list) { | |
if (handlers.hasOwnProperty(node.type)) { | |
handlers[node.type].call(this, node, item, list); | |
} | |
} | |
}); | |
}; | |
},{"./Atrule":183,"./AttributeSelector":184,"./Dimension":185,"./Number":186,"./Percentage":187,"./String":188,"./Url":189,"./Value":190,"./color":192,"css-tree":42}],194:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
module.exports = function compressBackground(node) { | |
function lastType() { | |
if (buffer.length) { | |
return buffer[buffer.length - 1].type; | |
} | |
} | |
function flush() { | |
if (lastType() === 'WhiteSpace') { | |
buffer.pop(); | |
} | |
if (!buffer.length) { | |
buffer.unshift( | |
{ | |
type: 'Number', | |
loc: null, | |
value: '0' | |
}, | |
{ | |
type: 'WhiteSpace', | |
value: ' ' | |
}, | |
{ | |
type: 'Number', | |
loc: null, | |
value: '0' | |
} | |
); | |
} | |
newValue.push.apply(newValue, buffer); | |
buffer = []; | |
} | |
var newValue = []; | |
var buffer = []; | |
node.children.each(function(node) { | |
if (node.type === 'Operator' && node.value === ',') { | |
flush(); | |
newValue.push(node); | |
return; | |
} | |
// remove defaults | |
if (node.type === 'Identifier') { | |
if (node.name === 'transparent' || | |
node.name === 'none' || | |
node.name === 'repeat' || | |
node.name === 'scroll') { | |
return; | |
} | |
} | |
// don't add redundant spaces | |
if (node.type === 'WhiteSpace' && (!buffer.length || lastType() === 'WhiteSpace')) { | |
return; | |
} | |
buffer.push(node); | |
}); | |
flush(); | |
node.children = new List().fromArray(newValue); | |
}; | |
},{"css-tree":42}],195:[function(require,module,exports){ | |
function removeItemAndRedundantWhiteSpace(list, item) { | |
var prev = item.prev; | |
var next = item.next; | |
if (next !== null) { | |
if (next.data.type === 'WhiteSpace' && (prev === null || prev.data.type === 'WhiteSpace')) { | |
list.remove(next); | |
} | |
} else if (prev !== null && prev.data.type === 'WhiteSpace') { | |
list.remove(prev); | |
} | |
list.remove(item); | |
} | |
module.exports = function compressBorder(node) { | |
node.children.each(function(node, item, list) { | |
if (node.type === 'Identifier' && node.name.toLowerCase() === 'none') { | |
if (list.head === list.tail) { | |
// replace `none` for zero when `none` is a single term | |
item.data = { | |
type: 'Number', | |
loc: node.loc, | |
value: '0' | |
}; | |
} else { | |
removeItemAndRedundantWhiteSpace(list, item); | |
} | |
} | |
}); | |
}; | |
},{}],196:[function(require,module,exports){ | |
module.exports = function compressFontWeight(node) { | |
var value = node.children.head.data; | |
if (value.type === 'Identifier') { | |
switch (value.name) { | |
case 'normal': | |
node.children.head.data = { | |
type: 'Number', | |
loc: value.loc, | |
value: '400' | |
}; | |
break; | |
case 'bold': | |
node.children.head.data = { | |
type: 'Number', | |
loc: value.loc, | |
value: '700' | |
}; | |
break; | |
} | |
} | |
}; | |
},{}],197:[function(require,module,exports){ | |
module.exports = function compressFont(node) { | |
var list = node.children; | |
list.eachRight(function(node, item) { | |
if (node.type === 'Identifier') { | |
if (node.name === 'bold') { | |
item.data = { | |
type: 'Number', | |
loc: node.loc, | |
value: '700' | |
}; | |
} else if (node.name === 'normal') { | |
var prev = item.prev; | |
if (prev && prev.data.type === 'Operator' && prev.data.value === '/') { | |
this.remove(prev); | |
} | |
this.remove(item); | |
} else if (node.name === 'medium') { | |
var next = item.next; | |
if (!next || next.data.type !== 'Operator') { | |
this.remove(item); | |
} | |
} | |
} | |
}); | |
// remove redundant spaces | |
list.each(function(node, item) { | |
if (node.type === 'WhiteSpace') { | |
if (!item.prev || !item.next || item.next.data.type === 'WhiteSpace') { | |
this.remove(item); | |
} | |
} | |
}); | |
if (list.isEmpty()) { | |
list.insert(list.createItem({ | |
type: 'Identifier', | |
name: 'normal' | |
})); | |
} | |
}; | |
},{}],198:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
var resolveKeyword = require('css-tree').keyword; | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
var walk = require('css-tree').walk; | |
function addRuleToMap(map, item, list, single) { | |
var node = item.data; | |
var name = resolveKeyword(node.name).basename; | |
var id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null); | |
if (!hasOwnProperty.call(map, name)) { | |
map[name] = Object.create(null); | |
} | |
if (single) { | |
delete map[name][id]; | |
} | |
if (!hasOwnProperty.call(map[name], id)) { | |
map[name][id] = new List(); | |
} | |
map[name][id].append(list.remove(item)); | |
} | |
function relocateAtrules(ast, options) { | |
var collected = Object.create(null); | |
var topInjectPoint = null; | |
ast.children.each(function(node, item, list) { | |
if (node.type === 'Atrule') { | |
var name = resolveKeyword(node.name).basename; | |
switch (name) { | |
case 'keyframes': | |
addRuleToMap(collected, item, list, true); | |
return; | |
case 'media': | |
if (options.forceMediaMerge) { | |
addRuleToMap(collected, item, list, false); | |
return; | |
} | |
break; | |
} | |
if (topInjectPoint === null && | |
name !== 'charset' && | |
name !== 'import') { | |
topInjectPoint = item; | |
} | |
} else { | |
if (topInjectPoint === null) { | |
topInjectPoint = item; | |
} | |
} | |
}); | |
for (var atrule in collected) { | |
for (var id in collected[atrule]) { | |
ast.children.insertList( | |
collected[atrule][id], | |
atrule === 'media' ? null : topInjectPoint | |
); | |
} | |
} | |
}; | |
function isMediaRule(node) { | |
return node.type === 'Atrule' && node.name === 'media'; | |
} | |
function processAtrule(node, item, list) { | |
if (!isMediaRule(node)) { | |
return; | |
} | |
var prev = item.prev && item.prev.data; | |
if (!prev || !isMediaRule(prev)) { | |
return; | |
} | |
// merge @media with same query | |
if (node.prelude && | |
prev.prelude && | |
node.prelude.id === prev.prelude.id) { | |
prev.block.children.appendList(node.block.children); | |
list.remove(item); | |
// TODO: use it when we can refer to several points in source | |
// prev.loc = { | |
// primary: prev.loc, | |
// merged: node.loc | |
// }; | |
} | |
} | |
module.exports = function rejoinAtrule(ast, options) { | |
relocateAtrules(ast, options); | |
walk(ast, { | |
visit: 'Atrule', | |
reverse: true, | |
enter: processAtrule | |
}); | |
}; | |
},{"css-tree":42}],199:[function(require,module,exports){ | |
var walk = require('css-tree').walk; | |
var utils = require('./utils'); | |
function processRule(node, item, list) { | |
var selectors = node.prelude.children; | |
var declarations = node.block.children; | |
list.prevUntil(item.prev, function(prev) { | |
// skip non-ruleset node if safe | |
if (prev.type !== 'Rule') { | |
return utils.unsafeToSkipNode.call(selectors, prev); | |
} | |
var prevSelectors = prev.prelude.children; | |
var prevDeclarations = prev.block.children; | |
// try to join rulesets with equal pseudo signature | |
if (node.pseudoSignature === prev.pseudoSignature) { | |
// try to join by selectors | |
if (utils.isEqualSelectors(prevSelectors, selectors)) { | |
prevDeclarations.appendList(declarations); | |
list.remove(item); | |
return true; | |
} | |
// try to join by declarations | |
if (utils.isEqualDeclarations(declarations, prevDeclarations)) { | |
utils.addSelectors(prevSelectors, selectors); | |
list.remove(item); | |
return true; | |
} | |
} | |
// go to prev ruleset if has no selector similarities | |
return utils.hasSimilarSelectors(selectors, prevSelectors); | |
}); | |
} | |
// NOTE: direction should be left to right, since rulesets merge to left | |
// ruleset. When direction right to left unmerged rulesets may prevent lookup | |
// TODO: remove initial merge | |
module.exports = function initialMergeRule(ast) { | |
walk(ast, { | |
visit: 'Rule', | |
enter: processRule | |
}); | |
}; | |
},{"./utils":210,"css-tree":42}],200:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
var walk = require('css-tree').walk; | |
function processRule(node, item, list) { | |
var selectors = node.prelude.children; | |
// generate new rule sets: | |
// .a, .b { color: red; } | |
// -> | |
// .a { color: red; } | |
// .b { color: red; } | |
// while there are more than 1 simple selector split for rulesets | |
while (selectors.head !== selectors.tail) { | |
var newSelectors = new List(); | |
newSelectors.insert(selectors.remove(selectors.head)); | |
list.insert(list.createItem({ | |
type: 'Rule', | |
loc: node.loc, | |
prelude: { | |
type: 'SelectorList', | |
loc: node.prelude.loc, | |
children: newSelectors | |
}, | |
block: { | |
type: 'Block', | |
loc: node.block.loc, | |
children: node.block.children.copy() | |
}, | |
pseudoSignature: node.pseudoSignature | |
}), item); | |
} | |
} | |
module.exports = function disjoinRule(ast) { | |
walk(ast, { | |
visit: 'Rule', | |
reverse: true, | |
enter: processRule | |
}); | |
}; | |
},{"css-tree":42}],201:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
var generate = require('css-tree').generate; | |
var walk = require('css-tree').walk; | |
var REPLACE = 1; | |
var REMOVE = 2; | |
var TOP = 0; | |
var RIGHT = 1; | |
var BOTTOM = 2; | |
var LEFT = 3; | |
var SIDES = ['top', 'right', 'bottom', 'left']; | |
var SIDE = { | |
'margin-top': 'top', | |
'margin-right': 'right', | |
'margin-bottom': 'bottom', | |
'margin-left': 'left', | |
'padding-top': 'top', | |
'padding-right': 'right', | |
'padding-bottom': 'bottom', | |
'padding-left': 'left', | |
'border-top-color': 'top', | |
'border-right-color': 'right', | |
'border-bottom-color': 'bottom', | |
'border-left-color': 'left', | |
'border-top-width': 'top', | |
'border-right-width': 'right', | |
'border-bottom-width': 'bottom', | |
'border-left-width': 'left', | |
'border-top-style': 'top', | |
'border-right-style': 'right', | |
'border-bottom-style': 'bottom', | |
'border-left-style': 'left' | |
}; | |
var MAIN_PROPERTY = { | |
'margin': 'margin', | |
'margin-top': 'margin', | |
'margin-right': 'margin', | |
'margin-bottom': 'margin', | |
'margin-left': 'margin', | |
'padding': 'padding', | |
'padding-top': 'padding', | |
'padding-right': 'padding', | |
'padding-bottom': 'padding', | |
'padding-left': 'padding', | |
'border-color': 'border-color', | |
'border-top-color': 'border-color', | |
'border-right-color': 'border-color', | |
'border-bottom-color': 'border-color', | |
'border-left-color': 'border-color', | |
'border-width': 'border-width', | |
'border-top-width': 'border-width', | |
'border-right-width': 'border-width', | |
'border-bottom-width': 'border-width', | |
'border-left-width': 'border-width', | |
'border-style': 'border-style', | |
'border-top-style': 'border-style', | |
'border-right-style': 'border-style', | |
'border-bottom-style': 'border-style', | |
'border-left-style': 'border-style' | |
}; | |
function TRBL(name) { | |
this.name = name; | |
this.loc = null; | |
this.iehack = undefined; | |
this.sides = { | |
'top': null, | |
'right': null, | |
'bottom': null, | |
'left': null | |
}; | |
} | |
TRBL.prototype.getValueSequence = function(declaration, count) { | |
var values = []; | |
var iehack = ''; | |
var hasBadValues = declaration.value.children.some(function(child) { | |
var special = false; | |
switch (child.type) { | |
case 'Identifier': | |
switch (child.name) { | |
case '\\0': | |
case '\\9': | |
iehack = child.name; | |
return; | |
case 'inherit': | |
case 'initial': | |
case 'unset': | |
case 'revert': | |
special = child.name; | |
break; | |
} | |
break; | |
case 'Dimension': | |
switch (child.unit) { | |
// is not supported until IE11 | |
case 'rem': | |
// v* units is too buggy across browsers and better | |
// don't merge values with those units | |
case 'vw': | |
case 'vh': | |
case 'vmin': | |
case 'vmax': | |
case 'vm': // IE9 supporting "vm" instead of "vmin". | |
special = child.unit; | |
break; | |
} | |
break; | |
case 'HexColor': // color | |
case 'Number': | |
case 'Percentage': | |
break; | |
case 'Function': | |
special = child.name; | |
break; | |
case 'WhiteSpace': | |
return false; // ignore space | |
default: | |
return true; // bad value | |
} | |
values.push({ | |
node: child, | |
special: special, | |
important: declaration.important | |
}); | |
}); | |
if (hasBadValues || values.length > count) { | |
return false; | |
} | |
if (typeof this.iehack === 'string' && this.iehack !== iehack) { | |
return false; | |
} | |
this.iehack = iehack; // move outside | |
return values; | |
}; | |
TRBL.prototype.canOverride = function(side, value) { | |
var currentValue = this.sides[side]; | |
return !currentValue || (value.important && !currentValue.important); | |
}; | |
TRBL.prototype.add = function(name, declaration) { | |
function attemptToAdd() { | |
var sides = this.sides; | |
var side = SIDE[name]; | |
if (side) { | |
if (side in sides === false) { | |
return false; | |
} | |
var values = this.getValueSequence(declaration, 1); | |
if (!values || !values.length) { | |
return false; | |
} | |
// can mix only if specials are equal | |
for (var key in sides) { | |
if (sides[key] !== null && sides[key].special !== values[0].special) { | |
return false; | |
} | |
} | |
if (!this.canOverride(side, values[0])) { | |
return true; | |
} | |
sides[side] = values[0]; | |
return true; | |
} else if (name === this.name) { | |
var values = this.getValueSequence(declaration, 4); | |
if (!values || !values.length) { | |
return false; | |
} | |
switch (values.length) { | |
case 1: | |
values[RIGHT] = values[TOP]; | |
values[BOTTOM] = values[TOP]; | |
values[LEFT] = values[TOP]; | |
break; | |
case 2: | |
values[BOTTOM] = values[TOP]; | |
values[LEFT] = values[RIGHT]; | |
break; | |
case 3: | |
values[LEFT] = values[RIGHT]; | |
break; | |
} | |
// can mix only if specials are equal | |
for (var i = 0; i < 4; i++) { | |
for (var key in sides) { | |
if (sides[key] !== null && sides[key].special !== values[i].special) { | |
return false; | |
} | |
} | |
} | |
for (var i = 0; i < 4; i++) { | |
if (this.canOverride(SIDES[i], values[i])) { | |
sides[SIDES[i]] = values[i]; | |
} | |
} | |
return true; | |
} | |
} | |
if (!attemptToAdd.call(this)) { | |
return false; | |
} | |
// TODO: use it when we can refer to several points in source | |
// if (this.loc) { | |
// this.loc = { | |
// primary: this.loc, | |
// merged: declaration.loc | |
// }; | |
// } else { | |
// this.loc = declaration.loc; | |
// } | |
if (!this.loc) { | |
this.loc = declaration.loc; | |
} | |
return true; | |
}; | |
TRBL.prototype.isOkToMinimize = function() { | |
var top = this.sides.top; | |
var right = this.sides.right; | |
var bottom = this.sides.bottom; | |
var left = this.sides.left; | |
if (top && right && bottom && left) { | |
var important = | |
top.important + | |
right.important + | |
bottom.important + | |
left.important; | |
return important === 0 || important === 4; | |
} | |
return false; | |
}; | |
TRBL.prototype.getValue = function() { | |
var result = new List(); | |
var sides = this.sides; | |
var values = [ | |
sides.top, | |
sides.right, | |
sides.bottom, | |
sides.left | |
]; | |
var stringValues = [ | |
generate(sides.top.node), | |
generate(sides.right.node), | |
generate(sides.bottom.node), | |
generate(sides.left.node) | |
]; | |
if (stringValues[LEFT] === stringValues[RIGHT]) { | |
values.pop(); | |
if (stringValues[BOTTOM] === stringValues[TOP]) { | |
values.pop(); | |
if (stringValues[RIGHT] === stringValues[TOP]) { | |
values.pop(); | |
} | |
} | |
} | |
for (var i = 0; i < values.length; i++) { | |
if (i) { | |
result.appendData({ type: 'WhiteSpace', value: ' ' }); | |
} | |
result.appendData(values[i].node); | |
} | |
if (this.iehack) { | |
result.appendData({ type: 'WhiteSpace', value: ' ' }); | |
result.appendData({ | |
type: 'Identifier', | |
loc: null, | |
name: this.iehack | |
}); | |
} | |
return { | |
type: 'Value', | |
loc: null, | |
children: result | |
}; | |
}; | |
TRBL.prototype.getDeclaration = function() { | |
return { | |
type: 'Declaration', | |
loc: this.loc, | |
important: this.sides.top.important, | |
property: this.name, | |
value: this.getValue() | |
}; | |
}; | |
function processRule(rule, shorts, shortDeclarations, lastShortSelector) { | |
var declarations = rule.block.children; | |
var selector = rule.prelude.children.first().id; | |
rule.block.children.eachRight(function(declaration, item) { | |
var property = declaration.property; | |
if (!MAIN_PROPERTY.hasOwnProperty(property)) { | |
return; | |
} | |
var key = MAIN_PROPERTY[property]; | |
var shorthand; | |
var operation; | |
if (!lastShortSelector || selector === lastShortSelector) { | |
if (key in shorts) { | |
operation = REMOVE; | |
shorthand = shorts[key]; | |
} | |
} | |
if (!shorthand || !shorthand.add(property, declaration)) { | |
operation = REPLACE; | |
shorthand = new TRBL(key); | |
// if can't parse value ignore it and break shorthand children | |
if (!shorthand.add(property, declaration)) { | |
lastShortSelector = null; | |
return; | |
} | |
} | |
shorts[key] = shorthand; | |
shortDeclarations.push({ | |
operation: operation, | |
block: declarations, | |
item: item, | |
shorthand: shorthand | |
}); | |
lastShortSelector = selector; | |
}); | |
return lastShortSelector; | |
} | |
function processShorthands(shortDeclarations, markDeclaration) { | |
shortDeclarations.forEach(function(item) { | |
var shorthand = item.shorthand; | |
if (!shorthand.isOkToMinimize()) { | |
return; | |
} | |
if (item.operation === REPLACE) { | |
item.item.data = markDeclaration(shorthand.getDeclaration()); | |
} else { | |
item.block.remove(item.item); | |
} | |
}); | |
} | |
module.exports = function restructBlock(ast, indexer) { | |
var stylesheetMap = {}; | |
var shortDeclarations = []; | |
walk(ast, { | |
visit: 'Rule', | |
reverse: true, | |
enter: function(node) { | |
var stylesheet = this.block || this.stylesheet; | |
var ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first().id; | |
var ruleMap; | |
var shorts; | |
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) { | |
ruleMap = { | |
lastShortSelector: null | |
}; | |
stylesheetMap[stylesheet.id] = ruleMap; | |
} else { | |
ruleMap = stylesheetMap[stylesheet.id]; | |
} | |
if (ruleMap.hasOwnProperty(ruleId)) { | |
shorts = ruleMap[ruleId]; | |
} else { | |
shorts = {}; | |
ruleMap[ruleId] = shorts; | |
} | |
ruleMap.lastShortSelector = processRule.call(this, node, shorts, shortDeclarations, ruleMap.lastShortSelector); | |
} | |
}); | |
processShorthands(shortDeclarations, indexer.declaration); | |
}; | |
},{"css-tree":42}],202:[function(require,module,exports){ | |
var resolveProperty = require('css-tree').property; | |
var resolveKeyword = require('css-tree').keyword; | |
var walk = require('css-tree').walk; | |
var generate = require('css-tree').generate; | |
var fingerprintId = 1; | |
var dontRestructure = { | |
'src': 1 // https://github.com/afelix/csso/issues/50 | |
}; | |
var DONT_MIX_VALUE = { | |
// https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility | |
'display': /table|ruby|flex|-(flex)?box$|grid|contents|run-in/i, | |
// https://developer.mozilla.org/en/docs/Web/CSS/text-align | |
'text-align': /^(start|end|match-parent|justify-all)$/i | |
}; | |
var CURSOR_SAFE_VALUE = [ | |
'auto', 'crosshair', 'default', 'move', 'text', 'wait', 'help', | |
'n-resize', 'e-resize', 's-resize', 'w-resize', | |
'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', | |
'pointer', 'progress', 'not-allowed', 'no-drop', 'vertical-text', 'all-scroll', | |
'col-resize', 'row-resize' | |
]; | |
var POSITION_SAFE_VALUE = [ | |
'static', 'relative', 'absolute', 'fixed' | |
]; | |
var NEEDLESS_TABLE = { | |
'border-width': ['border'], | |
'border-style': ['border'], | |
'border-color': ['border'], | |
'border-top': ['border'], | |
'border-right': ['border'], | |
'border-bottom': ['border'], | |
'border-left': ['border'], | |
'border-top-width': ['border-top', 'border-width', 'border'], | |
'border-right-width': ['border-right', 'border-width', 'border'], | |
'border-bottom-width': ['border-bottom', 'border-width', 'border'], | |
'border-left-width': ['border-left', 'border-width', 'border'], | |
'border-top-style': ['border-top', 'border-style', 'border'], | |
'border-right-style': ['border-right', 'border-style', 'border'], | |
'border-bottom-style': ['border-bottom', 'border-style', 'border'], | |
'border-left-style': ['border-left', 'border-style', 'border'], | |
'border-top-color': ['border-top', 'border-color', 'border'], | |
'border-right-color': ['border-right', 'border-color', 'border'], | |
'border-bottom-color': ['border-bottom', 'border-color', 'border'], | |
'border-left-color': ['border-left', 'border-color', 'border'], | |
'margin-top': ['margin'], | |
'margin-right': ['margin'], | |
'margin-bottom': ['margin'], | |
'margin-left': ['margin'], | |
'padding-top': ['padding'], | |
'padding-right': ['padding'], | |
'padding-bottom': ['padding'], | |
'padding-left': ['padding'], | |
'font-style': ['font'], | |
'font-variant': ['font'], | |
'font-weight': ['font'], | |
'font-size': ['font'], | |
'font-family': ['font'], | |
'list-style-type': ['list-style'], | |
'list-style-position': ['list-style'], | |
'list-style-image': ['list-style'] | |
}; | |
function getPropertyFingerprint(propertyName, declaration, fingerprints) { | |
var realName = resolveProperty(propertyName).basename; | |
if (realName === 'background') { | |
return propertyName + ':' + generate(declaration.value); | |
} | |
var declarationId = declaration.id; | |
var fingerprint = fingerprints[declarationId]; | |
if (!fingerprint) { | |
switch (declaration.value.type) { | |
case 'Value': | |
var vendorId = ''; | |
var iehack = ''; | |
var special = {}; | |
var raw = false; | |
declaration.value.children.each(function walk(node) { | |
switch (node.type) { | |
case 'Value': | |
case 'Brackets': | |
case 'Parentheses': | |
node.children.each(walk); | |
break; | |
case 'Raw': | |
raw = true; | |
break; | |
case 'Identifier': | |
var name = node.name; | |
if (!vendorId) { | |
vendorId = resolveKeyword(name).vendor; | |
} | |
if (/\\[09]/.test(name)) { | |
iehack = RegExp.lastMatch; | |
} | |
if (realName === 'cursor') { | |
if (CURSOR_SAFE_VALUE.indexOf(name) === -1) { | |
special[name] = true; | |
} | |
} else if (realName === 'position') { | |
if (POSITION_SAFE_VALUE.indexOf(name) === -1) { | |
special[name] = true; | |
} | |
} else if (DONT_MIX_VALUE.hasOwnProperty(realName)) { | |
if (DONT_MIX_VALUE[realName].test(name)) { | |
special[name] = true; | |
} | |
} | |
break; | |
case 'Function': | |
var name = node.name; | |
if (!vendorId) { | |
vendorId = resolveKeyword(name).vendor; | |
} | |
if (name === 'rect') { | |
// there are 2 forms of rect: | |
// rect(<top>, <right>, <bottom>, <left>) - standart | |
// rect(<top> <right> <bottom> <left>) – backwards compatible syntax | |
// only the same form values can be merged | |
var hasComma = node.children.some(function(node) { | |
return node.type === 'Operator' && node.value === ','; | |
}); | |
if (!hasComma) { | |
name = 'rect-backward'; | |
} | |
} | |
special[name + '()'] = true; | |
// check nested tokens too | |
node.children.each(walk); | |
break; | |
case 'Dimension': | |
var unit = node.unit; | |
switch (unit) { | |
// is not supported until IE11 | |
case 'rem': | |
// v* units is too buggy across browsers and better | |
// don't merge values with those units | |
case 'vw': | |
case 'vh': | |
case 'vmin': | |
case 'vmax': | |
case 'vm': // IE9 supporting "vm" instead of "vmin". | |
special[unit] = true; | |
break; | |
} | |
break; | |
} | |
}); | |
fingerprint = raw | |
? '!' + fingerprintId++ | |
: '!' + Object.keys(special).sort() + '|' + iehack + vendorId; | |
break; | |
case 'Raw': | |
fingerprint = '!' + declaration.value.value; | |
break; | |
default: | |
fingerprint = generate(declaration.value); | |
} | |
fingerprints[declarationId] = fingerprint; | |
} | |
return propertyName + fingerprint; | |
} | |
function needless(props, declaration, fingerprints) { | |
var property = resolveProperty(declaration.property); | |
if (NEEDLESS_TABLE.hasOwnProperty(property.basename)) { | |
var table = NEEDLESS_TABLE[property.basename]; | |
for (var i = 0; i < table.length; i++) { | |
var ppre = getPropertyFingerprint(property.prefix + table[i], declaration, fingerprints); | |
var prev = props.hasOwnProperty(ppre) ? props[ppre] : null; | |
if (prev && (!declaration.important || prev.item.data.important)) { | |
return prev; | |
} | |
} | |
} | |
} | |
function processRule(rule, item, list, props, fingerprints) { | |
var declarations = rule.block.children; | |
declarations.eachRight(function(declaration, declarationItem) { | |
var property = declaration.property; | |
var fingerprint = getPropertyFingerprint(property, declaration, fingerprints); | |
var prev = props[fingerprint]; | |
if (prev && !dontRestructure.hasOwnProperty(property)) { | |
if (declaration.important && !prev.item.data.important) { | |
props[fingerprint] = { | |
block: declarations, | |
item: declarationItem | |
}; | |
prev.block.remove(prev.item); | |
// TODO: use it when we can refer to several points in source | |
// declaration.loc = { | |
// primary: declaration.loc, | |
// merged: prev.item.data.loc | |
// }; | |
} else { | |
declarations.remove(declarationItem); | |
// TODO: use it when we can refer to several points in source | |
// prev.item.data.loc = { | |
// primary: prev.item.data.loc, | |
// merged: declaration.loc | |
// }; | |
} | |
} else { | |
var prev = needless(props, declaration, fingerprints); | |
if (prev) { | |
declarations.remove(declarationItem); | |
// TODO: use it when we can refer to several points in source | |
// prev.item.data.loc = { | |
// primary: prev.item.data.loc, | |
// merged: declaration.loc | |
// }; | |
} else { | |
declaration.fingerprint = fingerprint; | |
props[fingerprint] = { | |
block: declarations, | |
item: declarationItem | |
}; | |
} | |
} | |
}); | |
if (declarations.isEmpty()) { | |
list.remove(item); | |
} | |
} | |
module.exports = function restructBlock(ast) { | |
var stylesheetMap = {}; | |
var fingerprints = Object.create(null); | |
walk(ast, { | |
visit: 'Rule', | |
reverse: true, | |
enter: function(node, item, list) { | |
var stylesheet = this.block || this.stylesheet; | |
var ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first().id; | |
var ruleMap; | |
var props; | |
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) { | |
ruleMap = {}; | |
stylesheetMap[stylesheet.id] = ruleMap; | |
} else { | |
ruleMap = stylesheetMap[stylesheet.id]; | |
} | |
if (ruleMap.hasOwnProperty(ruleId)) { | |
props = ruleMap[ruleId]; | |
} else { | |
props = {}; | |
ruleMap[ruleId] = props; | |
} | |
processRule.call(this, node, item, list, props, fingerprints); | |
} | |
}); | |
}; | |
},{"css-tree":42}],203:[function(require,module,exports){ | |
var walk = require('css-tree').walk; | |
var utils = require('./utils'); | |
/* | |
At this step all rules has single simple selector. We try to join by equal | |
declaration blocks to first rule, e.g. | |
.a { color: red } | |
b { ... } | |
.b { color: red } | |
-> | |
.a, .b { color: red } | |
b { ... } | |
*/ | |
function processRule(node, item, list) { | |
var selectors = node.prelude.children; | |
var declarations = node.block.children; | |
var nodeCompareMarker = selectors.first().compareMarker; | |
var skippedCompareMarkers = {}; | |
list.nextUntil(item.next, function(next, nextItem) { | |
// skip non-ruleset node if safe | |
if (next.type !== 'Rule') { | |
return utils.unsafeToSkipNode.call(selectors, next); | |
} | |
if (node.pseudoSignature !== next.pseudoSignature) { | |
return true; | |
} | |
var nextFirstSelector = next.prelude.children.head; | |
var nextDeclarations = next.block.children; | |
var nextCompareMarker = nextFirstSelector.data.compareMarker; | |
// if next ruleset has same marked as one of skipped then stop joining | |
if (nextCompareMarker in skippedCompareMarkers) { | |
return true; | |
} | |
// try to join by selectors | |
if (selectors.head === selectors.tail) { | |
if (selectors.first().id === nextFirstSelector.data.id) { | |
declarations.appendList(nextDeclarations); | |
list.remove(nextItem); | |
return; | |
} | |
} | |
// try to join by properties | |
if (utils.isEqualDeclarations(declarations, nextDeclarations)) { | |
var nextStr = nextFirstSelector.data.id; | |
selectors.some(function(data, item) { | |
var curStr = data.id; | |
if (nextStr < curStr) { | |
selectors.insert(nextFirstSelector, item); | |
return true; | |
} | |
if (!item.next) { | |
selectors.insert(nextFirstSelector); | |
return true; | |
} | |
}); | |
list.remove(nextItem); | |
return; | |
} | |
// go to next ruleset if current one can be skipped (has no equal specificity nor element selector) | |
if (nextCompareMarker === nodeCompareMarker) { | |
return true; | |
} | |
skippedCompareMarkers[nextCompareMarker] = true; | |
}); | |
} | |
module.exports = function mergeRule(ast) { | |
walk(ast, { | |
visit: 'Rule', | |
enter: processRule | |
}); | |
}; | |
},{"./utils":210,"css-tree":42}],204:[function(require,module,exports){ | |
var List = require('css-tree').List; | |
var walk = require('css-tree').walk; | |
var utils = require('./utils'); | |
function calcSelectorLength(list) { | |
var length = 0; | |
list.each(function(data) { | |
length += data.id.length + 1; | |
}); | |
return length - 1; | |
} | |
function calcDeclarationsLength(tokens) { | |
var length = 0; | |
for (var i = 0; i < tokens.length; i++) { | |
length += tokens[i].length; | |
} | |
return ( | |
length + // declarations | |
tokens.length - 1 // delimeters | |
); | |
} | |
function processRule(node, item, list) { | |
var avoidRulesMerge = this.block !== null ? this.block.avoidRulesMerge : false; | |
var selectors = node.prelude.children; | |
var block = node.block; | |
var disallowDownMarkers = Object.create(null); | |
var allowMergeUp = true; | |
var allowMergeDown = true; | |
list.prevUntil(item.prev, function(prev, prevItem) { | |
// skip non-ruleset node if safe | |
if (prev.type !== 'Rule') { | |
return utils.unsafeToSkipNode.call(selectors, prev); | |
} | |
var prevSelectors = prev.prelude.children; | |
var prevBlock = prev.block; | |
if (node.pseudoSignature !== prev.pseudoSignature) { | |
return true; | |
} | |
allowMergeDown = !prevSelectors.some(function(selector) { | |
return selector.compareMarker in disallowDownMarkers; | |
}); | |
// try prev ruleset if simpleselectors has no equal specifity and element selector | |
if (!allowMergeDown && !allowMergeUp) { | |
return true; | |
} | |
// try to join by selectors | |
if (allowMergeUp && utils.isEqualSelectors(prevSelectors, selectors)) { | |
prevBlock.children.appendList(block.children); | |
list.remove(item); | |
return true; | |
} | |
// try to join by properties | |
var diff = utils.compareDeclarations(block.children, prevBlock.children); | |
// console.log(diff.eq, diff.ne1, diff.ne2); | |
if (diff.eq.length) { | |
if (!diff.ne1.length && !diff.ne2.length) { | |
// equal blocks | |
if (allowMergeDown) { | |
utils.addSelectors(selectors, prevSelectors); | |
list.remove(prevItem); | |
} | |
return true; | |
} else if (!avoidRulesMerge) { /* probably we don't need to prevent those merges for @keyframes | |
TODO: need to be checked */ | |
if (diff.ne1.length && !diff.ne2.length) { | |
// prevBlock is subset block | |
var selectorLength = calcSelectorLength(selectors); | |
var blockLength = calcDeclarationsLength(diff.eq); // declarations length | |
if (allowMergeUp && selectorLength < blockLength) { | |
utils.addSelectors(prevSelectors, selectors); | |
block.children = new List().fromArray(diff.ne1); | |
} | |
} else if (!diff.ne1.length && diff.ne2.length) { | |
// node is subset of prevBlock | |
var selectorLength = calcSelectorLength(prevSelectors); | |
var blockLength = calcDeclarationsLength(diff.eq); // declarations length | |
if (allowMergeDown && selectorLength < blockLength) { | |
utils.addSelectors(selectors, prevSelectors); | |
prevBlock.children = new List().fromArray(diff.ne2); | |
} | |
} else { | |
// diff.ne1.length && diff.ne2.length | |
// extract equal block | |
var newSelector = { | |
type: 'SelectorList', | |
loc: null, | |
children: utils.addSelectors(prevSelectors.copy(), selectors) | |
}; | |
var newBlockLength = calcSelectorLength(newSelector.children) + 2; // selectors length + curly braces length | |
var blockLength = calcDeclarationsLength(diff.eq); // declarations length | |
// create new ruleset if declarations length greater than | |
// ruleset description overhead | |
if (allowMergeDown && blockLength >= newBlockLength) { | |
var newRule = { | |
type: 'Rule', | |
loc: null, | |
prelude: newSelector, | |
block: { | |
type: 'Block', | |
loc: null, | |
children: new List().fromArray(diff.eq) | |
}, | |
pseudoSignature: node.pseudoSignature | |
}; | |
block.children = new List().fromArray(diff.ne1); | |
prevBlock.children = new List().fromArray(diff.ne2.concat(diff.ne2overrided)); | |
list.insert(list.createItem(newRule), prevItem); | |
return true; | |
} | |
} | |
} | |
} | |
if (allowMergeUp) { | |
// TODO: disallow up merge only if any property interception only (i.e. diff.ne2overrided.length > 0); | |
// await property families to find property interception correctly | |
allowMergeUp = !prevSelectors.some(function(prevSelector) { | |
return selectors.some(function(selector) { | |
return selector.compareMarker === prevSelector.compareMarker; | |
}); | |
}); | |
} | |
prevSelectors.each(function(data) { | |
disallowDownMarkers[data.compareMarker] = true; | |
}); | |
}); | |
} | |
module.exports = function restructRule(ast) { | |
walk(ast, { | |
visit: 'Rule', | |
reverse: true, | |
enter: processRule | |
}); | |
}; | |
},{"./utils":210,"css-tree":42}],205:[function(require,module,exports){ | |
var prepare = require('./prepare/index'); | |
var mergeAtrule = require('./1-mergeAtrule'); | |
var initialMergeRuleset = require('./2-initialMergeRuleset'); | |
var disjoinRuleset = require('./3-disjoinRuleset'); | |
var restructShorthand = require('./4-restructShorthand'); | |
var restructBlock = require('./6-restructBlock'); | |
var mergeRuleset = require('./7-mergeRuleset'); | |
var restructRuleset = require('./8-restructRuleset'); | |
module.exports = function(ast, options) { | |
// prepare ast for restructing | |
var indexer = prepare(ast, options); | |
options.logger('prepare', ast); | |
mergeAtrule(ast, options); | |
options.logger('mergeAtrule', ast); | |
initialMergeRuleset(ast); | |
options.logger('initialMergeRuleset', ast); | |
disjoinRuleset(ast); | |
options.logger('disjoinRuleset', ast); | |
restructShorthand(ast, indexer); | |
options.logger('restructShorthand', ast); | |
restructBlock(ast); | |
options.logger('restructBlock', ast); | |
mergeRuleset(ast); | |
options.logger('mergeRuleset', ast); | |
restructRuleset(ast); | |
options.logger('restructRuleset', ast); | |
}; | |
},{"./1-mergeAtrule":198,"./2-initialMergeRuleset":199,"./3-disjoinRuleset":200,"./4-restructShorthand":201,"./6-restructBlock":202,"./7-mergeRuleset":203,"./8-restructRuleset":204,"./prepare/index":207}],206:[function(require,module,exports){ | |
var generate = require('css-tree').generate; | |
function Index() { | |
this.seed = 0; | |
this.map = Object.create(null); | |
} | |
Index.prototype.resolve = function(str) { | |
var index = this.map[str]; | |
if (!index) { | |
index = ++this.seed; | |
this.map[str] = index; | |
} | |
return index; | |
}; | |
module.exports = function createDeclarationIndexer() { | |
var ids = new Index(); | |
return function markDeclaration(node) { | |
var id = generate(node); | |
node.id = ids.resolve(id); | |
node.length = id.length; | |
node.fingerprint = null; | |
return node; | |
}; | |
}; | |
},{"css-tree":42}],207:[function(require,module,exports){ | |
var resolveKeyword = require('css-tree').keyword; | |
var walk = require('css-tree').walk; | |
var generate = require('css-tree').generate; | |
var createDeclarationIndexer = require('./createDeclarationIndexer'); | |
var processSelector = require('./processSelector'); | |
module.exports = function prepare(ast, options) { | |
var markDeclaration = createDeclarationIndexer(); | |
walk(ast, { | |
visit: 'Rule', | |
enter: function processRule(node) { | |
node.block.children.each(markDeclaration); | |
processSelector(node, options.usage); | |
} | |
}); | |
walk(ast, { | |
visit: 'Atrule', | |
enter: function(node) { | |
if (node.prelude) { | |
node.prelude.id = null; // pre-init property to avoid multiple hidden class for generate | |
node.prelude.id = generate(node.prelude); | |
} | |
// compare keyframe selectors by its values | |
// NOTE: still no clarification about problems with keyframes selector grouping (issue #197) | |
if (resolveKeyword(node.name).basename === 'keyframes') { | |
node.block.avoidRulesMerge = true; /* probably we don't need to prevent those merges for @keyframes | |
TODO: need to be checked */ | |
node.block.children.each(function(rule) { | |
rule.prelude.children.each(function(simpleselector) { | |
simpleselector.compareMarker = simpleselector.id; | |
}); | |
}); | |
} | |
} | |
}); | |
return { | |
declaration: markDeclaration | |
}; | |
}; | |
},{"./createDeclarationIndexer":206,"./processSelector":208,"css-tree":42}],208:[function(require,module,exports){ | |
var generate = require('css-tree').generate; | |
var specificity = require('./specificity'); | |
var nonFreezePseudoElements = { | |
'first-letter': true, | |
'first-line': true, | |
'after': true, | |
'before': true | |
}; | |
var nonFreezePseudoClasses = { | |
'link': true, | |
'visited': true, | |
'hover': true, | |
'active': true, | |
'first-letter': true, | |
'first-line': true, | |
'after': true, | |
'before': true | |
}; | |
module.exports = function freeze(node, usageData) { | |
var pseudos = Object.create(null); | |
var hasPseudo = false; | |
node.prelude.children.each(function(simpleSelector) { | |
var tagName = '*'; | |
var scope = 0; | |
simpleSelector.children.each(function(node) { | |
switch (node.type) { | |
case 'ClassSelector': | |
if (usageData && usageData.scopes) { | |
var classScope = usageData.scopes[node.name] || 0; | |
if (scope !== 0 && classScope !== scope) { | |
throw new Error('Selector can\'t has classes from different scopes: ' + generate(simpleSelector)); | |
} | |
scope = classScope; | |
} | |
break; | |
case 'PseudoClassSelector': | |
var name = node.name.toLowerCase(); | |
if (!nonFreezePseudoClasses.hasOwnProperty(name)) { | |
pseudos[name] = true; | |
hasPseudo = true; | |
} | |
break; | |
case 'PseudoElementSelector': | |
var name = node.name.toLowerCase(); | |
if (!nonFreezePseudoElements.hasOwnProperty(name)) { | |
pseudos[name] = true; | |
hasPseudo = true; | |
} | |
break; | |
case 'TypeSelector': | |
tagName = node.name.toLowerCase(); | |
break; | |
case 'AttributeSelector': | |
if (node.flags) { | |
pseudos['[' + node.flags.toLowerCase() + ']'] = true; | |
hasPseudo = true; | |
} | |
break; | |
case 'WhiteSpace': | |
case 'Combinator': | |
tagName = '*'; | |
break; | |
} | |
}); | |
simpleSelector.compareMarker = specificity(simpleSelector).toString(); | |
simpleSelector.id = null; // pre-init property to avoid multiple hidden class | |
simpleSelector.id = generate(simpleSelector); | |
if (scope) { | |
simpleSelector.compareMarker += ':' + scope; | |
} | |
if (tagName !== '*') { | |
simpleSelector.compareMarker += ',' + tagName; | |
} | |
}); | |
// add property to all rule nodes to avoid multiple hidden class | |
node.pseudoSignature = hasPseudo && Object.keys(pseudos).sort().join(','); | |
}; | |
},{"./specificity":209,"css-tree":42}],209:[function(require,module,exports){ | |
module.exports = function specificity(simpleSelector) { | |
var A = 0; | |
var B = 0; | |
var C = 0; | |
simpleSelector.children.each(function walk(node) { | |
switch (node.type) { | |
case 'SelectorList': | |
case 'Selector': | |
node.children.each(walk); | |
break; | |
case 'IdSelector': | |
A++; | |
break; | |
case 'ClassSelector': | |
case 'AttributeSelector': | |
B++; | |
break; | |
case 'PseudoClassSelector': | |
switch (node.name.toLowerCase()) { | |
case 'not': | |
node.children.each(walk); | |
break; | |
case 'before': | |
case 'after': | |
case 'first-line': | |
case 'first-letter': | |
C++; | |
break; | |
// TODO: support for :nth-*(.. of <SelectorList>), :matches(), :has() | |
default: | |
B++; | |
} | |
break; | |
case 'PseudoElementSelector': | |
C++; | |
break; | |
case 'TypeSelector': | |
// ignore universal selector | |
if (node.name.charAt(node.name.length - 1) !== '*') { | |
C++; | |
} | |
break; | |
} | |
}); | |
return [A, B, C]; | |
}; | |
},{}],210:[function(require,module,exports){ | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
function isEqualSelectors(a, b) { | |
var cursor1 = a.head; | |
var cursor2 = b.head; | |
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) { | |
cursor1 = cursor1.next; | |
cursor2 = cursor2.next; | |
} | |
return cursor1 === null && cursor2 === null; | |
} | |
function isEqualDeclarations(a, b) { | |
var cursor1 = a.head; | |
var cursor2 = b.head; | |
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) { | |
cursor1 = cursor1.next; | |
cursor2 = cursor2.next; | |
} | |
return cursor1 === null && cursor2 === null; | |
} | |
function compareDeclarations(declarations1, declarations2) { | |
var result = { | |
eq: [], | |
ne1: [], | |
ne2: [], | |
ne2overrided: [] | |
}; | |
var fingerprints = Object.create(null); | |
var declarations2hash = Object.create(null); | |
for (var cursor = declarations2.head; cursor; cursor = cursor.next) { | |
declarations2hash[cursor.data.id] = true; | |
} | |
for (var cursor = declarations1.head; cursor; cursor = cursor.next) { | |
var data = cursor.data; | |
if (data.fingerprint) { | |
fingerprints[data.fingerprint] = data.important; | |
} | |
if (declarations2hash[data.id]) { | |
declarations2hash[data.id] = false; | |
result.eq.push(data); | |
} else { | |
result.ne1.push(data); | |
} | |
} | |
for (var cursor = declarations2.head; cursor; cursor = cursor.next) { | |
var data = cursor.data; | |
if (declarations2hash[data.id]) { | |
// if declarations1 has overriding declaration, this is not a difference | |
// but take in account !important - prev should be equal or greater than follow | |
if (hasOwnProperty.call(fingerprints, data.fingerprint) && | |
Number(fingerprints[data.fingerprint]) >= Number(data.important)) { | |
result.ne2overrided.push(data); | |
} else { | |
result.ne2.push(data); | |
} | |
} | |
} | |
return result; | |
} | |
function addSelectors(dest, source) { | |
source.each(function(sourceData) { | |
var newStr = sourceData.id; | |
var cursor = dest.head; | |
while (cursor) { | |
var nextStr = cursor.data.id; | |
if (nextStr === newStr) { | |
return; | |
} | |
if (nextStr > newStr) { | |
break; | |
} | |
cursor = cursor.next; | |
} | |
dest.insert(dest.createItem(sourceData), cursor); | |
}); | |
return dest; | |
} | |
// check if simpleselectors has no equal specificity and element selector | |
function hasSimilarSelectors(selectors1, selectors2) { | |
var cursor1 = selectors1.head; | |
while (cursor1 !== null) { | |
var cursor2 = selectors2.head; | |
while (cursor2 !== null) { | |
if (cursor1.data.compareMarker === cursor2.data.compareMarker) { | |
return true; | |
} | |
cursor2 = cursor2.next; | |
} | |
cursor1 = cursor1.next; | |
} | |
return false; | |
} | |
// test node can't to be skipped | |
function unsafeToSkipNode(node) { | |
switch (node.type) { | |
case 'Rule': | |
// unsafe skip ruleset with selector similarities | |
return hasSimilarSelectors(node.prelude.children, this); | |
case 'Atrule': | |
// can skip at-rules with blocks | |
if (node.block) { | |
// unsafe skip at-rule if block contains something unsafe to skip | |
return node.block.children.some(unsafeToSkipNode, this); | |
} | |
break; | |
case 'Declaration': | |
return false; | |
} | |
// unsafe by default | |
return true; | |
} | |
module.exports = { | |
isEqualSelectors: isEqualSelectors, | |
isEqualDeclarations: isEqualDeclarations, | |
compareDeclarations: compareDeclarations, | |
addSelectors: addSelectors, | |
hasSimilarSelectors: hasSimilarSelectors, | |
unsafeToSkipNode: unsafeToSkipNode | |
}; | |
},{}],211:[function(require,module,exports){ | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
function buildMap(list, caseInsensitive) { | |
var map = Object.create(null); | |
if (!Array.isArray(list)) { | |
return null; | |
} | |
for (var i = 0; i < list.length; i++) { | |
var name = list[i]; | |
if (caseInsensitive) { | |
name = name.toLowerCase(); | |
} | |
map[name] = true; | |
} | |
return map; | |
} | |
function buildList(data) { | |
if (!data) { | |
return null; | |
} | |
var tags = buildMap(data.tags, true); | |
var ids = buildMap(data.ids); | |
var classes = buildMap(data.classes); | |
if (tags === null && | |
ids === null && | |
classes === null) { | |
return null; | |
} | |
return { | |
tags: tags, | |
ids: ids, | |
classes: classes | |
}; | |
} | |
function buildIndex(data) { | |
var scopes = false; | |
if (data.scopes && Array.isArray(data.scopes)) { | |
scopes = Object.create(null); | |
for (var i = 0; i < data.scopes.length; i++) { | |
var list = data.scopes[i]; | |
if (!list || !Array.isArray(list)) { | |
throw new Error('Wrong usage format'); | |
} | |
for (var j = 0; j < list.length; j++) { | |
var name = list[j]; | |
if (hasOwnProperty.call(scopes, name)) { | |
throw new Error('Class can\'t be used for several scopes: ' + name); | |
} | |
scopes[name] = i + 1; | |
} | |
} | |
} | |
return { | |
whitelist: buildList(data), | |
blacklist: buildList(data.blacklist), | |
scopes: scopes | |
}; | |
} | |
module.exports = { | |
buildIndex: buildIndex | |
}; | |
},{}],212:[function(require,module,exports){ | |
module.exports={ | |
"_from": "csso", | |
"_id": "[email protected]", | |
"_inBundle": false, | |
"_integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", | |
"_location": "/csso", | |
"_phantomChildren": {}, | |
"_requested": { | |
"type": "tag", | |
"registry": true, | |
"raw": "csso", | |
"name": "csso", | |
"escapedName": "csso", | |
"rawSpec": "", | |
"saveSpec": null, | |
"fetchSpec": "latest" | |
}, | |
"_requiredBy": [ | |
"#USER", | |
"/" | |
], | |
"_resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", | |
"_shasum": "7b9eb8be61628973c1b261e169d2f024008e758b", | |
"_spec": "csso", | |
"_where": "/Users/gvrizzo/cssscan-landing/demo-build", | |
"author": { | |
"name": "Sergey Kryzhanovsky", | |
"email": "[email protected]", | |
"url": "https://github.com/afelix" | |
}, | |
"bugs": { | |
"url": "https://github.com/css/csso/issues" | |
}, | |
"bundleDependencies": false, | |
"dependencies": { | |
"css-tree": "1.0.0-alpha.29" | |
}, | |
"deprecated": false, | |
"description": "CSS minifier with structural optimisations", | |
"devDependencies": { | |
"browserify": "^13.0.0", | |
"coveralls": "^2.11.6", | |
"eslint": "^2.2.0", | |
"istanbul": "^0.4.2", | |
"jscs": "~3.0.7", | |
"mocha": "^3.5.3", | |
"package-json-versionify": "^1.0.4", | |
"source-map": "^0.5.6", | |
"uglify-js": "^2.6.1" | |
}, | |
"engines": { | |
"node": ">=0.10.0" | |
}, | |
"eslintConfig": { | |
"env": { | |
"node": true, | |
"mocha": true, | |
"es6": true | |
}, | |
"rules": { | |
"no-duplicate-case": 2, | |
"no-undef": 2, | |
"no-unused-vars": [ | |
2, | |
{ | |
"vars": "all", | |
"args": "after-used" | |
} | |
] | |
} | |
}, | |
"files": [ | |
"dist/csso-browser.js", | |
"lib", | |
"HISTORY.md", | |
"LICENSE", | |
"README.md" | |
], | |
"homepage": "https://github.com/css/csso", | |
"keywords": [ | |
"css", | |
"compress", | |
"minifier", | |
"minify", | |
"optimise", | |
"optimisation", | |
"csstree" | |
], | |
"license": "MIT", | |
"main": "./lib/index", | |
"maintainers": [ | |
{ | |
"name": "Roman Dvornov", | |
"email": "[email protected]" | |
} | |
], | |
"name": "csso", | |
"repository": { | |
"type": "git", | |
"url": "git+https://github.com/css/csso.git" | |
}, | |
"scripts": { | |
"browserify": "browserify -t package-json-versionify --standalone csso lib/index.js | uglifyjs --compress --mangle -o dist/csso-browser.js", | |
"codestyle": "jscs lib test && eslint lib test", | |
"codestyle-and-test": "npm run codestyle && npm test", | |
"coverage": "istanbul cover _mocha -- -R dot", | |
"coveralls": "istanbul cover _mocha --report lcovonly -- -R dot && cat ./coverage/lcov.info | coveralls", | |
"gh-pages": "git clone --depth=1 -b gh-pages https://github.com/css/csso.git .gh-pages && npm run browserify && cp dist/csso-browser.js .gh-pages/ && cd .gh-pages && git commit -am \"update\" && git push && cd .. && rm -rf .gh-pages", | |
"hydrogen": "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm --trace_hydrogen_file=code.cfg --print-opt-code bin/csso --stat -o /dev/null", | |
"postpublish": "npm run gh-pages", | |
"prepublish": "npm run browserify", | |
"test": "mocha --reporter dot", | |
"travis": "npm run codestyle-and-test && npm run coveralls" | |
}, | |
"version": "3.5.1" | |
} | |
},{}],213:[function(require,module,exports){ | |
'use strict'; | |
const isObj = require('is-obj'); | |
function getPathSegments(path) { | |
const pathArr = path.split('.'); | |
const parts = []; | |
for (let i = 0; i < pathArr.length; i++) { | |
let p = pathArr[i]; | |
while (p[p.length - 1] === '\\' && pathArr[i + 1] !== undefined) { | |
p = p.slice(0, -1) + '.'; | |
p += pathArr[++i]; | |
} | |
parts.push(p); | |
} | |
return parts; | |
} | |
module.exports = { | |
get(obj, path, value) { | |
if (!isObj(obj) || typeof path !== 'string') { | |
return value === undefined ? obj : value; | |
} | |
const pathArr = getPathSegments(path); | |
for (let i = 0; i < pathArr.length; i++) { | |
if (!Object.prototype.propertyIsEnumerable.call(obj, pathArr[i])) { | |
return value; | |
} | |
obj = obj[pathArr[i]]; | |
if (obj === undefined || obj === null) { | |
// `obj` is either `undefined` or `null` so we want to stop the loop, and | |
// if this is not the last bit of the path, and | |
// if it did't return `undefined` | |
// it would return `null` if `obj` is `null` | |
// but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied value, not `null` | |
if (i !== pathArr.length - 1) { | |
return value; | |
} | |
break; | |
} | |
} | |
return obj; | |
}, | |
set(obj, path, value) { | |
if (!isObj(obj) || typeof path !== 'string') { | |
return obj; | |
} | |
const root = obj; | |
const pathArr = getPathSegments(path); | |
for (let i = 0; i < pathArr.length; i++) { | |
const p = pathArr[i]; | |
if (!isObj(obj[p])) { | |
obj[p] = {}; | |
} | |
if (i === pathArr.length - 1) { | |
obj[p] = value; | |
} | |
obj = obj[p]; | |
} | |
return root; | |
}, | |
delete(obj, path) { | |
if (!isObj(obj) || typeof path !== 'string') { | |
return; | |
} | |
const pathArr = getPathSegments(path); | |
for (let i = 0; i < pathArr.length; i++) { | |
const p = pathArr[i]; | |
if (i === pathArr.length - 1) { | |
delete obj[p]; | |
return; | |
} | |
obj = obj[p]; | |
if (!isObj(obj)) { | |
return; | |
} | |
} | |
}, | |
has(obj, path) { | |
if (!isObj(obj) || typeof path !== 'string') { | |
return false; | |
} | |
const pathArr = getPathSegments(path); | |
for (let i = 0; i < pathArr.length; i++) { | |
if (isObj(obj)) { | |
if (!(pathArr[i] in obj)) { | |
return false; | |
} | |
obj = obj[pathArr[i]]; | |
} else { | |
return false; | |
} | |
} | |
return true; | |
} | |
}; | |
},{"is-obj":217}],214:[function(require,module,exports){ | |
module.exports = { | |
"3.0": "66", | |
"2.0": "61", | |
"1.8": "59", | |
"1.7": "58", | |
"1.6": "56", | |
"1.5": "54", | |
"1.4": "53", | |
"1.3": "52", | |
"1.2": "51", | |
"1.1": "50", | |
"1.0": "49", | |
"0.37": "49", | |
"0.36": "47", | |
"0.35": "45", | |
"0.34": "45", | |
"0.33": "45", | |
"0.32": "45", | |
"0.31": "44", | |
"0.30": "44", | |
"0.29": "43", | |
"0.28": "43", | |
"0.27": "42", | |
"0.26": "42", | |
"0.25": "42", | |
"0.24": "41", | |
"0.23": "41", | |
"0.22": "41", | |
"0.21": "40", | |
"0.20": "39" | |
}; | |
},{}],215:[function(require,module,exports){ | |
module.exports = function (ary, item) { | |
var i = -1, indexes = [] | |
while((i = ary.indexOf(item, i + 1)) !== -1) | |
indexes.push(i) | |
return indexes | |
} | |
},{}],216:[function(require,module,exports){ | |
if (typeof Object.create === 'function') { | |
// implementation from standard node.js 'util' module | |
module.exports = function inherits(ctor, superCtor) { | |
ctor.super_ = superCtor | |
ctor.prototype = Object.create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
}; | |
} else { | |
// old school shim for old browsers | |
module.exports = function inherits(ctor, superCtor) { | |
ctor.super_ = superCtor | |
var TempCtor = function () {} | |
TempCtor.prototype = superCtor.prototype | |
ctor.prototype = new TempCtor() | |
ctor.prototype.constructor = ctor | |
} | |
} | |
},{}],217:[function(require,module,exports){ | |
'use strict'; | |
module.exports = function (x) { | |
var type = typeof x; | |
return x !== null && (type === 'object' || type === 'function'); | |
}; | |
},{}],218:[function(require,module,exports){ | |
module.exports=[ | |
{ | |
"name": "nodejs", | |
"version": "0.2.0", | |
"date": "2011-08-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.3.0", | |
"date": "2011-08-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.4.0", | |
"date": "2011-08-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.5.0", | |
"date": "2011-08-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.6.0", | |
"date": "2011-11-04", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.7.0", | |
"date": "2012-01-17", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.8.0", | |
"date": "2012-06-22", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.9.0", | |
"date": "2012-07-20", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.10.0", | |
"date": "2013-03-11", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.11.0", | |
"date": "2013-03-28", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "0.12.0", | |
"date": "2015-02-06", | |
"lts": false | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.0.0", | |
"date": "2015-01-14" | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.1.0", | |
"date": "2015-02-03" | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.2.0", | |
"date": "2015-02-11" | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.3.0", | |
"date": "2015-02-20" | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.5.0", | |
"date": "2015-03-06" | |
}, | |
{ | |
"name": "iojs", | |
"version": "1.6.0", | |
"date": "2015-03-20" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.0.0", | |
"date": "2015-05-04" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.1.0", | |
"date": "2015-05-24" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.2.0", | |
"date": "2015-06-01" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.3.0", | |
"date": "2015-06-13" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.4.0", | |
"date": "2015-07-17" | |
}, | |
{ | |
"name": "iojs", | |
"version": "2.5.0", | |
"date": "2015-07-28" | |
}, | |
{ | |
"name": "iojs", | |
"version": "3.0.0", | |
"date": "2015-08-04" | |
}, | |
{ | |
"name": "iojs", | |
"version": "3.1.0", | |
"date": "2015-08-19" | |
}, | |
{ | |
"name": "iojs", | |
"version": "3.2.0", | |
"date": "2015-08-25" | |
}, | |
{ | |
"name": "iojs", | |
"version": "3.3.0", | |
"date": "2015-09-02" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.0.0", | |
"date": "2015-09-08", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.1.0", | |
"date": "2015-09-17", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.2.0", | |
"date": "2015-10-12", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.3.0", | |
"date": "2016-02-09", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.4.0", | |
"date": "2016-03-08", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.5.0", | |
"date": "2016-08-16", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.6.0", | |
"date": "2016-09-27", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.7.0", | |
"date": "2016-12-06", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.8.0", | |
"date": "2017-02-21", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "4.9.0", | |
"date": "2018-03-28", | |
"lts": "Argon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.0.0", | |
"date": "2015-10-29", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.1.0", | |
"date": "2015-11-17", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.2.0", | |
"date": "2015-12-09", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.3.0", | |
"date": "2015-12-15", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.4.0", | |
"date": "2016-01-06", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.5.0", | |
"date": "2016-01-21", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.6.0", | |
"date": "2016-02-09", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.7.0", | |
"date": "2016-02-23", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.8.0", | |
"date": "2016-03-09", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.9.0", | |
"date": "2016-03-16", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.10.0", | |
"date": "2016-04-01", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.11.0", | |
"date": "2016-04-21", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "5.12.0", | |
"date": "2016-06-23", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.0.0", | |
"date": "2016-04-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.1.0", | |
"date": "2016-05-05", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.2.0", | |
"date": "2016-05-17", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.3.0", | |
"date": "2016-07-06", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.4.0", | |
"date": "2016-08-12", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.5.0", | |
"date": "2016-08-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.6.0", | |
"date": "2016-09-14", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.7.0", | |
"date": "2016-09-27", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.8.0", | |
"date": "2016-10-12", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.9.0", | |
"date": "2016-10-18", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.10.0", | |
"date": "2017-02-21", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.11.0", | |
"date": "2017-06-06", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.12.0", | |
"date": "2017-11-06", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.13.0", | |
"date": "2018-02-10", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "6.14.0", | |
"date": "2018-03-28", | |
"lts": "Boron" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.0.0", | |
"date": "2016-10-25", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.1.0", | |
"date": "2016-11-08", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.2.0", | |
"date": "2016-11-22", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.3.0", | |
"date": "2016-12-20", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.4.0", | |
"date": "2017-01-04", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.5.0", | |
"date": "2017-01-31", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.6.0", | |
"date": "2017-02-21", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.7.0", | |
"date": "2017-02-28", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.8.0", | |
"date": "2017-03-29", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.9.0", | |
"date": "2017-04-11", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "7.10.0", | |
"date": "2017-05-02", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.0.0", | |
"date": "2017-05-30", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.1.0", | |
"date": "2017-06-08", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.2.0", | |
"date": "2017-07-19", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.3.0", | |
"date": "2017-08-08", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.4.0", | |
"date": "2017-08-15", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.5.0", | |
"date": "2017-09-12", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.6.0", | |
"date": "2017-09-26", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.7.0", | |
"date": "2017-10-11", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.8.0", | |
"date": "2017-10-24", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.9.0", | |
"date": "2017-10-31", | |
"lts": "Carbon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.10.0", | |
"date": "2018-03-06", | |
"lts": "Carbon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "8.11.0", | |
"date": "2018-03-28", | |
"lts": "Carbon" | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.0.0", | |
"date": "2017-10-31", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.1.0", | |
"date": "2017-11-07", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.2.0", | |
"date": "2017-11-14", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.3.0", | |
"date": "2017-12-12", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.4.0", | |
"date": "2018-01-10", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.5.0", | |
"date": "2018-01-31", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.6.0", | |
"date": "2018-02-21", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.7.0", | |
"date": "2018-03-01", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.8.0", | |
"date": "2018-03-07", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.9.0", | |
"date": "2018-03-21", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.10.0", | |
"date": "2018-03-28", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "9.11.0", | |
"date": "2018-04-04", | |
"lts": false | |
}, | |
{ | |
"name": "nodejs", | |
"version": "10.0.0", | |
"date": "2018-04-24", | |
"lts": false | |
} | |
] | |
},{}],219:[function(require,module,exports){ | |
module.exports={ | |
"v0.10": { | |
"start": "2013-03-11", | |
"end": "2016-10-31" | |
}, | |
"v0.12": { | |
"start": "2015-02-06", | |
"end": "2016-12-31" | |
}, | |
"v4": { | |
"start": "2015-09-08", | |
"lts": "2015-10-12", | |
"maintenance": "2017-04-01", | |
"end": "2018-04-30", | |
"codename": "Argon" | |
}, | |
"v5": { | |
"start": "2015-10-29", | |
"maintenance": "2016-04-30", | |
"end": "2016-06-30" | |
}, | |
"v6": { | |
"start": "2016-04-26", | |
"lts": "2016-10-18", | |
"maintenance": "2018-04-30", | |
"end": "2019-04-01", | |
"codename": "Boron" | |
}, | |
"v7": { | |
"start": "2016-10-25", | |
"maintenance": "2017-04-30", | |
"end": "2017-06-30" | |
}, | |
"v8": { | |
"start": "2017-05-30", | |
"lts": "2017-10-31", | |
"maintenance": "2019-04-01", | |
"end": "2019-12-31", | |
"codename": "Carbon" | |
}, | |
"v9": { | |
"start": "2017-10-01", | |
"maintenance": "2018-04-01", | |
"end": "2018-06-30" | |
}, | |
"v10": { | |
"start": "2018-04-30", | |
"lts": "2018-10-01", | |
"maintenance": "2020-04-01", | |
"end": "2021-04-01", | |
"codename": "" | |
} | |
} | |
},{}],220:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _postcss = require('postcss'); | |
var _postcss2 = _interopRequireDefault(_postcss); | |
var _decl = require('./lib/decl'); | |
var _decl2 = _interopRequireDefault(_decl); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = _postcss2.default.plugin('postcss-merge-longhand', () => { | |
return css => { | |
css.walkRules(rule => { | |
_decl2.default.forEach(p => { | |
p.explode(rule); | |
p.merge(rule); | |
}); | |
}); | |
}; | |
}); | |
module.exports = exports['default']; | |
},{"./lib/decl":226,"postcss":254}],221:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _isCustomProp = require('./isCustomProp'); | |
var _isCustomProp2 = _interopRequireDefault(_isCustomProp); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
const isInherit = node => ~node.value.indexOf('inherit'); | |
const isInitial = node => ~node.value.indexOf('initial'); | |
exports.default = prop => !isInherit(prop) && !isInitial(prop) && !(0, _isCustomProp2.default)(prop); | |
module.exports = exports['default']; | |
},{"./isCustomProp":235}],222:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _isCustomProp = require('./isCustomProp'); | |
var _isCustomProp2 = _interopRequireDefault(_isCustomProp); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
const important = node => node.important; | |
const unimportant = node => !node.important; | |
const hasInherit = node => ~node.value.indexOf('inherit'); | |
const hasInitial = node => ~node.value.indexOf('initial'); | |
exports.default = (...props) => { | |
if (props.some(hasInherit) || props.some(hasInitial) || props.some(_isCustomProp2.default)) { | |
return props.every(hasInherit) || props.every(hasInitial) || props.every(_isCustomProp2.default); | |
} | |
return props.every(unimportant) || props.every(important); | |
}; | |
module.exports = exports['default']; | |
},{"./isCustomProp":235}],223:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _postcss = require('postcss'); | |
var _stylehacks = require('stylehacks'); | |
var _insertCloned = require('../insertCloned'); | |
var _insertCloned2 = _interopRequireDefault(_insertCloned); | |
var _parseTrbl = require('../parseTrbl'); | |
var _parseTrbl2 = _interopRequireDefault(_parseTrbl); | |
var _hasAllProps = require('../hasAllProps'); | |
var _hasAllProps2 = _interopRequireDefault(_hasAllProps); | |
var _getDecls = require('../getDecls'); | |
var _getDecls2 = _interopRequireDefault(_getDecls); | |
var _getRules = require('../getRules'); | |
var _getRules2 = _interopRequireDefault(_getRules); | |
var _getValue = require('../getValue'); | |
var _getValue2 = _interopRequireDefault(_getValue); | |
var _mergeRules = require('../mergeRules'); | |
var _mergeRules2 = _interopRequireDefault(_mergeRules); | |
var _minifyTrbl = require('../minifyTrbl'); | |
var _minifyTrbl2 = _interopRequireDefault(_minifyTrbl); | |
var _canMerge = require('../canMerge'); | |
var _canMerge2 = _interopRequireDefault(_canMerge); | |
var _remove = require('../remove'); | |
var _remove2 = _interopRequireDefault(_remove); | |
var _trbl = require('../trbl'); | |
var _trbl2 = _interopRequireDefault(_trbl); | |
var _isCustomProp = require('../isCustomProp'); | |
var _isCustomProp2 = _interopRequireDefault(_isCustomProp); | |
var _canExplode = require('../canExplode'); | |
var _canExplode2 = _interopRequireDefault(_canExplode); | |
var _getLastNode = require('../getLastNode'); | |
var _getLastNode2 = _interopRequireDefault(_getLastNode); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
const wsc = ['width', 'style', 'color']; | |
const defaults = ['medium', 'none', 'currentColor']; | |
function borderProperty(...parts) { | |
return `border-${parts.join('-')}`; | |
} | |
function mapBorderProperty(value) { | |
return borderProperty(value); | |
} | |
const directions = _trbl2.default.map(mapBorderProperty); | |
const properties = wsc.map(mapBorderProperty); | |
const directionalProperties = directions.reduce((prev, curr) => prev.concat(wsc.map(prop => `${curr}-${prop}`)), []); | |
const precedence = [['border'], directions.concat(properties), directionalProperties]; | |
const allProperties = precedence.reduce((a, b) => a.concat(b)); | |
function getLevel(prop) { | |
for (let i = 0; i < precedence.length; i++) { | |
if (!!~precedence[i].indexOf(prop)) { | |
return i; | |
} | |
} | |
} | |
const widths = ['thin', 'medium', 'thick']; | |
const styles = ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset']; | |
function isStyle(value) { | |
return !!~styles.indexOf(value); | |
} | |
function isWidth(value) { | |
return !!~widths.indexOf(value) || /^(\d+(\.\d+)?|\.\d+)(\w+)?$/.test(value); | |
} | |
function parseWsc(value) { | |
if (value === 'none' || value === 'none none' || value === 'none none currentColor') { | |
return ['none', 'none', 'currentColor']; | |
} | |
let [width, style, color] = defaults; | |
const values = _postcss.list.space(value); | |
if (values.length > 1 && isStyle(values[1]) && values[0] === 'none') { | |
values.unshift(); | |
width = 'none'; | |
} | |
values.forEach(v => { | |
if (isStyle(v)) { | |
style = v; | |
} else if (isWidth(v)) { | |
width = v; | |
} else { | |
color = v; | |
} | |
}); | |
return [width, style, color]; | |
} | |
function getColorValue(decl) { | |
if (decl.prop.substr(-5) === 'color') { | |
return decl.value; | |
} | |
return parseWsc(decl.value)[2]; | |
} | |
function diffingProps(values, nextValues) { | |
const diff = wsc.reduce((prev, curr, i) => { | |
if (values[i] === nextValues[i]) { | |
return prev; | |
} | |
return [...prev, curr]; | |
}, []); | |
return diff; | |
} | |
function mergeRedundant({ values, nextValues, decl, nextDecl, index }) { | |
if ((0, _stylehacks.detect)(decl) || (0, _stylehacks.detect)(nextDecl)) { | |
return; | |
} | |
const diff = diffingProps(values, nextValues); | |
if (diff.length > 1) { | |
return; | |
} | |
const prop = diff.pop(); | |
const position = wsc.indexOf(prop); | |
const prop1 = `${nextDecl.prop}-${prop}`; | |
const prop2 = `border-${prop}`; | |
let props = (0, _parseTrbl2.default)(values[position]); | |
props[index] = nextValues[position]; | |
const borderValue2 = values.filter((e, i) => i !== position).join(' '); | |
const propValue2 = (0, _minifyTrbl2.default)(props); | |
const origLength = (decl.value + nextDecl.prop + nextDecl.value).length; | |
const newLength1 = decl.value.length + prop1.length + nextValues[position].length; | |
const newLength2 = borderValue2.length + prop2.length + propValue2.length; | |
if (newLength1 < newLength2 && newLength1 < origLength) { | |
nextDecl.prop = prop1; | |
nextDecl.value = nextValues[position]; | |
} | |
if (newLength2 < newLength1 && newLength2 < origLength) { | |
decl.value = borderValue2; | |
nextDecl.prop = prop2; | |
nextDecl.value = propValue2; | |
} | |
} | |
function isCloseEnough(mapped) { | |
return mapped[0] === mapped[1] && mapped[1] === mapped[2] || mapped[1] === mapped[2] && mapped[2] === mapped[3] || mapped[2] === mapped[3] && mapped[3] === mapped[0] || mapped[3] === mapped[0] && mapped[0] === mapped[1]; | |
} | |
function getDistinctShorthands(mapped) { | |
return mapped.reduce((a, b) => { | |
a = Array.isArray(a) ? a : [a]; | |
if (!~a.indexOf(b)) { | |
a.push(b); | |
} | |
return a; | |
}); | |
} | |
function explode(rule) { | |
rule.walkDecls(/^border/, decl => { | |
if (!(0, _canExplode2.default)(decl)) { | |
return; | |
} | |
if ((0, _stylehacks.detect)(decl)) { | |
return; | |
} | |
const { prop } = decl; | |
// border -> border-trbl | |
if (prop === 'border') { | |
directions.forEach(direction => { | |
(0, _insertCloned2.default)(decl.parent, decl, { prop: direction }); | |
}); | |
return decl.remove(); | |
} | |
// border-trbl -> border-trbl-wsc | |
if (directions.some(direction => prop === direction)) { | |
let values = parseWsc(decl.value); | |
wsc.forEach((d, i) => { | |
(0, _insertCloned2.default)(decl.parent, decl, { | |
prop: `${prop}-${d}`, | |
value: values[i] | |
}); | |
}); | |
return decl.remove(); | |
} | |
// border-wsc -> border-trbl-wsc | |
wsc.some(style => { | |
if (prop !== borderProperty(style)) { | |
return false; | |
} | |
(0, _parseTrbl2.default)(decl.value).forEach((value, i) => { | |
(0, _insertCloned2.default)(decl.parent, decl, { | |
prop: borderProperty(_trbl2.default[i], style), | |
value | |
}); | |
}); | |
return decl.remove(); | |
}); | |
}); | |
} | |
function merge(rule) { | |
// border-trbl-wsc -> border-trbl | |
_trbl2.default.forEach(direction => { | |
const prop = borderProperty(direction); | |
(0, _mergeRules2.default)(rule, wsc.map(style => borderProperty(direction, style)), (rules, lastNode) => { | |
if ((0, _canMerge2.default)(...rules) && !rules.some(_stylehacks.detect)) { | |
(0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop, | |
value: rules.map(_getValue2.default).join(' ') | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
} | |
}); | |
}); | |
// border-trbl-wsc -> border-wsc | |
wsc.forEach(style => { | |
const prop = borderProperty(style); | |
(0, _mergeRules2.default)(rule, _trbl2.default.map(direction => borderProperty(direction, style)), (rules, lastNode) => { | |
if ((0, _canMerge2.default)(...rules) && !rules.some(_stylehacks.detect)) { | |
(0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop, | |
value: (0, _minifyTrbl2.default)(rules.map(_getValue2.default).join(' ')) | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
} | |
}); | |
}); | |
// border-trbl -> border-wsc | |
(0, _mergeRules2.default)(rule, directions, (rules, lastNode) => { | |
if (rules.some(_stylehacks.detect)) { | |
return; | |
} | |
wsc.forEach((d, i) => { | |
(0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop: borderProperty(d), | |
value: (0, _minifyTrbl2.default)(rules.map(node => _postcss.list.space(node.value)[i])) | |
}); | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
}); | |
// border-wsc -> border | |
// border-wsc -> border + border-color | |
// border-wsc -> border + border-dir | |
(0, _mergeRules2.default)(rule, properties, (rules, lastNode) => { | |
if (rules.some(_stylehacks.detect)) { | |
return; | |
} | |
const [width, style, color] = rules; | |
const values = rules.map(node => (0, _parseTrbl2.default)(node.value)); | |
const mapped = [0, 1, 2, 3].map(i => [values[0][i], values[1][i], values[2][i]].join(' ')); | |
const reduced = getDistinctShorthands(mapped); | |
if (isCloseEnough(mapped) && (0, _canMerge2.default)(...rules)) { | |
const first = mapped.indexOf(reduced[0]) !== mapped.lastIndexOf(reduced[0]); | |
const border = (0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop: 'border', | |
value: first ? reduced[0] : reduced[1] | |
}); | |
if (reduced[1]) { | |
const value = first ? reduced[1] : reduced[0]; | |
const prop = borderProperty(_trbl2.default[mapped.indexOf(value)]); | |
rule.insertAfter(border, Object.assign(lastNode.clone(), { | |
prop, | |
value | |
})); | |
} | |
rules.forEach(_remove2.default); | |
return true; | |
} else if (reduced.length === 1) { | |
rule.insertBefore(color, Object.assign(lastNode.clone(), { | |
prop: 'border', | |
value: [width, style].map(_getValue2.default).join(' ') | |
})); | |
rules.filter(node => node.prop !== properties[2]).forEach(_remove2.default); | |
return true; | |
} | |
}); | |
// border-wsc -> border + border-trbl | |
(0, _mergeRules2.default)(rule, properties, (rules, lastNode) => { | |
if (rules.some(_stylehacks.detect)) { | |
return; | |
} | |
const values = rules.map(node => (0, _parseTrbl2.default)(node.value)); | |
const mapped = [0, 1, 2, 3].map(i => [values[0][i], values[1][i], values[2][i]].join(' ')); | |
const reduced = getDistinctShorthands(mapped); | |
const none = 'none none currentColor'; | |
if (reduced.length === 2 && reduced[0] === none || reduced[1] === none) { | |
rule.insertBefore(lastNode, Object.assign(lastNode.clone(), { | |
prop: 'border', | |
value: mapped[1] === none ? 'none' : mapped.filter(value => value !== none)[0] | |
})); | |
directions.forEach((dir, i) => { | |
if (mapped[1] === none && mapped[i] !== none) { | |
rule.insertBefore(lastNode, Object.assign(lastNode.clone(), { | |
prop: dir, | |
value: mapped[i] | |
})); | |
} | |
if (mapped[1] !== none && mapped[i] === none) { | |
rule.insertBefore(lastNode, Object.assign(lastNode.clone(), { | |
prop: dir, | |
value: 'none' | |
})); | |
} | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
} | |
}); | |
// optimize border-trbl | |
let decls = (0, _getDecls2.default)(rule, directions); | |
while (decls.length) { | |
const lastNode = decls[decls.length - 1]; | |
wsc.forEach((d, i) => { | |
const names = directions.filter(name => name !== lastNode.prop).map(name => `${name}-${d}`); | |
let nodes = rule.nodes.slice(0, rule.nodes.indexOf(lastNode)); | |
const border = (0, _getLastNode2.default)(nodes, 'border'); | |
if (border) { | |
nodes = nodes.slice(nodes.indexOf(border)); | |
} | |
const props = nodes.filter(node => node.prop && ~names.indexOf(node.prop) && node.important === lastNode.important); | |
const rules = (0, _getRules2.default)(props, names); | |
if ((0, _hasAllProps2.default)(rules, ...names) && !rules.some(_stylehacks.detect)) { | |
const values = rules.map(node => node ? node.value : null); | |
const filteredValues = values.filter(Boolean); | |
const lastNodeValue = _postcss.list.space(lastNode.value)[i]; | |
values[directions.indexOf(lastNode.prop)] = lastNodeValue; | |
let value = (0, _minifyTrbl2.default)(values.join(' ')); | |
if (filteredValues[0] === filteredValues[1] && filteredValues[1] === filteredValues[2]) { | |
value = filteredValues[0]; | |
} | |
let refNode = props[props.length - 1]; | |
if (value === lastNodeValue) { | |
refNode = lastNode; | |
let valueArray = _postcss.list.space(lastNode.value); | |
valueArray.splice(i, 1); | |
lastNode.value = valueArray.join(' '); | |
} | |
(0, _insertCloned2.default)(refNode.parent, refNode, { | |
prop: borderProperty(d), | |
value | |
}); | |
decls = decls.filter(node => !~rules.indexOf(node)); | |
rules.forEach(_remove2.default); | |
} | |
}); | |
decls = decls.filter(node => node !== lastNode); | |
} | |
rule.walkDecls('border', decl => { | |
const nextDecl = decl.next(); | |
if (!nextDecl || nextDecl.type !== 'decl') { | |
return; | |
} | |
const index = directions.indexOf(nextDecl.prop); | |
if (!~index) { | |
return; | |
} | |
const values = parseWsc(decl.value); | |
const nextValues = parseWsc(nextDecl.value); | |
const config = { | |
values, | |
nextValues, | |
decl, | |
nextDecl, | |
index | |
}; | |
return mergeRedundant(config); | |
}); | |
// clean-up values | |
rule.walkDecls(/^border($|-(top|right|bottom|left))/, decl => { | |
const value = [...parseWsc(decl.value), ''].reduceRight((prev, cur, i, arr) => { | |
if (cur === defaults[i] && arr[i - 1] !== cur) { | |
return prev; | |
} | |
return cur + ' ' + prev; | |
}).trim() || defaults[0]; | |
decl.value = (0, _minifyTrbl2.default)(value || defaults[0]); | |
}); | |
// border-spacing-hv -> border-spacing | |
rule.walkDecls('border-spacing', decl => { | |
const value = _postcss.list.space(decl.value); | |
// merge vertical and horizontal dups | |
if (value.length > 1 && value[0] === value[1]) { | |
decl.value = value.slice(1).join(' '); | |
} | |
}); | |
// clean-up rules | |
decls = (0, _getDecls2.default)(rule, allProperties); | |
while (decls.length) { | |
const lastNode = decls[decls.length - 1]; | |
const lastPart = lastNode.prop.split('-').pop(); | |
// remove properties of lower precedence | |
const lesser = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && getLevel(node.prop) > getLevel(lastNode.prop) && (!!~node.prop.indexOf(lastNode.prop) || node.prop.endsWith(lastPart))); | |
lesser.forEach(_remove2.default); | |
decls = decls.filter(node => !~lesser.indexOf(node)); | |
// get duplicate properties | |
let duplicates = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && node.prop === lastNode.prop && !(!(0, _isCustomProp2.default)(node) && (0, _isCustomProp2.default)(lastNode))); | |
if (duplicates.length) { | |
if (/hsla|rgba/.test(getColorValue(lastNode))) { | |
const preserve = duplicates.filter(node => !/hsla|rgba/.test(getColorValue(node))).pop(); | |
duplicates = duplicates.filter(node => node !== preserve); | |
} | |
duplicates.forEach(_remove2.default); | |
} | |
decls = decls.filter(node => node !== lastNode && !~duplicates.indexOf(node)); | |
} | |
} | |
exports.default = { | |
explode, | |
merge | |
}; | |
module.exports = exports['default']; | |
},{"../canExplode":221,"../canMerge":222,"../getDecls":229,"../getLastNode":230,"../getRules":231,"../getValue":232,"../hasAllProps":233,"../insertCloned":234,"../isCustomProp":235,"../mergeRules":236,"../minifyTrbl":238,"../parseTrbl":239,"../remove":240,"../trbl":241,"postcss":254,"stylehacks":347}],224:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _stylehacks = require('stylehacks'); | |
var _canMerge = require('../canMerge'); | |
var _canMerge2 = _interopRequireDefault(_canMerge); | |
var _getDecls = require('../getDecls'); | |
var _getDecls2 = _interopRequireDefault(_getDecls); | |
var _minifyTrbl = require('../minifyTrbl'); | |
var _minifyTrbl2 = _interopRequireDefault(_minifyTrbl); | |
var _parseTrbl = require('../parseTrbl'); | |
var _parseTrbl2 = _interopRequireDefault(_parseTrbl); | |
var _insertCloned = require('../insertCloned'); | |
var _insertCloned2 = _interopRequireDefault(_insertCloned); | |
var _mergeRules = require('../mergeRules'); | |
var _mergeRules2 = _interopRequireDefault(_mergeRules); | |
var _mergeValues = require('../mergeValues'); | |
var _mergeValues2 = _interopRequireDefault(_mergeValues); | |
var _remove = require('../remove'); | |
var _remove2 = _interopRequireDefault(_remove); | |
var _trbl = require('../trbl'); | |
var _trbl2 = _interopRequireDefault(_trbl); | |
var _isCustomProp = require('../isCustomProp'); | |
var _isCustomProp2 = _interopRequireDefault(_isCustomProp); | |
var _canExplode = require('../canExplode'); | |
var _canExplode2 = _interopRequireDefault(_canExplode); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = prop => { | |
const properties = _trbl2.default.map(direction => `${prop}-${direction}`); | |
const cleanup = rule => { | |
let decls = (0, _getDecls2.default)(rule, [prop].concat(properties)); | |
while (decls.length) { | |
const lastNode = decls[decls.length - 1]; | |
// remove properties of lower precedence | |
const lesser = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && lastNode.prop === prop && node.prop !== lastNode.prop); | |
lesser.forEach(_remove2.default); | |
decls = decls.filter(node => !~lesser.indexOf(node)); | |
// get duplicate properties | |
let duplicates = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && node.prop === lastNode.prop && !(!(0, _isCustomProp2.default)(node) && (0, _isCustomProp2.default)(lastNode))); | |
duplicates.forEach(_remove2.default); | |
decls = decls.filter(node => node !== lastNode && !~duplicates.indexOf(node)); | |
} | |
}; | |
const processor = { | |
explode: rule => { | |
rule.walkDecls(prop, decl => { | |
if (!(0, _canExplode2.default)(decl)) { | |
return; | |
} | |
if ((0, _stylehacks.detect)(decl)) { | |
return; | |
} | |
const values = (0, _parseTrbl2.default)(decl.value); | |
_trbl2.default.forEach((direction, index) => { | |
(0, _insertCloned2.default)(decl.parent, decl, { | |
prop: properties[index], | |
value: values[index] | |
}); | |
}); | |
decl.remove(); | |
}); | |
}, | |
merge: rule => { | |
(0, _mergeRules2.default)(rule, properties, (rules, lastNode) => { | |
if ((0, _canMerge2.default)(...rules) && !rules.some(_stylehacks.detect)) { | |
(0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop, | |
value: (0, _minifyTrbl2.default)((0, _mergeValues2.default)(...rules)) | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
} | |
}); | |
cleanup(rule); | |
} | |
}; | |
return processor; | |
}; | |
module.exports = exports['default']; | |
},{"../canExplode":221,"../canMerge":222,"../getDecls":229,"../insertCloned":234,"../isCustomProp":235,"../mergeRules":236,"../mergeValues":237,"../minifyTrbl":238,"../parseTrbl":239,"../remove":240,"../trbl":241,"stylehacks":347}],225:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _postcss = require('postcss'); | |
var _postcssValueParser = require('postcss-value-parser'); | |
var _stylehacks = require('stylehacks'); | |
var _canMerge = require('../canMerge'); | |
var _canMerge2 = _interopRequireDefault(_canMerge); | |
var _getDecls = require('../getDecls'); | |
var _getDecls2 = _interopRequireDefault(_getDecls); | |
var _getValue = require('../getValue'); | |
var _getValue2 = _interopRequireDefault(_getValue); | |
var _mergeRules = require('../mergeRules'); | |
var _mergeRules2 = _interopRequireDefault(_mergeRules); | |
var _insertCloned = require('../insertCloned'); | |
var _insertCloned2 = _interopRequireDefault(_insertCloned); | |
var _remove = require('../remove'); | |
var _remove2 = _interopRequireDefault(_remove); | |
var _isCustomProp = require('../isCustomProp'); | |
var _isCustomProp2 = _interopRequireDefault(_isCustomProp); | |
var _canExplode = require('../canExplode'); | |
var _canExplode2 = _interopRequireDefault(_canExplode); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
const properties = ['column-width', 'column-count']; | |
const auto = 'auto'; | |
const inherit = 'inherit'; | |
/** | |
* Normalize a columns shorthand definition. Both of the longhand | |
* properties' initial values are 'auto', and as per the spec, | |
* omitted values are set to their initial values. Thus, we can | |
* remove any 'auto' definition when there are two values. | |
* | |
* Specification link: https://www.w3.org/TR/css3-multicol/ | |
*/ | |
function normalize(values) { | |
if (values[0] === auto) { | |
return values[1]; | |
} | |
if (values[1] === auto) { | |
return values[0]; | |
} | |
if (values[0] === inherit && values[1] === inherit) { | |
return inherit; | |
} | |
return values.join(' '); | |
} | |
function explode(rule) { | |
rule.walkDecls('columns', decl => { | |
if (!(0, _canExplode2.default)(decl)) { | |
return; | |
} | |
if ((0, _stylehacks.detect)(decl)) { | |
return; | |
} | |
let values = _postcss.list.space(decl.value); | |
if (values.length === 1) { | |
values.push(auto); | |
} | |
values.forEach((value, i) => { | |
let prop = properties[1]; | |
if (value === auto) { | |
prop = properties[i]; | |
} else if ((0, _postcssValueParser.unit)(value).unit) { | |
prop = properties[0]; | |
} | |
(0, _insertCloned2.default)(decl.parent, decl, { | |
prop, | |
value | |
}); | |
}); | |
decl.remove(); | |
}); | |
} | |
function cleanup(rule) { | |
let decls = (0, _getDecls2.default)(rule, ['columns'].concat(properties)); | |
while (decls.length) { | |
const lastNode = decls[decls.length - 1]; | |
// remove properties of lower precedence | |
const lesser = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && lastNode.prop === 'columns' && node.prop !== lastNode.prop); | |
lesser.forEach(_remove2.default); | |
decls = decls.filter(node => !~lesser.indexOf(node)); | |
// get duplicate properties | |
let duplicates = decls.filter(node => !(0, _stylehacks.detect)(lastNode) && !(0, _stylehacks.detect)(node) && node !== lastNode && node.important === lastNode.important && node.prop === lastNode.prop && !(!(0, _isCustomProp2.default)(node) && (0, _isCustomProp2.default)(lastNode))); | |
duplicates.forEach(_remove2.default); | |
decls = decls.filter(node => node !== lastNode && !~duplicates.indexOf(node)); | |
} | |
} | |
function merge(rule) { | |
(0, _mergeRules2.default)(rule, properties, (rules, lastNode) => { | |
if ((0, _canMerge2.default)(...rules) && !rules.some(_stylehacks.detect)) { | |
(0, _insertCloned2.default)(lastNode.parent, lastNode, { | |
prop: 'columns', | |
value: normalize(rules.map(_getValue2.default)) | |
}); | |
rules.forEach(_remove2.default); | |
return true; | |
} | |
}); | |
cleanup(rule); | |
} | |
exports.default = { | |
explode, | |
merge | |
}; | |
module.exports = exports['default']; | |
},{"../canExplode":221,"../canMerge":222,"../getDecls":229,"../getValue":232,"../insertCloned":234,"../isCustomProp":235,"../mergeRules":236,"../remove":240,"postcss":254,"postcss-value-parser":292,"stylehacks":347}],226:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _borders = require('./borders'); | |
var _borders2 = _interopRequireDefault(_borders); | |
var _columns = require('./columns'); | |
var _columns2 = _interopRequireDefault(_columns); | |
var _margin = require('./margin'); | |
var _margin2 = _interopRequireDefault(_margin); | |
var _padding = require('./padding'); | |
var _padding2 = _interopRequireDefault(_padding); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = [_borders2.default, _columns2.default, _margin2.default, _padding2.default]; | |
module.exports = exports['default']; | |
},{"./borders":223,"./columns":225,"./margin":227,"./padding":228}],227:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _boxBase = require('./boxBase'); | |
var _boxBase2 = _interopRequireDefault(_boxBase); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = (0, _boxBase2.default)('margin'); | |
module.exports = exports['default']; | |
},{"./boxBase":224}],228:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _boxBase = require('./boxBase'); | |
var _boxBase2 = _interopRequireDefault(_boxBase); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = (0, _boxBase2.default)('padding'); | |
module.exports = exports['default']; | |
},{"./boxBase":224}],229:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = getDecls; | |
function getDecls(rule, properties) { | |
return rule.nodes.filter(({ prop }) => prop && ~properties.indexOf(prop)); | |
} | |
module.exports = exports["default"]; | |
},{}],230:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = (rule, prop) => { | |
return rule.filter(n => n.prop && n.prop === prop).pop(); | |
}; | |
module.exports = exports["default"]; | |
},{}],231:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = getRules; | |
var _getLastNode = require('./getLastNode'); | |
var _getLastNode2 = _interopRequireDefault(_getLastNode); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function getRules(props, properties) { | |
return properties.map(property => { | |
return (0, _getLastNode2.default)(props, property); | |
}).filter(Boolean); | |
} | |
module.exports = exports['default']; | |
},{"./getLastNode":230}],232:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = getValue; | |
function getValue({ value }) { | |
return value; | |
} | |
module.exports = exports["default"]; | |
},{}],233:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = (rule, ...props) => { | |
return props.every(p => rule.some(({ prop }) => prop && ~prop.indexOf(p))); | |
}; | |
module.exports = exports["default"]; | |
},{}],234:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = insertCloned; | |
function insertCloned(rule, decl, props) { | |
const newNode = Object.assign(decl.clone(), props); | |
rule.insertAfter(decl, newNode); | |
return newNode; | |
}; | |
module.exports = exports["default"]; | |
},{}],235:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = node => ~node.value.search(/var\s*\(\s*--/i); | |
module.exports = exports["default"]; | |
},{}],236:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = mergeRules; | |
var _hasAllProps = require('./hasAllProps'); | |
var _hasAllProps2 = _interopRequireDefault(_hasAllProps); | |
var _getDecls = require('./getDecls'); | |
var _getDecls2 = _interopRequireDefault(_getDecls); | |
var _getRules = require('./getRules'); | |
var _getRules2 = _interopRequireDefault(_getRules); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function mergeRules(rule, properties, callback) { | |
let decls = (0, _getDecls2.default)(rule, properties); | |
while (decls.length) { | |
const last = decls[decls.length - 1]; | |
const props = decls.filter(node => node.important === last.important); | |
const rules = (0, _getRules2.default)(props, properties); | |
if ((0, _hasAllProps2.default)(rules, ...properties)) { | |
if (callback(rules, last, props)) { | |
decls = decls.filter(node => !~rules.indexOf(node)); | |
} | |
} | |
decls = decls.filter(node => node !== last); | |
} | |
} | |
module.exports = exports['default']; | |
},{"./getDecls":229,"./getRules":231,"./hasAllProps":233}],237:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _getValue = require('./getValue'); | |
var _getValue2 = _interopRequireDefault(_getValue); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = (...rules) => rules.map(_getValue2.default).join(' '); | |
module.exports = exports['default']; | |
},{"./getValue":232}],238:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _parseTrbl = require('./parseTrbl'); | |
var _parseTrbl2 = _interopRequireDefault(_parseTrbl); | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
exports.default = v => { | |
const value = (0, _parseTrbl2.default)(v); | |
if (value[3] === value[1]) { | |
value.pop(); | |
if (value[2] === value[0]) { | |
value.pop(); | |
if (value[0] === value[1]) { | |
value.pop(); | |
} | |
} | |
} | |
return value.join(' '); | |
}; | |
module.exports = exports['default']; | |
},{"./parseTrbl":239}],239:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _postcss = require('postcss'); | |
exports.default = v => { | |
const s = typeof v === 'string' ? _postcss.list.space(v) : v; | |
return [s[0], // top | |
s[1] || s[0], // right | |
s[2] || s[0], // bottom | |
s[3] || s[1] || s[0]]; | |
}; | |
module.exports = exports['default']; | |
},{"postcss":254}],240:[function(require,module,exports){ | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = remove; | |
function remove(node) { | |
return node.remove(); | |
} | |
module.exports = exports["default"]; | |
},{}],241:[function(require,module,exports){ | |
'use strict'; | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
exports.default = ['top', 'right', 'bottom', 'left']; | |
module.exports = exports['default']; | |
},{}],242:[function(require,module,exports){ | |
arguments[4][12][0].apply(exports,arguments) | |
},{"./container":244,"dup":12}],243:[function(require,module,exports){ | |
arguments[4][13][0].apply(exports,arguments) | |
},{"./node":251,"dup":13}],244:[function(require,module,exports){ | |
arguments[4][14][0].apply(exports,arguments) | |
},{"./at-rule":242,"./comment":243,"./declaration":246,"./node":251,"./parse":252,"./root":258,"./rule":259,"dup":14}],245:[function(require,module,exports){ | |
arguments[4][15][0].apply(exports,arguments) | |
},{"./terminal-highlight":262,"chalk":393,"dup":15,"supports-color":393}],246:[function(require,module,exports){ | |
arguments[4][16][0].apply(exports,arguments) | |
},{"./node":251,"dup":16}],247:[function(require,module,exports){ | |
arguments[4][17][0].apply(exports,arguments) | |
},{"./css-syntax-error":245,"./previous-map":255,"dup":17,"path":397}],248:[function(require,module,exports){ | |
arguments[4][18][0].apply(exports,arguments) | |
},{"./map-generator":250,"./parse":252,"./result":257,"./stringify":261,"./warn-once":265,"dup":18}],249:[function(require,module,exports){ | |
arguments[4][19][0].apply(exports,arguments) | |
},{"dup":19}],250:[function(require,module,exports){ | |
arguments[4][20][0].apply(exports,arguments) | |
},{"buffer":395,"dup":20,"path":397,"source-map":340}],251:[function(require,module,exports){ | |
arguments[4][21][0].apply(exports,arguments) | |
},{"./css-syntax-error":245,"./stringifier":260,"./stringify":261,"./warn-once":265,"dup":21}],252:[function(require,module,exports){ | |
arguments[4][22][0].apply(exports,arguments) | |
},{"./input":247,"./parser":253,"dup":22}],253:[function(require,module,exports){ | |
arguments[4][23][0].apply(exports,arguments) | |
},{"./at-rule":242,"./comment":243,"./declaration":246,"./root":258,"./rule":259,"./tokenize":263,"dup":23}],254:[function(require,module,exports){ | |
arguments[4][24][0].apply(exports,arguments) | |
},{"./at-rule":242,"./comment":243,"./declaration":246,"./list":249,"./parse":252,"./processor":256,"./root":258,"./rule":259,"./stringify":261,"./vendor":264,"dup":24}],255:[function(require,module,exports){ | |
arguments[4][25][0].apply(exports,arguments) | |
},{"buffer":395,"dup":25,"fs":393,"path":397,"source-map":340}],256:[function(require,module,exports){ | |
arguments[4][26][0].apply(exports,arguments) | |
},{"./lazy-result":248,"dup":26}],257:[function(require,module,exports){ | |
arguments[4][27][0].apply(exports,arguments) | |
},{"./warning":266,"dup":27}],258:[function(require,module,exports){ | |
arguments[4][28][0].apply(exports,arguments) | |
},{"./container":244,"./lazy-result":248,"./processor":256,"dup":28}],259:[function(require,module,exports){ | |
arguments[4][29][0].apply(exports,arguments) | |
},{"./container":244,"./list":249,"dup":29}],260:[function(require,module,exports){ | |
arguments[4][30][0].apply(exports,arguments) | |
},{"dup":30}],261:[function(require,module,exports){ | |
arguments[4][31][0].apply(exports,arguments) | |
},{"./stringifier":260,"dup":31}],262:[function(require,module,exports){ | |
arguments[4][32][0].apply(exports,arguments) | |
},{"./input":247,"./tokenize":263,"chalk":393,"dup":32}],263:[function(require,module,exports){ | |
arguments[4][33][0].apply(exports,arguments) | |
},{"dup":33}],264:[function(require,module,exports){ | |
arguments[4][34][0].apply(exports,arguments) | |
},{"dup":34}],265:[function(require,module,exports){ | |
arguments[4][35][0].apply(exports,arguments) | |
},{"dup":35}],266:[function(require,module,exports){ | |
arguments[4][36][0].apply(exports,arguments) | |
},{"dup":36}],267:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _processor = require('./processor'); | |
var _processor2 = _interopRequireDefault(_processor); | |
var _selectors = require('./selectors'); | |
var selectors = _interopRequireWildcard(_selectors); | |
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
var parser = function parser(processor) { | |
return new _processor2.default(processor); | |
}; | |
Object.assign(parser, selectors); | |
delete parser.__esModule; | |
exports.default = parser; | |
module.exports = exports['default']; | |
},{"./processor":269,"./selectors":278}],268:[function(require,module,exports){ | |
'use strict'; | |
exports.__esModule = true; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
var _dotProp = require('dot-prop'); | |
var _dotProp2 = _interopRequireDefault(_dotProp); | |
var _indexesOf = require('indexes-of'); | |
var _indexesOf2 = _interopRequireDefault(_indexesOf); | |
var _uniq = require('uniq'); | |
var _uniq2 = _interopRequireDefault(_uniq); | |
var _root = require('./selectors/root'); | |
var _root2 = _interopRequireDefault(_root); | |
var _selector = require('./selectors/selector'); | |
var _selector2 = _interopRequireDefault(_selector); | |
var _className = require('./selectors/className'); | |
var _className2 = _interopRequireDefault(_className); | |
var _comment = require('./selectors/comment'); | |
var _comment2 = _interopRequireDefault(_comment); | |
var _id = require('./selectors/id'); | |
var _id2 = _interopRequireDefault(_id); | |
var _tag = require('./selectors/tag'); | |
var _tag2 = _interopRequireDefault(_tag); | |
var _string = require('./selectors/string'); | |
var _string2 = _interopRequireDefault(_string); | |
var _pseudo = require('./selectors/pseudo'); | |
var _pseudo2 = _interopRequireDefault(_pseudo); | |
var _attribute = require('./selectors/attribute'); | |
var _attribute2 = _interopRequireDefault(_attribute); | |
var _universal = require('./selectors/universal'); | |
var _universal2 = _interopRequireDefault(_universal); | |
var _combinator = require('./selectors/combinator'); | |
var _combinator2 = _interopRequireDefault(_combinator); | |
var _nesting = require('./selectors/nesting'); | |
var _nesting2 = _interopRequireDefault(_nesting); | |
var _sortAscending = require('./sortAscending'); | |
var _sortAscending2 = _interopRequireDefault(_sortAscending); | |
var _tokenize = require('./tokenize'); | |
var _tokenize2 = _interopRequireDefault(_tokenize); | |
var _tokenTypes = require('./tokenTypes'); | |
var tokens = _interopRequireWildcard(_tokenTypes); | |
var _types = require('./selectors/types'); | |
var types = _interopRequireWildcard(_types); | |
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | |
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function getSource(startLine, startColumn, endLine, endColumn) { | |
return { | |
start: { | |
line: startLine, | |
column: startColumn | |
}, | |
end: { | |
line: endLine, | |
column: endColumn | |
} | |
}; | |
} | |
var Parser = function () { | |
function Parser(rule) { | |
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | |
_classCallCheck(this, Parser); | |
this.rule = rule; | |
this.options = Object.assign({ lossy: false, safe: false }, options); | |
this.position = 0; | |
this.root = new _root2.default(); | |
this.root.errorGenerator = this._errorGenerator(); | |
var selector = new _selector2.default(); | |
this.root.append(selector); | |
this.current = selector; | |
this.css = typeof this.rule === 'string' ? this.rule : this.rule.selector; | |
if (this.options.lossy) { | |
this.css = this.css.trim(); | |
} | |
this.tokens = (0, _tokenize2.default)({ | |
css: this.css, | |
error: this._errorGenerator(), | |
safe: this.options.safe | |
}); | |
this.loop(); | |
} | |
Parser.prototype._errorGenerator = function _errorGenerator() { | |
var _this = this; | |
return function (message, errorOptions) { | |
if (typeof _this.rule === 'string') { | |
return new Error(message); | |
} | |
return _this.rule.error(message, errorOptions); | |
}; | |
}; | |
Parser.prototype.attribute = function attribute() { | |
var attr = []; | |
var startingToken = this.currToken; | |
this.position++; | |
while (this.position < this.tokens.length && this.currToken[0] !== tokens.closeSquare) { | |
attr.push(this.currToken); | |
this.position++; | |
} | |
if (this.currToken[0] !== tokens.closeSquare) { | |
return this.expected('closing square bracket', this.currToken[5]); | |
} | |
var len = attr.length; | |
var node = { | |
source: getSource(startingToken[1], startingToken[2], this.currToken[3], this.currToken[4]), | |
sourceIndex: startingToken[5] | |
}; | |
if (len === 1 && !~[tokens.word].indexOf(attr[0][0])) { | |
return this.expected('attribute', attr[0][5]); | |
} | |
var pos = 0; | |
var spaceBefore = ''; | |
var commentBefore = ''; | |
var lastAdded = null; | |
var spaceAfterMeaningfulToken = false; | |
while (pos < len) { | |
var token = attr[pos]; | |
var content = this.content(token); | |
var next = attr[pos + 1]; | |
switch (token[0]) { | |
case tokens.space: | |
if (len === 1 || pos === 0 && this.content(next) === '|') { | |
return this.expected('attribute', token[5], content); | |
} | |
spaceAfterMeaningfulToken = true; | |
if (this.options.lossy) { | |
break; | |
} | |
if (lastAdded) { | |
var spaceProp = 'spaces.' + lastAdded + '.after'; | |
_dotProp2.default.set(node, spaceProp, _dotProp2.default.get(node, spaceProp, '') + content); | |
var commentProp = 'raws.spaces.' + lastAdded + '.after'; | |
var existingComment = _dotProp2.default.get(node, commentProp); | |
if (existingComment) { | |
_dotProp2.default.set(node, commentProp, existingComment + content); | |
} | |
} else { | |
spaceBefore = spaceBefore + content; | |
commentBefore = commentBefore + content; | |
} | |
break; | |
case tokens.asterisk: | |
if (next[0] === tokens.equals) { | |
node.operator = content; | |
lastAdded = 'operator'; | |
} else if ((!node.namespace || lastAdded === "namespace" && !spaceAfterMeaningfulToken) && next) { | |
if (spaceBefore) { | |
_dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore); | |
spaceBefore = ''; | |
} | |
if (commentBefore) { | |
_dotProp2.default.set(node, 'raws.spaces.attribute.before', spaceBefore); | |
commentBefore = ''; | |
} | |
node.namespace = (node.namespace || "") + content; | |
var rawValue = _dotProp2.default.get(node, "raws.namespace"); | |
if (rawValue) { | |
node.raws.namespace += content; | |
} | |
lastAdded = 'namespace'; | |
} | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.dollar: | |
case tokens.caret: | |
if (next[0] === tokens.equals) { | |
node.operator = content; | |
lastAdded = 'operator'; | |
} | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.combinator: | |
if (content === '~' && next[0] === tokens.equals) { | |
node.operator = content; | |
lastAdded = 'operator'; | |
} | |
if (content !== '|') { | |
spaceAfterMeaningfulToken = false; | |
break; | |
} | |
if (next[0] === tokens.equals) { | |
node.operator = content; | |
lastAdded = 'operator'; | |
} else if (!node.namespace && !node.attribute) { | |
node.namespace = true; | |
} | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.word: | |
if (next && this.content(next) === '|' && attr[pos + 2] && attr[pos + 2][0] !== tokens.equals && // this look-ahead probably fails with comment nodes involved. | |
!node.operator && !node.namespace) { | |
node.namespace = content; | |
lastAdded = 'namespace'; | |
} else if (!node.attribute || lastAdded === "attribute" && !spaceAfterMeaningfulToken) { | |
if (spaceBefore) { | |
_dotProp2.default.set(node, 'spaces.attribute.before', spaceBefore); | |
spaceBefore = ''; | |
} | |
if (commentBefore) { | |
_dotProp2.default.set(node, 'raws.spaces.attribute.before', commentBefore); | |
commentBefore = ''; | |
} | |
node.attribute = (node.attribute || "") + content; | |
var _rawValue = _dotProp2.default.get(node, "raws.attribute"); | |
if (_rawValue) { | |
node.raws.attribute += content; | |
} | |
lastAdded = 'attribute'; | |
} else if (!node.value || lastAdded === "value" && !spaceAfterMeaningfulToken) { | |
node.value = (node.value || "") + content; | |
var _rawValue2 = _dotProp2.default.get(node, "raws.value"); | |
if (_rawValue2) { | |
node.raws.value += content; | |
} | |
lastAdded = 'value'; | |
_dotProp2.default.set(node, 'raws.unquoted', _dotProp2.default.get(node, 'raws.unquoted', '') + content); | |
} else if (content === 'i') { | |
if (node.value && (node.quoted || spaceAfterMeaningfulToken)) { | |
node.insensitive = true; | |
lastAdded = 'insensitive'; | |
if (spaceBefore) { | |
_dotProp2.default.set(node, 'spaces.insensitive.before', spaceBefore); | |
spaceBefore = ''; | |
} | |
if (commentBefore) { | |
_dotProp2.default.set(node, 'raws.spaces.insensitive.before', commentBefore); | |
commentBefore = ''; | |
} | |
} else if (node.value) { | |
lastAdded = 'value'; | |
node.value += 'i'; | |
if (node.raws.value) { | |
node.raws.value += 'i'; | |
} | |
} | |
} | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.str: | |
if (!node.attribute || !node.operator) { | |
return this.error('Expected an attribute followed by an operator preceding the string.', { | |
index: token[5] | |
}); | |
} | |
node.value = content; | |
node.quoted = true; | |
lastAdded = 'value'; | |
_dotProp2.default.set(node, 'raws.unquoted', content.slice(1, -1)); | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.equals: | |
if (!node.attribute) { | |
return this.expected('attribute', token[5], content); | |
} | |
if (node.value) { | |
return this.error('Unexpected "=" found; an operator was already defined.', { index: token[5] }); | |
} | |
node.operator = node.operator ? node.operator + content : content; | |
lastAdded = 'operator'; | |
spaceAfterMeaningfulToken = false; | |
break; | |
case tokens.comment: | |
if (lastAdded) { | |
if (spaceAfterMeaningfulToken || next && next[0] === tokens.space) { | |
var lastComment = _dotProp2.default.get(node, 'raws.spaces.' + lastAdded + '.after', _dotProp2.default.get(node, 'spaces.' + lastAdded + '.after', '')); | |
_dotProp2.default.set(node, 'raws.spaces.' + lastAdded + '.after', lastComment + content); | |
} else { | |
var lastValue = _dotProp2.default.get(node, 'raws.' + lastAdded, _dotProp2.default.get(node, lastAdded, '')); | |
_dotProp2.default.set(node, 'raws.' + lastAdded, lastValue + content); | |
} | |
} else { | |
commentBefore = commentBefore + content; | |
} | |
break; | |
default: | |
return this.error('Unexpected "' + content + '" found.', { index: token[5] }); | |
} | |
pos++; | |
} | |
this.newNode(new _attribute2.default(node)); | |
this.position++; | |
}; | |
Parser.prototype.combinator = function combinator() { | |
var current = this.currToken; | |
if (this.content() === '|') { | |
return this.namespace(); | |
} | |
var node = new _combinator2.default({ | |
value: '', | |
source: getSource(current[1], current[2], current[3], current[4]), | |
sourceIndex: current[5] | |
}); | |
while (this.position < this.tokens.length && this.currToken && (this.currToken[0] === tokens.space || this.currToken[0] === tokens.combinator)) { | |
var content = this.content(); | |
if (this.nextToken && this.nextToken[0] === tokens.combinator) { | |
node.spaces.before = this.parseSpace(content); | |
node.source = getSource(this.nextToken[1], this.nextToken[2], this.nextToken[3], this.nextToken[4]); | |
node.sourceIndex = this.nextToken[5]; | |
} else if (this.prevToken && this.prevToken[0] === tokens.combinator) { | |
node.spaces.after = this.parseSpace(content); | |
} else if (this.currToken[0] === tokens.combinator) { | |
node.value = content; | |
} else if (this.currToken[0] === tokens.space) { | |
node.value = this.parseSpace(content, ' '); | |
} | |
this.position++; | |
} | |
return this.newNode(node); | |
}; | |
Parser.prototype.comma = function comma() { | |
if (this.position === this.tokens.length - 1) { | |
this.root.trailingComma = true; | |
this.position++; | |
return; | |
} | |
var selector = new _selector2.default(); | |
this.current.parent.append(selector); | |
this.current = selector; | |
this.position++; | |
}; | |
Parser.prototype.comment = function comment() { | |
var current = this.currToken; | |
this.newNode(new _comment2.default({ | |
value: this.content(), | |
source: getSource(current[1], current[2], current[3], current[4]), | |
sourceIndex: current[5] | |
})); | |
this.position++; | |
}; | |
Parser.prototype.error = function error(message, opts) { | |
throw this.root.error(message, opts); | |
}; | |
Parser.prototype.missingBackslash = function missingBackslash() { | |
return this.error('Expected a backslash preceding the semicolon.', { | |
index: this.currToken[5] | |
}); | |
}; | |
Parser.prototype.missingParenthesis = function missingParenthesis() { | |
return this.expected('opening parenthesis', this.currToken[5]); | |
}; | |
Parser.prototype.missingSquareBracket = function missingSquareBracket() { | |
return this.expected('opening square bracket', this.currToken[5]); | |
}; | |
Parser.prototype.namespace = function namespace() { | |
var before = this.prevToken && this.content(this.prevToken) || true; | |
if (this.nextToken[0] === tokens.word) { | |
this.position++; | |
return this.word(before); | |
} else if (this.nextToken[0] === tokens.asterisk) { | |
this.position++; | |
return this.universal(before); | |
} | |
}; | |
Parser.prototype.nesting = function nesting() { | |
var current = this.currToken; | |
this.newNode(new _nesting2.default({ | |
value: this.content(), | |
source: getSource(current[1], current[2], current[3], current[4]), | |
sourceIndex: current[5] | |
})); | |
this.position++; | |
}; | |
Parser.prototype.parentheses = function parentheses() { | |
var last = this.current.last; | |
var balanced = 1; | |
this.position++; | |
if (last && last.type === types.PSEUDO) { | |
var selector = new _selector2.default(); | |
var cache = this.current; | |
last.append(selector); | |
this.current = selector; | |
while (this.position < this.tokens.length && balanced) { | |
if (this.currToken[0] === tokens.openParenthesis) { | |
balanced++; | |
} | |
if (this.currToken[0] === tokens.closeParenthesis) { | |
balanced--; | |
} | |
if (balanced) { | |
this.parse(); | |
} else { | |
selector.parent.source.end.line = this.currToken[3]; | |
selector.parent.source.end.column = this.currToken[4]; | |
this.position++; | |
} | |
} | |
this.current = cache; | |
} else { | |
last.value += '('; | |
while (this.position < this.tokens.length && balanced) { | |
if (this.currToken[0] === tokens.openParenthesis) { | |
balanced++; | |
} | |
if (this.currToken[0] === tokens.closeParenthesis) { | |
balanced--; | |
} | |
last.value += this.parseParenthesisToken(this.currToken); | |
this.position++; | |
} | |
} | |
if (balanced) { | |
return this.expected('closing parenthesis', this.currToken[5]); | |
} | |
}; | |
Parser.prototype.pseudo = function pseudo() { | |
var _this2 = this; | |
var pseudoStr = ''; | |
var startingToken = this.currToken; | |
while (this.currToken && this.currToken[0] === tokens.colon) { | |
pseudoStr += this.content(); | |
this.position++; | |
} | |
if (!this.currToken) { | |
return this.expected(['pseudo-class', 'pseudo-element'], this.position - 1); | |
} | |
if (this.currToken[0] === tokens.word) { | |
this.splitWord(false, function (first, length) { | |
pseudoStr += first; | |
_this2.newNode(new _pseudo2.default({ | |
value: pseudoStr, | |
source: getSource(startingToken[1], startingToken[2], _this2.currToken[3], _this2.currToken[4]), | |
sourceIndex: startingToken[5] | |
})); | |
if (length > 1 && _this2.nextToken && _this2.nextToken[0] === tokens.openParenthesis) { | |
_this2.error('Misplaced parenthesis.', { | |
index: _this2.nextToken[5] | |
}); | |
} | |
}); | |
} else { | |
return this.expected(['pseudo-class', 'pseudo-element'], this.currToken[5]); | |
} | |
}; | |
Parser.prototype.space = function space() { | |
var content = this.content(); | |
// Handle space before and after the selector | |
if (this.position === 0 || this.prevToken[0] === tokens.comma || this.prevToken[0] === tokens.openParenthesis) { | |
this.spaces = this.parseSpace(content); | |
this.position++; | |
} else if (this.position === this.tokens.length - 1 || this.nextToken[0] === tokens.comma || this.nextToken[0] === tokens.closeParenthesis) { | |
this.current.last.spaces.after = this.parseSpace(content); | |
this.position++; | |
} else { | |
this.combinator(); | |
} | |
}; | |
Parser.prototype.string = function string() { | |
var current = this.currToken; | |
this.newNode(new _string2.default({ | |
value: this.content(), | |
source: getSource(current[1], current[2], current[3], current[4]), | |
sourceIndex: current[5] | |
})); | |
this.position++; | |
}; | |
Parser.prototype.universal = function universal(namespace) { | |
var nextToken = this.nextToken; | |
if (nextToken && this.content(nextToken) === '|') { | |
this.position++; | |
return this.namespace(); | |
} | |
var current = this.currToken; | |
this.newNode(new _universal2.default({ | |
value: this.content(), | |
source: getSource(current[1], current[2], current[3], current[4]), | |
sourceIndex: current[5] | |
}), namespace); | |
this.position++; | |
}; | |
Parser.prototype.splitWord = function splitWord(namespace, firstCallback) { | |
var _this3 = this; | |
var nextToken = this.nextToken; | |
var word = this.content(); | |
while (nextToken && ~[tokens.dollar, tokens.caret, tokens.equals, tokens.word].indexOf(nextToken[0])) { | |
this.position++; | |
var current = this.content(); | |
word += current; | |
if (current.lastIndexOf('\\') === current.length - 1) { | |
var next = this.nextToken; | |
if (next && next[0] === tokens.space) { | |
word += this.parseSpace(this.content(next), ' '); | |
this.position++; | |
} | |
} | |
nextToken = this.nextToken; | |
} | |
var hasClass = (0, _indexesOf2.default)(word, '.'); | |
var hasId = (0, _indexesOf2.default)(word, '#'); | |
// Eliminate Sass interpolations from the list of id indexes | |
var interpolations = (0, _indexesOf2.default)(word, '#{'); | |
if (interpolations.length) { | |
hasId = hasId.filter(function (hashIndex) { | |
return !~interpolations.indexOf(hashIndex); | |
}); | |
} | |
var indices = (0, _sortAscending2.default)((0, _uniq2.default)([0].concat(hasClass, hasId))); | |
indices.forEach(function (ind, i) { | |
var index = indices[i + 1] || word.length; | |
var value = word.slice(ind, index); | |
if (i === 0 && firstCallback) { | |
return firstCallback.call(_this3, value, indices.length); | |
} | |
var node = void 0; | |
var current = _this3.currToken; | |
var sourceIndex = current[5] + indices[i]; | |
var source = getSource(current[1], current[2] + ind, current[3], current[2] + (index - 1)); | |
if (~hasClass.indexOf(ind)) { | |
node = new _className2.default({ | |
value: value.slice(1), | |
source: source, | |
sourceIndex: sourceIndex | |
}); | |
} else if (~hasId.indexOf(ind)) { | |
node = new _id2.default({ | |
value: value.slice(1), | |
source: source, | |
sourceIndex: sourceIndex | |
}); | |
} else { | |
node = new _tag2.default({ | |
value: value, | |
source: source, | |
sourceIndex: sourceIndex | |
}); | |
} | |
_this3.newNode(node, namespace); | |
// Ensure that the namespace is used only once | |
namespace = null; | |
}); | |
this.position++; | |
}; | |
Parser.prototype.word = function word(namespace) { | |
var nextToken = this.nextToken; | |
if (nextToken && this.content(nextToken) === '|') { | |
this.position++; | |
return this.namespace(); | |
} | |
return this.splitWord(namespace); | |
}; | |
Parser.prototype.loop = function loop() { | |
while (this.position < this.tokens.length) { | |
this.parse(true); | |
} | |
return this.root; | |
}; | |
Parser.prototype.parse = function parse(throwOnParenthesis) { | |
switch (this.currToken[0]) { | |
case tokens.space: | |
this.space(); | |
break; | |
case tokens.comment: | |
this.comment(); | |
break; | |
case tokens.openParenthesis: | |
this.parentheses(); | |
break; | |
case tokens.closeParenthesis: | |
if (throwOnParenthesis) { | |
this.missingParenthesis(); | |
} | |
break; | |
case tokens.openSquare: | |
this.attribute(); | |
break; | |
case tokens.dollar: | |
case tokens.caret: | |
case tokens.equals: | |
case tokens.word: | |
this.word(); | |
break; | |
case tokens.colon: | |
this.pseudo(); | |
break; | |
case tokens.comma: | |
this.comma(); | |
break; | |
case tokens.asterisk: | |
this.universal(); | |
break; | |
case tokens.ampersand: | |
this.nesting(); | |
break; | |
case tokens.combinator: | |
this.combinator(); | |
break; | |
case tokens.str: | |
this.string(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment