mirror of
https://github.com/alexadam/save-as-ebook.git
synced 2025-09-11 01:44:44 +00:00
move 3rd party libs to /libs folder
This commit is contained in:
parent
1d40954594
commit
ab229d926e
9 changed files with 5 additions and 3 deletions
297
web-extension/libs/cssjson.js
Normal file
297
web-extension/libs/cssjson.js
Normal file
|
@ -0,0 +1,297 @@
|
|||
/**
|
||||
* CSS-JSON Converter for JavaScript
|
||||
* Converts CSS to JSON and back.
|
||||
* Version 2.1
|
||||
*
|
||||
* Released under the MIT license.
|
||||
*
|
||||
* Copyright (c) 2013 Aram Kocharyan, http://aramk.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var CSSJSON = new function () {
|
||||
|
||||
var base = this;
|
||||
|
||||
base.init = function () {
|
||||
// String functions
|
||||
String.prototype.trim = function () {
|
||||
return this.replace(/^\s+|\s+$/g, '');
|
||||
};
|
||||
|
||||
String.prototype.repeat = function (n) {
|
||||
return new Array(1 + n).join(this);
|
||||
};
|
||||
};
|
||||
base.init();
|
||||
|
||||
var selX = /([^\s\;\{\}][^\;\{\}]*)\{/g;
|
||||
var endX = /\}/g;
|
||||
var lineX = /([^\;\{\}]*)\;/g;
|
||||
var commentX = /\/\*[\s\S]*?\*\//g;
|
||||
var lineAttrX = /([^\:]+):([^\;]*);/;
|
||||
|
||||
// This is used, a concatenation of all above. We use alternation to
|
||||
// capture.
|
||||
var altX = /(\/\*[\s\S]*?\*\/)|([^\s\;\{\}][^\;\{\}]*(?=\{))|(\})|([^\;\{\}]+\;(?!\s*\*\/))/gmi;
|
||||
|
||||
// Capture groups
|
||||
var capComment = 1;
|
||||
var capSelector = 2;
|
||||
var capEnd = 3;
|
||||
var capAttr = 4;
|
||||
|
||||
var isEmpty = function (x) {
|
||||
return typeof x == 'undefined' || x.length == 0 || x == null;
|
||||
};
|
||||
|
||||
var isCssJson = function (node) {
|
||||
return !isEmpty(node) ? (node.attributes && node.children) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input is css string and current pos, returns JSON object
|
||||
*
|
||||
* @param cssString
|
||||
* The CSS string.
|
||||
* @param args
|
||||
* An optional argument object. ordered: Whether order of
|
||||
* comments and other nodes should be kept in the output. This
|
||||
* will return an object where all the keys are numbers and the
|
||||
* values are objects containing "name" and "value" keys for each
|
||||
* node. comments: Whether to capture comments. split: Whether to
|
||||
* split each comma separated list of selectors.
|
||||
*/
|
||||
base.toJSON = function (cssString, args) {
|
||||
var node = {
|
||||
children: {},
|
||||
attributes: {}
|
||||
};
|
||||
var match = null;
|
||||
var count = 0;
|
||||
|
||||
if (typeof args == 'undefined') {
|
||||
var args = {
|
||||
ordered: false,
|
||||
comments: false,
|
||||
stripComments: false,
|
||||
split: false
|
||||
};
|
||||
}
|
||||
if (args.stripComments) {
|
||||
args.comments = false;
|
||||
cssString = cssString.replace(commentX, '');
|
||||
}
|
||||
|
||||
while ((match = altX.exec(cssString)) != null) {
|
||||
if (!isEmpty(match[capComment]) && args.comments) {
|
||||
// Comment
|
||||
var add = match[capComment].trim();
|
||||
node[count++] = add;
|
||||
} else if (!isEmpty(match[capSelector])) {
|
||||
// New node, we recurse
|
||||
var name = match[capSelector].trim();
|
||||
// This will return when we encounter a closing brace
|
||||
var newNode = base.toJSON(cssString, args);
|
||||
if (args.ordered) {
|
||||
var obj = {};
|
||||
obj['name'] = name;
|
||||
obj['value'] = newNode;
|
||||
// Since we must use key as index to keep order and not
|
||||
// name, this will differentiate between a Rule Node and an
|
||||
// Attribute, since both contain a name and value pair.
|
||||
obj['type'] = 'rule';
|
||||
node[count++] = obj;
|
||||
} else {
|
||||
if (args.split) {
|
||||
var bits = name.split(',');
|
||||
} else {
|
||||
var bits = [name];
|
||||
}
|
||||
for (i in bits) {
|
||||
var sel = bits[i].trim();
|
||||
if (sel in node.children) {
|
||||
for (var att in newNode.attributes) {
|
||||
node.children[sel].attributes[att] = newNode.attributes[att];
|
||||
}
|
||||
} else {
|
||||
node.children[sel] = newNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!isEmpty(match[capEnd])) {
|
||||
// Node has finished
|
||||
return node;
|
||||
} else if (!isEmpty(match[capAttr])) {
|
||||
var line = match[capAttr].trim();
|
||||
var attr = lineAttrX.exec(line);
|
||||
if (attr) {
|
||||
// Attribute
|
||||
var name = attr[1].trim();
|
||||
var value = attr[2].trim();
|
||||
if (args.ordered) {
|
||||
var obj = {};
|
||||
obj['name'] = name;
|
||||
obj['value'] = value;
|
||||
obj['type'] = 'attr';
|
||||
node[count++] = obj;
|
||||
} else {
|
||||
if (name in node.attributes) {
|
||||
var currVal = node.attributes[name];
|
||||
if (!(currVal instanceof Array)) {
|
||||
node.attributes[name] = [currVal];
|
||||
}
|
||||
node.attributes[name].push(value);
|
||||
} else {
|
||||
node.attributes[name] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Semicolon terminated line
|
||||
node[count++] = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* A JSON node.
|
||||
* @param depth
|
||||
* The depth of the current node; used for indentation and
|
||||
* optional.
|
||||
* @param breaks
|
||||
* Whether to add line breaks in the output.
|
||||
*/
|
||||
base.toCSS = function (node, depth, breaks) {
|
||||
var cssString = '';
|
||||
if (typeof depth == 'undefined') {
|
||||
depth = 0;
|
||||
}
|
||||
if (typeof breaks == 'undefined') {
|
||||
breaks = false;
|
||||
}
|
||||
if (node.attributes) {
|
||||
for (i in node.attributes) {
|
||||
var att = node.attributes[i];
|
||||
if (att instanceof Array) {
|
||||
for (var j = 0; j < att.length; j++) {
|
||||
cssString += strAttr(i, att[j], depth);
|
||||
}
|
||||
} else {
|
||||
cssString += strAttr(i, att, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.children) {
|
||||
var first = true;
|
||||
for (i in node.children) {
|
||||
if (breaks && !first) {
|
||||
cssString += '\n';
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
cssString += strNode(i, node.children[i], depth);
|
||||
}
|
||||
}
|
||||
return cssString;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* You can pass css string or the CSSJS.toJSON return value.
|
||||
* @param id (Optional)
|
||||
* To identify and easy removable of the style element
|
||||
* @param replace (Optional. defaults to TRUE)
|
||||
* Whether to remove or simply do nothing
|
||||
* @return HTMLLinkElement
|
||||
*/
|
||||
base.toHEAD = function (data, id, replace) {
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var xnode = document.getElementById(id);
|
||||
var _xnodeTest = (xnode !== null && xnode instanceof HTMLStyleElement);
|
||||
|
||||
if (isEmpty(data) || !(head instanceof HTMLHeadElement)) return;
|
||||
if (_xnodeTest) {
|
||||
if (replace === true || isEmpty(replace)) {
|
||||
xnode.removeAttribute('id');
|
||||
} else return;
|
||||
}
|
||||
if (isCssJson(data)) {
|
||||
data = base.toCSS(data);
|
||||
}
|
||||
|
||||
var node = document.createElement('style');
|
||||
node.type = 'text/css';
|
||||
|
||||
if (!isEmpty(id)) {
|
||||
node.id = id;
|
||||
} else {
|
||||
node.id = 'cssjson_' + timestamp();
|
||||
}
|
||||
if (node.styleSheet) {
|
||||
node.styleSheet.cssText = data;
|
||||
} else {
|
||||
node.appendChild(document.createTextNode(data));
|
||||
}
|
||||
|
||||
head.appendChild(node);
|
||||
|
||||
if (isValidStyleNode(node)) {
|
||||
if (_xnodeTest) {
|
||||
xnode.parentNode.removeChild(xnode);
|
||||
}
|
||||
} else {
|
||||
node.parentNode.removeChild(node);
|
||||
if (_xnodeTest) {
|
||||
xnode.setAttribute('id', id);
|
||||
node = xnode;
|
||||
} else return;
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
// Alias
|
||||
|
||||
if (typeof window != 'undefined') {
|
||||
window.createCSS = base.toHEAD;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
var isValidStyleNode = function (node) {
|
||||
return (node instanceof HTMLStyleElement) && node.sheet.cssRules.length > 0;
|
||||
}
|
||||
|
||||
var timestamp = function () {
|
||||
return Date.now() || +new Date();
|
||||
};
|
||||
|
||||
var strAttr = function (name, value, depth) {
|
||||
return '\t'.repeat(depth) + name + ': ' + value + ';\n';
|
||||
};
|
||||
|
||||
var strNode = function (name, value, depth) {
|
||||
var cssString = '\t'.repeat(depth) + name + ' {\n';
|
||||
cssString += base.toCSS(value, depth + 1);
|
||||
cssString += '\t'.repeat(depth) + '}\n';
|
||||
return cssString;
|
||||
};
|
||||
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue