cssom
Version:
CSS Object Model implementation and CSS parser
283 lines (261 loc) • 5.69 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>CSSOM.js parse method</title>
<script>
var exports = {};
function require(){
return exports;
}
</script>
<script src="../lib/CSSStyleDeclaration.js"></script>
<script src="../lib/CSSRule.js"></script>
<script src="../lib/CSSStyleRule.js"></script>
<script src="../lib/CSSImportRule.js"></script>
<script src="../lib/MediaList.js"></script>
<script src="../lib/CSSMediaRule.js"></script>
<script src="../lib/StyleSheet.js"></script>
<script src="../lib/CSSStyleSheet.js"></script>
<script src="../lib/parse.js"></script>
<script>
window.CSSOM = exports;
</script>
<style type="text/css">
html, body {
background: #333;
color: #EEE;
font: 12px sans-serif;
margin: 0;
height: 100%;
}
body {
padding-bottom: 1.7em;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
table {
width: 100%;
table-layout: fixed;
margin: 0 auto;
}
td {
vertical-align: top;
}
h1 {
font: normal 1em sans-serif;
display: inline;
}
#labels {
color: #FFE992;
width: 66%;
}
#labels td {
width: 50%;
text-align: center;
}
#labels td::before {
content: '↱ ';
color: #998e62;
position: relative;
top: .4em;
}
#labels td::after {
content: ' ↴';
color: #998e62;
position: relative;
top: .4em;
}
#content {
width: 100%;
height: 100%;
}
#content td {
width: 33%;
}
#content td + td {
padding-left: 1%;
}
#output span {
color: #666;
}
.style-cell textarea {
width: 99%;
height: 100%;
font: 12px monospace;
white-space: pre-wrap;
}
.serialized-cell {
border-left: 1px solid #363636;
}
#message {
visibility: hidden;
}
.error #message {
visibility: visible;
position: absolute;
top: 0;
left: 34%;
padding: 1em;
background: black;
color: #e34343;
font-size: 24px;
}
</style>
</head>
<body>
<table id="labels">
<tr><td><h1>CSSOM.parse</h1></td><td>.toString</td></tr>
</table>
<table id="content">
<tr>
<td class="style-cell">
<textarea id="style" spellcheck="false" rows="40">img {
border: none
}</textarea></td>
<td class="output-cell"><pre id="output"></pre></td>
<td class="serialized-cell"><pre id="serialized"></pre></td>
</tr>
</table>
<div id="message"></div>
<script defer>
/**
* @param {number} depth
* @return {string}
*/
function makeIndent(depth) {
var INDENT = ' ';
if (depth == 1) {
return INDENT;
} else if (depth < 1) {
return '';
}
if (depth in makeIndent.cache) {
return makeIndent.cache[depth];
} else {
var result = INDENT;
for (var i = depth; --i;) {
result += INDENT;
}
makeIndent.cache[depth] = result;
return result;
}
}
makeIndent.cache = {};
/**
* buildPath(2) -> '../..'
* @param {number} level
* @return {string}
*/
function buildPath(level) {
if (level == 0) {
return '.';
} else {
var result = '..';
for (var i = 1; i < level; i++) {
result += '/..';
}
return result;
}
}
/**
* stringifyObjectKey('color') -> 'color'
* stringifyObjectKey('background-color') -> '"background-color"'
* @param {string} key
* @return {string}
*/
function stringifyObjectKey(key) {
return /^[a-zA-Z_$][A-Za-z0-9_$]*$/.test(key) ?
key :
'"' + escapeDoubleQuotes(key) + '"';
}
/**
* @param {string} string
* @return {string}
* @see http://stackoverflow.com/questions/7382115/escape-quotes-in-a-string-with-backslash
*/
function escapeDoubleQuotes(string) {
return string.replace(/(\\*)(")/g, function(all, backslashes, quote) {
return backslashes.length % 2 ?
all :
backslashes + '\\' + quote;
});
}
/**
* @param {Object} object
* @param {number} [depth]
* @param {Array} [stack]
* @return {string}
*/
function inspect(object, depth, stack) {
depth ? depth++ : (depth = 1);
stack = stack || (stack = []);
switch (typeof object) {
case 'object':
var level = stack.indexOf(object);
if (level != -1) {
return buildPath(level);
}
stack = [object].concat(stack);
var properties = [];
var indent = makeIndent(depth);
for (var key in object) {
if (object.hasOwnProperty(key)) {
properties.push(indent + stringifyObjectKey(key) + '<span>: </span>' + inspect(object[key], depth, stack));
}
}
var indentInside = makeIndent(depth - 1);
return '<span>{</span>\n' + properties.join('<span>,</span>\n') + '\n' + indentInside + '<span>}</span>';
case 'string':
return '"' + object + '"';
default:
return object.toString();
}
}
var errors = [];
if (!("__defineGetter__" in {})) {
errors.push("Object.prototype.__defineGetter__ isn’t supported");
}
if (errors.length) {
document.getElementById("message").innerHTML = errors.join("<br>");
document.body.className = "error";
throw errors.join("\n\n");
}
var style = document.getElementById("style");
var output = document.getElementById("output");
var serialized = document.getElementById("serialized");
function outputUpdated(){
var value = style.value;
if (value != style.prevValue) {
var css = CSSOM.parse(value);
output.innerHTML = inspect(css);
serialized.innerHTML = css.toString();
style.prevValue = value;
}
}
function hashChanged(){
var hash = location.hash;
var splitted = hash.split("=");
if (splitted.length < 2) {
return;
}
var name = splitted[0];
var value = splitted[1];
if (name == "#css") {
style.value = decodeURIComponent(value);
outputUpdated();
}
}
hashChanged();
outputUpdated();
window.onhashchange = hashChanged;
style.onkeyup = style.onpaste = function changed(){
outputUpdated();
};
style.onchange = function updateLocation(){
location.hash = "css=" + encodeURIComponent(style.value);
};
</script>
</body>
</html>