├── WebContent ├── error.gif ├── options.png ├── close_icon.gif ├── jsonview128.png ├── jsonview16.png ├── jsonview48.png ├── viewer │ ├── jsoneditor │ │ ├── img │ │ │ └── jsoneditor-icons.png │ │ └── jsoneditor.min.css │ ├── viewer.js │ └── index.html ├── content_error.css ├── codemirror │ ├── default.css │ ├── LICENSE │ ├── codemirror.css │ └── css.js ├── jsonview.css ├── csseditor.html ├── manifest.json ├── options.html ├── options.js ├── options.css ├── jsonview-core.css ├── workerFormatter.js ├── csseditor.js ├── background.js ├── csseditor.css ├── content.js └── workerJSONLint.js ├── README.md ├── .project └── LICENSE.txt /WebContent/error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/error.gif -------------------------------------------------------------------------------- /WebContent/options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/options.png -------------------------------------------------------------------------------- /WebContent/close_icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/close_icon.gif -------------------------------------------------------------------------------- /WebContent/jsonview128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/jsonview128.png -------------------------------------------------------------------------------- /WebContent/jsonview16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/jsonview16.png -------------------------------------------------------------------------------- /WebContent/jsonview48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/jsonview48.png -------------------------------------------------------------------------------- /WebContent/viewer/jsoneditor/img/jsoneditor-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aneasystone/JSONView-for-Chrome/master/WebContent/viewer/jsoneditor/img/jsoneditor-icons.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSONView-for-Chrome 2 | 3 | JSONView-for-Chrome is an extension of chrome created by [gildas-lormeau](https://github.com/gildas-lormeau/JSONView-for-Chrome) 4 | which is very useful for people who deals a lot with json type http requests. 5 | 6 | But sometimes we would like to handle with our own json data, not from the internet. So I added a json editor to this extension 7 | to make it more handful. The json editor is copied from [josdejong's jsoneditor](https://github.com/josdejong/jsoneditor). 8 | -------------------------------------------------------------------------------- /WebContent/viewer/viewer.js: -------------------------------------------------------------------------------- 1 | var container = document.getElementById('jsoneditor'); 2 | 3 | var options = { 4 | mode: 'text', 5 | modes: ['code', 'text', 'view'], // allowed modes 6 | error: function (err) { 7 | alert(err.toString()); 8 | } 9 | }; 10 | 11 | var json = { 12 | "array": [1, 2, 3], 13 | "boolean": true, 14 | "null": null, 15 | "number": 123, 16 | "object": {"a": "b", "c": "d"}, 17 | "string": "Hello World" 18 | }; 19 | 20 | var editor = new JSONEditor(container, options, json); -------------------------------------------------------------------------------- /WebContent/content_error.css: -------------------------------------------------------------------------------- 1 | .error-position { 2 | display: inline-block; 3 | color: fireBrick; 4 | padding-left: 3px; 5 | padding-right: 3px; 6 | } 7 | 8 | .error-position img { 9 | padding-right: 3px; 10 | height: .8em; 11 | } 12 | 13 | .container { 14 | position: absolute; 15 | left: 0px; 16 | width: 100%; 17 | } 18 | 19 | .content { 20 | top: 3px; 21 | width: 30em; 22 | margin: 0 auto; 23 | background-color: #FEE; 24 | border: 2px solid #933; 25 | color: #933; 26 | padding: 20px; 27 | position: relative; 28 | -webkit-box-shadow: #888 3px 3px 5px; 29 | } 30 | 31 | .close-error { 32 | background-image: url("close_icon.gif"); 33 | width: 16px; 34 | height: 16px; 35 | position: absolute; 36 | top: 3px; 37 | right: 3px; 38 | cursor: pointer; 39 | } -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JSONView 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.wst.common.project.facet.core.builder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.validation.validationbuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.wst.common.project.facet.core.nature 26 | org.eclipse.wst.common.modulecore.ModuleCoreNature 27 | org.eclipse.wst.jsdt.core.jsNature 28 | 29 | 30 | -------------------------------------------------------------------------------- /WebContent/codemirror/default.css: -------------------------------------------------------------------------------- 1 | .cm-s-default span.cm-keyword {color: #708;} 2 | .cm-s-default span.cm-atom {color: #219;} 3 | .cm-s-default span.cm-number {color: #164;} 4 | .cm-s-default span.cm-def {color: #00f;} 5 | .cm-s-default span.cm-variable {color: black;} 6 | .cm-s-default span.cm-variable-2 {color: #05a;} 7 | .cm-s-default span.cm-variable-3 {color: #085;} 8 | .cm-s-default span.cm-property {color: black;} 9 | .cm-s-default span.cm-operator {color: black;} 10 | .cm-s-default span.cm-comment {color: #a50;} 11 | .cm-s-default span.cm-string {color: #a11;} 12 | .cm-s-default span.cm-string-2 {color: #f50;} 13 | .cm-s-default span.cm-meta {color: #555;} 14 | .cm-s-default span.cm-error {color: #f00;} 15 | .cm-s-default span.cm-qualifier {color: #555;} 16 | .cm-s-default span.cm-builtin {color: #30a;} 17 | .cm-s-default span.cm-bracket {color: #cc7;} 18 | .cm-s-default span.cm-tag {color: #170;} 19 | .cm-s-default span.cm-attribute {color: #00c;} 20 | -------------------------------------------------------------------------------- /WebContent/jsonview.css: -------------------------------------------------------------------------------- 1 | body { 2 | white-space: pre; 3 | font-family: monospace; 4 | } 5 | 6 | .property { 7 | font-weight: bold; 8 | } 9 | 10 | .type-null { 11 | color: gray; 12 | } 13 | 14 | .type-boolean { 15 | color: firebrick; 16 | } 17 | 18 | .type-number { 19 | color: blue; 20 | } 21 | 22 | .type-string { 23 | color: green; 24 | } 25 | 26 | .callback-function { 27 | color: gray; 28 | } 29 | 30 | .collapser:after { 31 | content: "-"; 32 | } 33 | 34 | .collapsed > .collapser:after { 35 | content: "+"; 36 | } 37 | 38 | .ellipsis:after { 39 | content: " … "; 40 | } 41 | 42 | .collapsible { 43 | margin-left: 2em; 44 | } 45 | 46 | .hoverable { 47 | padding-top: 1px; 48 | padding-bottom: 1px; 49 | padding-left: 2px; 50 | padding-right: 2px; 51 | border-radius: 2px; 52 | } 53 | 54 | .hovered { 55 | background-color: rgba(235, 238, 249, 1); 56 | } 57 | 58 | .collapser { 59 | padding-right: 6px; 60 | padding-left: 6px; 61 | } -------------------------------------------------------------------------------- /WebContent/csseditor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Style editor - JSONView 5 | 6 | 7 | 8 | 9 | 10 |
11 |

Style editor

12 |
13 |
14 |
CSS
15 | 16 |
17 |
18 |
Preview
19 | 20 |
21 | 22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /WebContent/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSONView", 3 | "icons": { 4 | "16": "jsonview16.png", 5 | "48": "jsonview48.png", 6 | "128": "jsonview128.png"}, 7 | "version": "0.0.32.2", 8 | "description": "Validate and view JSON documents", 9 | "options_page": "options.html", 10 | "browser_action": { 11 | "default_icon" : "jsonview16.png", 12 | "default_title" : "JSONView" 13 | }, 14 | "background" : { 15 | "scripts": [ 16 | "background.js" 17 | ] 18 | }, 19 | "content_scripts": [{ 20 | "matches": ["http://*/*", "https://*/*", "ftp://*/*", "file:///*"], 21 | "js": ["content.js"], 22 | "run_at" : "document_end", 23 | "all_frames" : true 24 | }], 25 | "web_accessible_resources": [ 26 | "jsonview.css", 27 | "jsonview-core.css", 28 | "content_error.css", 29 | "options.png", 30 | "close_icon.gif", 31 | "error.gif" 32 | ], 33 | "permissions" : ["clipboardWrite", "http://*/", "contextMenus", "https://*/", "ftp://*/"], 34 | "manifest_version": 2 35 | } 36 | -------------------------------------------------------------------------------- /WebContent/viewer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSONEditor | Switch mode 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 27 | 28 | 29 | 30 |
31 |

32 | You can paste the json data into `Text View` and change the view mode to see the effects. Enjoy it! 33 | Powered by josdejong's jsoneditor. 34 |

35 |
36 |
37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /WebContent/codemirror/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Marijn Haverbeke 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Original work Copyright (c) 2009 Benjamin Hollis 4 | Modified work Copyright (c) 2012 Gildas Lormeau 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /WebContent/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JSONView options 5 | 6 | 7 | 8 | 9 |
10 |
11 |

iconJSONView options

12 |
13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 | 28 |
29 |

(*) safe method forces the browser to send an extra HTTP request to get the raw HTTP content.

30 |
31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /WebContent/options.js: -------------------------------------------------------------------------------- 1 | function initOptions() { 2 | var bgPage = chrome.extension.getBackgroundPage(), options = localStorage.options ? JSON.parse(localStorage.options) : {}; 3 | var safeMethodInput = document.getElementById("safeMethodInput"), injectInFrameInput = document.getElementById("injectInFrameInput"), addContextMenuInput = document.getElementById("addContextMenuInput"); 4 | safeMethodInput.checked = options.safeMethod; 5 | injectInFrameInput.checked = options.injectInFrame; 6 | addContextMenuInput.checked = options.addContextMenu; 7 | safeMethodInput.addEventListener("change", function() { 8 | options.safeMethod = safeMethodInput.checked; 9 | localStorage.options = JSON.stringify(options); 10 | }); 11 | injectInFrameInput.addEventListener("change", function() { 12 | options.injectInFrame = injectInFrameInput.checked; 13 | localStorage.options = JSON.stringify(options); 14 | }); 15 | addContextMenuInput.addEventListener("change", function() { 16 | options.addContextMenu = addContextMenuInput.checked; 17 | localStorage.options = JSON.stringify(options); 18 | bgPage.refreshMenuEntry(); 19 | }); 20 | document.getElementById("open-editor").addEventListener("click", function() { 21 | location.href = "csseditor.html"; 22 | }, false); 23 | } 24 | 25 | addEventListener("load", initOptions, false); 26 | -------------------------------------------------------------------------------- /WebContent/options.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #EEE; 3 | font-size: 10pt; 4 | } 5 | 6 | body > div { 7 | position: relative; 8 | margin: 0px auto; 9 | width: 400px; 10 | font-family: sans-serif; 11 | background-color: white; 12 | border: 1px solid #D2DBED; 13 | font-family: Arial, sans-serif; 14 | font-size: 13px; 15 | -webkit-box-shadow: #888 2px 2px 2px; 16 | } 17 | 18 | body > div > div { 19 | padding-left: 10px; 20 | padding-right: 10px; 21 | } 22 | 23 | .optionBlock { 24 | overflow: hidden; 25 | height: 30px; 26 | position: relative; 27 | } 28 | 29 | h2 { 30 | font-size: 17px; 31 | font-weight: bold; 32 | margin-bottom: 20px; 33 | } 34 | 35 | label { 36 | position: absolute; 37 | top: 2px; 38 | display: inline-block; 39 | } 40 | 41 | input[type="checkbox"] { 42 | position: absolute; 43 | right: 0px; 44 | width: auto; 45 | margin-left: 15px; 46 | margin-bottom: 5px; 47 | margin-top: 5px; 48 | width: auto; 49 | } 50 | 51 | button { 52 | position: absolute; 53 | top: -4px; 54 | right: 0px; 55 | background-color: #F3F3F3; 56 | -webkit-border-radius: 3px; 57 | right: 0px; 58 | } 59 | 60 | #main { 61 | border-radius: 5px; 62 | } 63 | 64 | #icon { 65 | width: 25px; 66 | padding-right: 10px; 67 | vertical-align: bottom; 68 | } 69 | 70 | p { 71 | margin-top: 5px; 72 | font-style: italic; 73 | text-align: justify; 74 | color: gray; 75 | } -------------------------------------------------------------------------------- /WebContent/jsonview-core.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-bottom: 23px; 3 | white-space: normal !important; 4 | } 5 | 6 | ul { 7 | list-style-type: none; 8 | padding: 0px; 9 | margin: 0px 0px 0px 26px; 10 | } 11 | 12 | li { 13 | position: relative; 14 | } 15 | 16 | .hoverable { 17 | transition: background-color .2s ease-out 0s; 18 | -webkit-transition: background-color .2s ease-out 0s; 19 | display: inline-block; 20 | } 21 | 22 | .hovered { 23 | transition-delay: .2s; 24 | -webkit-transition-delay: .2s; 25 | } 26 | 27 | .selected { 28 | outline-style: solid; 29 | outline-width: 1px; 30 | outline-style: dotted; 31 | } 32 | 33 | .collapsed>.collapsible { 34 | display: none; 35 | } 36 | 37 | .ellipsis { 38 | display: none; 39 | } 40 | 41 | .collapsed>.ellipsis { 42 | display: inherit; 43 | } 44 | 45 | .collapser { 46 | position: absolute; 47 | top: 1px; 48 | left: -1.5em; 49 | cursor: default; 50 | user-select: none; 51 | -webkit-user-select: none; 52 | } 53 | 54 | .status { 55 | position: fixed; 56 | left: 0px; 57 | bottom: 0px; 58 | min-width: 628px; 59 | border-color: #c2c2c2; 60 | border-top-width: 1px; 61 | border-right-width: 1px; 62 | border-bottom-width: 0px; 63 | border-left-width: 0px; 64 | border-style: solid; 65 | border-top-right-radius: 4px; 66 | height: 16px; 67 | padding-top: 2px; 68 | padding-bottom: 2px; 69 | padding-right: 7px; 70 | padding-left: 4px; 71 | font-family: sans-serif; 72 | font-size: 12px; 73 | opacity: 0; 74 | background-color: #d2d2f6; 75 | color: #696969; 76 | transition: opacity .2s ease-out; 77 | -webkit-transition: opacity .2s ease-out; 78 | user-select: none; 79 | -webkit-user-select: none; 80 | } 81 | 82 | .status:not(:empty ) { 83 | opacity: 1; 84 | } 85 | 86 | .toolbox { 87 | font-family: sans-serif; 88 | font-size: 13px; 89 | opacity: .25; 90 | background-color: #d2d2f6; 91 | position: fixed; 92 | right: 0px; 93 | top: 0px; 94 | border-color: #c2c2c2; 95 | border-bottom-width: 1px; 96 | border-left-width: 1px; 97 | border-top-width: 0px; 98 | border-right-width: 0px; 99 | border-style: solid; 100 | border-bottom-left-radius: 4px; 101 | padding-bottom: 3px; 102 | transition: opacity .2s ease-out; 103 | -webkit-transition: opacity .2s ease-out; 104 | cursor: default; 105 | user-select: none; 106 | -webkit-user-select: none; 107 | padding-left: 2px; 108 | } 109 | 110 | .toolbox:hover { 111 | opacity: 1; 112 | } 113 | 114 | .toolbox>* { 115 | padding-left: 3px; 116 | padding-right: 3px; 117 | } 118 | 119 | .toolbox>a { 120 | padding-left: 5px; 121 | } 122 | 123 | .toolbox>img { 124 | height: 14px; 125 | vertical-align: bottom; 126 | cursor: pointer; 127 | } -------------------------------------------------------------------------------- /WebContent/workerFormatter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Adapted the code in to order to run in a web worker. 3 | * 4 | * Original author: Benjamin Hollis 5 | */ 6 | 7 | function htmlEncode(t) { 8 | return t != null ? t.toString().replace(/&/g, "&").replace(/"/g, """).replace(//g, ">") : ''; 9 | } 10 | 11 | function decorateWithSpan(value, className) { 12 | return '' + htmlEncode(value) + ''; 13 | } 14 | 15 | function valueToHTML(value) { 16 | var valueType = typeof value, output = ""; 17 | if (value == null) 18 | output += decorateWithSpan("null", "type-null"); 19 | else if (value && value.constructor == Array) 20 | output += arrayToHTML(value); 21 | else if (valueType == "object") 22 | output += objectToHTML(value); 23 | else if (valueType == "number") 24 | output += decorateWithSpan(value, "type-number"); 25 | else if (valueType == "string") 26 | if (/^(http|https):\/\/[^\s]+$/.test(value)) 27 | output += decorateWithSpan('"', "type-string") + '' + htmlEncode(value) + '' + decorateWithSpan('"', "type-string"); 28 | else 29 | output += decorateWithSpan('"' + value + '"', "type-string"); 30 | else if (valueType == "boolean") 31 | output += decorateWithSpan(value, "type-boolean"); 32 | 33 | return output; 34 | } 35 | 36 | function arrayToHTML(json) { 37 | var i, length, output = '
[]'; 47 | if (!hasContents) 48 | output = "[ ]"; 49 | return output; 50 | } 51 | 52 | function objectToHTML(json) { 53 | var i, key, length, keys = Object.keys(json), output = '
{}'; 65 | if (!hasContents) 66 | output = "{ }"; 67 | return output; 68 | } 69 | 70 | function jsonToHTML(json, fnName) { 71 | var output = ''; 72 | if (fnName) 73 | output += '
' + fnName + '(
'; 74 | output += '
'; 75 | output += valueToHTML(json); 76 | output += '
'; 77 | if (fnName) 78 | output += '
)
'; 79 | return output; 80 | } 81 | 82 | addEventListener("message", function(event) { 83 | var object; 84 | try { 85 | object = JSON.parse(event.data.json); 86 | } catch (e) { 87 | postMessage({ 88 | error : true 89 | }); 90 | return; 91 | } 92 | postMessage({ 93 | onjsonToHTML : true, 94 | html : jsonToHTML(object, event.data.fnName) 95 | }); 96 | }, false); 97 | -------------------------------------------------------------------------------- /WebContent/csseditor.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var SAMPLE_PART1 = '
{}
'; 5 | var PASSIVE_KEYS = [ "Down", "Up", "Left", "Right", "End", "Home", "PageDown", "PageUp", "Control", "Alt", "Shift", "Insert" ]; 6 | 7 | var bgPage = chrome.extension.getBackgroundPage(), editor = document.getElementById("editor"), resetButton = document.getElementById("reset-button"), saveButton = document 8 | .getElementById("save-button"), previewer = document.getElementById("previewer").contentWindow, codemirror; 9 | 10 | function updatePreview() { 11 | previewer.document.open(); 12 | previewer.document.write(SAMPLE_PART1); 13 | previewer.document.write(codemirror.getValue()); 14 | previewer.document.write(SAMPLE_PART2); 15 | previewer.document.close(); 16 | } 17 | 18 | resetButton.addEventListener("click", function() { 19 | bgPage.getDefaultTheme(function(theme) { 20 | codemirror.setValue(theme); 21 | updatePreview(); 22 | }); 23 | }, false); 24 | 25 | saveButton.addEventListener("click", function() { 26 | localStorage.theme = codemirror.getValue(); 27 | }, false); 28 | 29 | addEventListener("load", function() { 30 | var timeoutOnKey; 31 | codemirror = CodeMirror.fromTextArea(editor, { 32 | onKeyEvent : function(editor, event) { 33 | if (event.type == "keyup" && PASSIVE_KEYS.indexOf(event.keyIdentifier) == -1) { 34 | if (timeoutOnKey) 35 | clearTimeout(timeoutOnKey); 36 | timeoutOnKey = setTimeout(updatePreview, 500); 37 | } 38 | } 39 | }); 40 | codemirror.setValue(localStorage.theme); 41 | updatePreview(); 42 | }, false); 43 | 44 | })(); 45 | -------------------------------------------------------------------------------- /WebContent/background.js: -------------------------------------------------------------------------------- 1 | var path, value, copyPathMenuEntryId, copyValueMenuEntryId; 2 | 3 | function getDefaultTheme(callback) { 4 | var xhr = new XMLHttpRequest(); 5 | xhr.onreadystatechange = function() { 6 | if (xhr.readyState == 4) 7 | callback(xhr.responseText); 8 | }; 9 | xhr.open("GET", "jsonview.css", true); 10 | xhr.send(null); 11 | } 12 | 13 | function copy(value) { 14 | var selElement, selRange, selection; 15 | selElement = document.createElement("span"); 16 | selRange = document.createRange(); 17 | selElement.innerText = value; 18 | document.body.appendChild(selElement); 19 | selRange.selectNodeContents(selElement); 20 | selection = window.getSelection(); 21 | selection.removeAllRanges(); 22 | selection.addRange(selRange); 23 | document.execCommand("Copy"); 24 | document.body.removeChild(selElement); 25 | } 26 | 27 | function refreshMenuEntry() { 28 | var options = localStorage.options ? JSON.parse(localStorage.options) : {}; 29 | if (options.addContextMenu && !copyPathMenuEntryId) { 30 | copyPathMenuEntryId = chrome.contextMenus.create({ 31 | title : "Copy path", 32 | contexts : [ "page", "link" ], 33 | onclick : function(info, tab) { 34 | copy(path); 35 | } 36 | }); 37 | copyValueMenuEntryId = chrome.contextMenus.create({ 38 | title : "Copy value", 39 | contexts : [ "page", "link" ], 40 | onclick : function(info, tab) { 41 | copy(value); 42 | } 43 | }); 44 | } 45 | if (!options.addContextMenu && copyPathMenuEntryId) { 46 | chrome.contextMenus.remove(copyPathMenuEntryId); 47 | chrome.contextMenus.remove(copyValueMenuEntryId); 48 | copyPathMenuEntryId = null; 49 | } 50 | } 51 | 52 | function init() { 53 | chrome.runtime.onConnect.addListener(function(port) { 54 | port.onMessage.addListener(function(msg) { 55 | var workerFormatter, workerJSONLint, json = msg.json; 56 | 57 | function onWorkerJSONLintMessage() { 58 | var message = JSON.parse(event.data); 59 | workerJSONLint.removeEventListener("message", onWorkerJSONLintMessage, false); 60 | workerJSONLint.terminate(); 61 | port.postMessage({ 62 | ongetError : true, 63 | error : message.error, 64 | loc : message.loc, 65 | offset : msg.offset 66 | }); 67 | } 68 | 69 | function onWorkerFormatterMessage(event) { 70 | var message = event.data; 71 | workerFormatter.removeEventListener("message", onWorkerFormatterMessage, false); 72 | workerFormatter.terminate(); 73 | if (message.html) 74 | port.postMessage({ 75 | onjsonToHTML : true, 76 | html : message.html, 77 | theme : localStorage.theme 78 | }); 79 | if (message.error) { 80 | workerJSONLint = new Worker("workerJSONLint.js"); 81 | workerJSONLint.addEventListener("message", onWorkerJSONLintMessage, false); 82 | workerJSONLint.postMessage(json); 83 | } 84 | } 85 | 86 | if (msg.init) 87 | port.postMessage({ 88 | oninit : true, 89 | options : localStorage.options ? JSON.parse(localStorage.options) : {} 90 | }); 91 | if (msg.copyPropertyPath) { 92 | path = msg.path; 93 | value = msg.value; 94 | } 95 | if (msg.jsonToHTML) { 96 | workerFormatter = new Worker("workerFormatter.js"); 97 | workerFormatter.addEventListener("message", onWorkerFormatterMessage, false); 98 | workerFormatter.postMessage({ 99 | json : json, 100 | fnName : msg.fnName 101 | }); 102 | } 103 | }); 104 | }); 105 | refreshMenuEntry(); 106 | } 107 | 108 | var options = {}; 109 | if (localStorage.options) 110 | options = JSON.parse(localStorage.options); 111 | if (typeof options.addContextMenu == "undefined") { 112 | options.addContextMenu = true; 113 | localStorage.options = JSON.stringify(options); 114 | } 115 | 116 | if (!localStorage.theme) 117 | getDefaultTheme(function(theme) { 118 | localStorage.theme = theme; 119 | init(); 120 | }); 121 | else 122 | init(); 123 | 124 | // click on browser action 125 | chrome.browserAction.onClicked.addListener(function(tab) { 126 | chrome.tabs.create({ 127 | url: chrome.extension.getURL("viewer/index.html") 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /WebContent/csseditor.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #EEE; 3 | font-size: 10pt; 4 | } 5 | 6 | body>div { 7 | margin-left: auto; 8 | margin-right: auto; 9 | width: 950px; 10 | background-color: white; 11 | font-family: sans-serif; 12 | margin-bottom: 10px; 13 | border-width: 0px; 14 | border-style: solid; 15 | border-radius: 5px; 16 | padding-left: 10px; 17 | padding-right: 10px; 18 | padding-bottom: 5px; 19 | text-align: justify; 20 | -webkit-box-shadow: #888 2px 2px 2px; 21 | } 22 | 23 | h2 { 24 | padding-left: .1em; 25 | padding-top: 1em; 26 | padding-bottom: .1em; 27 | } 28 | 29 | #previewer { 30 | width: 420px; 31 | height: 315px; 32 | border-width: 1px; 33 | border-style: solid; 34 | border-color: #aaa; 35 | } 36 | 37 | #editor,.CodeMirror { 38 | width: 500px; 39 | height: 590px; 40 | border-width: 1px; 41 | border-style: solid; 42 | border-color: #aaa; 43 | } 44 | 45 | .CodeMirror .CodeMirror-scroll { 46 | height: 100%; 47 | } 48 | 49 | .panel { 50 | height: 620px; 51 | vertical-align: top; 52 | display: inline-block; 53 | margin: 5px; 54 | position: relative; 55 | } 56 | 57 | .panel-label { 58 | height: 20px; 59 | } 60 | 61 | .buttons { 62 | position: absolute; 63 | bottom: 0px; 64 | right: 0px; 65 | } 66 | 67 | .buttons button { 68 | background-color: #F3F3F3; 69 | -webkit-border-radius: 3px; 70 | } 71 | 72 | 73 | ::-webkit-scrollbar { 74 | height: 16px; 75 | overflow: visible; 76 | width: 16px 77 | } 78 | 79 | ::-webkit-scrollbar-button { 80 | height: 0; 81 | width: 0 82 | } 83 | 84 | ::-webkit-scrollbar-track { 85 | background-clip: padding-box; 86 | border: solid transparent; 87 | border-width: 0 0 0 7px 88 | } 89 | 90 | ::-webkit-scrollbar-track:horizontal { 91 | border-width: 7px 0 0 92 | } 93 | 94 | ::-webkit-scrollbar-track:hover { 95 | background-color: rgba(0, 0, 0, .05); 96 | box-shadow: inset 1px 0 0 rgba(0, 0, 0, .1) 97 | } 98 | 99 | ::-webkit-scrollbar-track:horizontal:hover { 100 | box-shadow: inset 0 1px 0 rgba(0, 0, 0, .1) 101 | } 102 | 103 | ::-webkit-scrollbar-track:active { 104 | background-color: rgba(0, 0, 0, .05); 105 | box-shadow: inset 1px 0 0 rgba(0, 0, 0, .14), inset -1px 0 0 106 | rgba(0, 0, 0, .07) 107 | } 108 | 109 | ::-webkit-scrollbar-track:horizontal:active { 110 | box-shadow: inset 0 1px 0 rgba(0, 0, 0, .14), inset 0 -1px 0 111 | rgba(0, 0, 0, .07) 112 | } 113 | 114 | ::-webkit-scrollbar-thumb { 115 | background-color: rgba(0, 0, 0, .2); 116 | background-clip: padding-box; 117 | border: solid transparent; 118 | border-width: 0 0 0 7px; 119 | min-height: 28px; 120 | padding: 100px 0 0; 121 | box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1), inset 0 -1px 0 122 | rgba(0, 0, 0, .07) 123 | } 124 | 125 | ::-webkit-scrollbar-thumb:horizontal { 126 | border-width: 7px 0 0; 127 | padding: 0 0 0 100px; 128 | box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1), inset -1px 0 0 129 | rgba(0, 0, 0, .07) 130 | } 131 | 132 | ::-webkit-scrollbar-thumb:hover { 133 | background-color: rgba(0, 0, 0, .4); 134 | box-shadow: inset 1px 1px 1px rgba(0, 0, 0, .25) 135 | } 136 | 137 | ::-webkit-scrollbar-thumb:active { 138 | background-color: rgba(0, 0, 0, 0.5); 139 | box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.35) 140 | } 141 | 142 | ::-webkit-scrollbar-corner { 143 | background: transparent 144 | } 145 | 146 | body::-webkit-scrollbar-track-piece { 147 | background-clip: padding-box; 148 | background-color: #f5f5f5; 149 | border: solid #fff; 150 | border-width: 0 0 0 3px; 151 | box-shadow: inset 1px 0 0 rgba(0, 0, 0, .14), inset -1px 0 0 152 | rgba(0, 0, 0, .07) 153 | } 154 | 155 | body::-webkit-scrollbar-track-piece:horizontal { 156 | border-width: 3px 0 0; 157 | box-shadow: inset 0 1px 0 rgba(0, 0, 0, .14), inset 0 -1px 0 158 | rgba(0, 0, 0, .07) 159 | } 160 | 161 | body::-webkit-scrollbar-thumb { 162 | border-width: 1px 1px 1px 5px 163 | } 164 | 165 | body::-webkit-scrollbar-thumb:horizontal { 166 | border-width: 5px 1px 1px 167 | } 168 | 169 | body::-webkit-scrollbar-corner { 170 | background-clip: padding-box; 171 | background-color: #f5f5f5; 172 | border: solid #fff; 173 | border-width: 3px 0 0 3px; 174 | box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .14) 175 | } -------------------------------------------------------------------------------- /WebContent/codemirror/codemirror.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { 2 | line-height: 1em; 3 | font-family: monospace; 4 | 5 | /* Necessary so the scrollbar can be absolutely positioned within the wrapper on Lion. */ 6 | position: relative; 7 | /* This prevents unwanted scrollbars from showing up on the body and wrapper in IE. */ 8 | overflow: hidden; 9 | } 10 | 11 | .CodeMirror-scroll { 12 | overflow: auto; 13 | height: 300px; 14 | /* This is needed to prevent an IE[67] bug where the scrolled content 15 | is visible outside of the scrolling box. */ 16 | position: relative; 17 | outline: none; 18 | } 19 | 20 | /* Vertical scrollbar */ 21 | .CodeMirror-scrollbar { 22 | position: absolute; 23 | right: 0; top: 0; 24 | overflow-x: hidden; 25 | overflow-y: scroll; 26 | z-index: 5; 27 | } 28 | .CodeMirror-scrollbar-inner { 29 | /* This needs to have a nonzero width in order for the scrollbar to appear 30 | in Firefox and IE9. */ 31 | width: 1px; 32 | } 33 | .CodeMirror-scrollbar.cm-sb-overlap { 34 | /* Ensure that the scrollbar appears in Lion, and that it overlaps the content 35 | rather than sitting to the right of it. */ 36 | position: absolute; 37 | z-index: 1; 38 | float: none; 39 | right: 0; 40 | min-width: 12px; 41 | } 42 | .CodeMirror-scrollbar.cm-sb-nonoverlap { 43 | min-width: 12px; 44 | } 45 | .CodeMirror-scrollbar.cm-sb-ie7 { 46 | min-width: 18px; 47 | } 48 | 49 | .CodeMirror-gutter { 50 | position: absolute; left: 0; top: 0; 51 | z-index: 10; 52 | background-color: #f7f7f7; 53 | border-right: 1px solid #eee; 54 | min-width: 2em; 55 | height: 100%; 56 | } 57 | .CodeMirror-gutter-text { 58 | color: #aaa; 59 | text-align: right; 60 | padding: .4em .2em .4em .4em; 61 | white-space: pre !important; 62 | cursor: default; 63 | } 64 | .CodeMirror-lines { 65 | padding: .4em; 66 | white-space: pre; 67 | cursor: text; 68 | } 69 | 70 | .CodeMirror pre { 71 | -moz-border-radius: 0; 72 | -webkit-border-radius: 0; 73 | -o-border-radius: 0; 74 | border-radius: 0; 75 | border-width: 0; margin: 0; padding: 0; background: transparent; 76 | font-family: inherit; 77 | font-size: inherit; 78 | padding: 0; margin: 0; 79 | white-space: pre; 80 | word-wrap: normal; 81 | line-height: inherit; 82 | color: inherit; 83 | overflow: visible; 84 | } 85 | 86 | .CodeMirror-wrap pre { 87 | word-wrap: break-word; 88 | white-space: pre-wrap; 89 | word-break: normal; 90 | } 91 | .CodeMirror-wrap .CodeMirror-scroll { 92 | overflow-x: hidden; 93 | } 94 | 95 | .CodeMirror textarea { 96 | outline: none !important; 97 | } 98 | 99 | .CodeMirror pre.CodeMirror-cursor { 100 | z-index: 10; 101 | position: absolute; 102 | visibility: hidden; 103 | border-left: 1px solid black; 104 | border-right: none; 105 | width: 0; 106 | } 107 | .cm-keymap-fat-cursor pre.CodeMirror-cursor { 108 | width: auto; 109 | border: 0; 110 | background: transparent; 111 | background: rgba(0, 200, 0, .4); 112 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); 113 | } 114 | /* Kludge to turn off filter in ie9+, which also accepts rgba */ 115 | .cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) { 116 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 117 | } 118 | .CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {} 119 | .CodeMirror-focused pre.CodeMirror-cursor { 120 | visibility: visible; 121 | } 122 | 123 | div.CodeMirror-selected { background: #d9d9d9; } 124 | .CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; } 125 | 126 | .CodeMirror-searching { 127 | background: #ffa; 128 | background: rgba(255, 255, 0, .4); 129 | } 130 | 131 | /* Default theme */ 132 | 133 | .cm-s-default span.cm-keyword {color: #708;} 134 | .cm-s-default span.cm-atom {color: #219;} 135 | .cm-s-default span.cm-number {color: #164;} 136 | .cm-s-default span.cm-def {color: #00f;} 137 | .cm-s-default span.cm-variable {color: black;} 138 | .cm-s-default span.cm-variable-2 {color: #05a;} 139 | .cm-s-default span.cm-variable-3 {color: #085;} 140 | .cm-s-default span.cm-property {color: black;} 141 | .cm-s-default span.cm-operator {color: black;} 142 | .cm-s-default span.cm-comment {color: #a50;} 143 | .cm-s-default span.cm-string {color: #a11;} 144 | .cm-s-default span.cm-string-2 {color: #f50;} 145 | .cm-s-default span.cm-meta {color: #555;} 146 | .cm-s-default span.cm-error {color: #f00;} 147 | .cm-s-default span.cm-qualifier {color: #555;} 148 | .cm-s-default span.cm-builtin {color: #30a;} 149 | .cm-s-default span.cm-bracket {color: #997;} 150 | .cm-s-default span.cm-tag {color: #170;} 151 | .cm-s-default span.cm-attribute {color: #00c;} 152 | .cm-s-default span.cm-header {color: blue;} 153 | .cm-s-default span.cm-quote {color: #090;} 154 | .cm-s-default span.cm-hr {color: #999;} 155 | .cm-s-default span.cm-link {color: #00c;} 156 | 157 | span.cm-header, span.cm-strong {font-weight: bold;} 158 | span.cm-em {font-style: italic;} 159 | span.cm-emstrong {font-style: italic; font-weight: bold;} 160 | span.cm-link {text-decoration: underline;} 161 | 162 | span.cm-invalidchar {color: #f00;} 163 | 164 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 165 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 166 | 167 | @media print { 168 | 169 | /* Hide the cursor when printing */ 170 | .CodeMirror pre.CodeMirror-cursor { 171 | visibility: hidden; 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /WebContent/viewer/jsoneditor/jsoneditor.min.css: -------------------------------------------------------------------------------- 1 | .jsoneditor .field,.jsoneditor .readonly,.jsoneditor .value{border:1px solid transparent;min-height:16px;min-width:32px;padding:2px;margin:1px;word-wrap:break-word;float:left}.jsoneditor .field p,.jsoneditor .value p{margin:0}.jsoneditor .value{word-break:break-word}.jsoneditor .readonly{min-width:16px;color:gray}.jsoneditor .empty{border-color:#d3d3d3;border-style:dashed;border-radius:2px}.jsoneditor .field.empty{background-image:url(img/jsoneditor-icons.png);background-position:0 -144px}.jsoneditor .value.empty{background-image:url(img/jsoneditor-icons.png);background-position:-48px -144px}.jsoneditor .value.url{color:green;text-decoration:underline}.jsoneditor a.value.url:focus,.jsoneditor a.value.url:hover{color:red}.jsoneditor .separator{padding:3px 0;vertical-align:top;color:gray}.jsoneditor .field.highlight,.jsoneditor .field[contenteditable=true]:focus,.jsoneditor .field[contenteditable=true]:hover,.jsoneditor .value.highlight,.jsoneditor .value[contenteditable=true]:focus,.jsoneditor .value[contenteditable=true]:hover{background-color:#FFFFAB;border:1px solid #ff0;border-radius:2px}.jsoneditor .field.highlight-active,.jsoneditor .field.highlight-active:focus,.jsoneditor .field.highlight-active:hover,.jsoneditor .value.highlight-active,.jsoneditor .value.highlight-active:focus,.jsoneditor .value.highlight-active:hover{background-color:#fe0;border:1px solid #ffc700;border-radius:2px}.jsoneditor div.tree button{width:24px;height:24px;padding:0;margin:0;border:none;cursor:pointer;background:url(img/jsoneditor-icons.png)}.jsoneditor div.tree button.collapsed{background-position:0 -48px}.jsoneditor div.tree button.expanded{background-position:0 -72px}.jsoneditor div.tree button.contextmenu{background-position:-48px -72px}.jsoneditor div.tree button.contextmenu.selected,.jsoneditor div.tree button.contextmenu:focus,.jsoneditor div.tree button.contextmenu:hover{background-position:-48px -48px}.jsoneditor div.tree :focus{outline:0}.jsoneditor div.tree button:focus{background-color:#f5f5f5;outline:#e5e5e5 solid 1px}.jsoneditor div.tree button.invisible{visibility:hidden;background:0 0}.jsoneditor{color:#1A1A1A;border:1px solid #97B0F8;box-sizing:border-box;width:100%;height:100%;overflow:auto;position:relative;padding:0;line-height:100%}.jsoneditor,.jsoneditor div.outer{-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.jsoneditor div.tree table.tree{border-collapse:collapse;border-spacing:0;width:100%;margin:0}.jsoneditor div.outer{width:100%;height:100%;margin:-35px 0 0;padding:35px 0 0;box-sizing:border-box;overflow:hidden}.jsoneditor div.tree{width:100%;height:100%;position:relative;overflow:auto}.jsoneditor textarea.text{width:100%;height:100%;margin:0;box-sizing:border-box;border:none;background-color:#fff;resize:none}.jsoneditor .menu,.jsoneditor textarea.text{-moz-box-sizing:border-box;-webkit-box-sizing:border-box}.jsoneditor tr.highlight{background-color:#FFFFAB}.jsoneditor div.tree button.dragarea{background:url(img/jsoneditor-icons.png)-72px -72px;cursor:move}.jsoneditor div.tree button.dragarea:focus,.jsoneditor div.tree button.dragarea:hover{background-position:-72px -48px}.jsoneditor td,.jsoneditor th,.jsoneditor tr{padding:0;margin:0}.jsoneditor td,.jsoneditor td.tree{vertical-align:top}.jsoneditor .field,.jsoneditor .value,.jsoneditor td,.jsoneditor textarea,.jsoneditor th{font-family:droid sans mono,consolas,monospace,courier new,courier,sans-serif;font-size:10pt;color:#1A1A1A}.jsoneditor-contextmenu{position:absolute;z-index:99999}.jsoneditor-contextmenu ul{position:relative;left:0;top:0;width:124px;background:#fff;border:1px solid #d3d3d3;box-shadow:2px 2px 12px rgba(128,128,128,.3);list-style:none;margin:0;padding:0}.jsoneditor-contextmenu ul li button{padding:0;margin:0;width:124px;height:24px;border:none;cursor:pointer;color:#4d4d4d;background:0 0;line-height:26px;text-align:left}.jsoneditor-contextmenu ul li button::-moz-focus-inner{padding:0;border:0}.jsoneditor-contextmenu ul li button:focus,.jsoneditor-contextmenu ul li button:hover{color:#1a1a1a;background-color:#f5f5f5;outline:0}.jsoneditor-contextmenu ul li button.default{width:92px}.jsoneditor-contextmenu ul li button.expand{float:right;width:32px;height:24px;border-left:1px solid #e5e5e5}.jsoneditor-contextmenu div.icon{float:left;width:24px;height:24px;border:none;padding:0;margin:0;background-image:url(img/jsoneditor-icons.png)}.jsoneditor-contextmenu ul li button div.expand{float:right;width:24px;height:24px;padding:0;margin:0 4px 0 0;background:url(img/jsoneditor-icons.png)0 -72px;opacity:.4}.jsoneditor-contextmenu ul li button.expand:focus div.expand,.jsoneditor-contextmenu ul li button.expand:hover div.expand,.jsoneditor-contextmenu ul li button:focus div.expand,.jsoneditor-contextmenu ul li button:hover div.expand,.jsoneditor-contextmenu ul li.selected div.expand{opacity:1}.jsoneditor-contextmenu .separator{height:0;border-top:1px solid #e5e5e5;padding-top:5px;margin-top:5px}.jsoneditor-contextmenu button.remove>.icon{background-position:-24px -24px}.jsoneditor-contextmenu button.remove:focus>.icon,.jsoneditor-contextmenu button.remove:hover>.icon{background-position:-24px 0}.jsoneditor-contextmenu button.append>.icon{background-position:0 -24px}.jsoneditor-contextmenu button.append:focus>.icon,.jsoneditor-contextmenu button.append:hover>.icon{background-position:0 0}.jsoneditor-contextmenu button.insert>.icon{background-position:0 -24px}.jsoneditor-contextmenu button.insert:focus>.icon,.jsoneditor-contextmenu button.insert:hover>.icon{background-position:0 0}.jsoneditor-contextmenu button.duplicate>.icon{background-position:-48px -24px}.jsoneditor-contextmenu button.duplicate:focus>.icon,.jsoneditor-contextmenu button.duplicate:hover>.icon{background-position:-48px 0}.jsoneditor-contextmenu button.sort-asc>.icon{background-position:-168px -24px}.jsoneditor-contextmenu button.sort-asc:focus>.icon,.jsoneditor-contextmenu button.sort-asc:hover>.icon{background-position:-168px 0}.jsoneditor-contextmenu button.sort-desc>.icon{background-position:-192px -24px}.jsoneditor-contextmenu button.sort-desc:focus>.icon,.jsoneditor-contextmenu button.sort-desc:hover>.icon{background-position:-192px 0}.jsoneditor-contextmenu ul li .selected{background-color:#D5DDF6}.jsoneditor-contextmenu ul li{overflow:hidden}.jsoneditor-contextmenu ul li ul{display:none;position:relative;left:-10px;top:0;border:none;box-shadow:inset 0 0 10px rgba(128,128,128,.5);padding:0 10px;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.jsoneditor-contextmenu ul li ul li button{padding-left:24px}.jsoneditor-contextmenu ul li ul li button:focus,.jsoneditor-contextmenu ul li ul li button:hover{background-color:#f5f5f5}.jsoneditor-contextmenu button.type-string>.icon{background-position:-144px -24px}.jsoneditor-contextmenu button.type-string.selected>.icon,.jsoneditor-contextmenu button.type-string:focus>.icon,.jsoneditor-contextmenu button.type-string:hover>.icon{background-position:-144px 0}.jsoneditor-contextmenu button.type-auto>.icon{background-position:-120px -24px}.jsoneditor-contextmenu button.type-auto.selected>.icon,.jsoneditor-contextmenu button.type-auto:focus>.icon,.jsoneditor-contextmenu button.type-auto:hover>.icon{background-position:-120px 0}.jsoneditor-contextmenu button.type-object>.icon{background-position:-72px -24px}.jsoneditor-contextmenu button.type-object.selected>.icon,.jsoneditor-contextmenu button.type-object:focus>.icon,.jsoneditor-contextmenu button.type-object:hover>.icon{background-position:-72px 0}.jsoneditor-contextmenu button.type-array>.icon{background-position:-96px -24px}.jsoneditor-contextmenu button.type-array.selected>.icon,.jsoneditor-contextmenu button.type-array:focus>.icon,.jsoneditor-contextmenu button.type-array:hover>.icon{background-position:-96px 0}.jsoneditor-contextmenu button.type-modes>.icon{background-image:none;width:6px}.jsoneditor .menu{width:100%;height:35px;padding:2px;margin:0;overflow:hidden;box-sizing:border-box;color:#1A1A1A;background-color:#D5DDF6;border-bottom:1px solid #97B0F8}.jsoneditor .menu button{width:26px;height:26px;margin:2px;padding:0;border-radius:2px;border:1px solid #aec0f8;background:url(img/jsoneditor-icons.png)#e3eaf6;color:#4D4D4D;opacity:.8;font-family:arial,sans-serif;font-size:10pt;float:left}.jsoneditor .menu button:hover{background-color:#f0f2f5}.jsoneditor .menu button:active,.jsoneditor .menu button:focus{background-color:#fff}.jsoneditor .menu button:disabled{background-color:#e3eaf6}.jsoneditor .menu button.collapse-all{background-position:0 -96px}.jsoneditor .menu button.expand-all{background-position:0 -120px}.jsoneditor .menu button.undo{background-position:-24px -96px}.jsoneditor .menu button.undo:disabled{background-position:-24px -120px}.jsoneditor .menu button.redo{background-position:-48px -96px}.jsoneditor .menu button.redo:disabled{background-position:-48px -120px}.jsoneditor .menu button.compact{background-position:-72px -96px}.jsoneditor .menu button.format{background-position:-72px -120px}.jsoneditor .menu button.modes{background-image:none;width:auto;padding-left:6px;padding-right:6px}.jsoneditor .menu button.separator{margin-left:10px}.jsoneditor .menu a{font-family:arial,sans-serif;font-size:10pt;color:#97B0F8;vertical-align:middle}.jsoneditor .menu a:hover{color:red}.jsoneditor .menu a.poweredBy{font-size:8pt;position:absolute;right:0;top:0;padding:10px}.jsoneditor .search .results,.jsoneditor .search input{font-family:arial,sans-serif;font-size:10pt;color:#1A1A1A;background:0 0}.jsoneditor .search{position:absolute;right:2px;top:2px}.jsoneditor .search .frame{border:1px solid #97B0F8;background-color:#fff;padding:0 2px;margin:0}.jsoneditor .search .frame table{border-collapse:collapse}.jsoneditor .search input{width:120px;border:none;outline:0;margin:1px}.jsoneditor .search .results{color:#4d4d4d;padding-right:5px;line-height:24px}.jsoneditor .search button{width:16px;height:24px;padding:0;margin:0;border:none;background:url(img/jsoneditor-icons.png);vertical-align:top}.jsoneditor .search button:hover{background-color:transparent}.jsoneditor .search button.refresh{width:18px;background-position:-99px -73px}.jsoneditor .search button.next{cursor:pointer;background-position:-124px -73px}.jsoneditor .search button.next:hover{background-position:-124px -49px}.jsoneditor .search button.previous{cursor:pointer;background-position:-148px -73px;margin-right:2px}.jsoneditor .search button.previous:hover{background-position:-148px -49px} -------------------------------------------------------------------------------- /WebContent/content.js: -------------------------------------------------------------------------------- 1 | var port = chrome.runtime.connect(), collapsers, options, jsonObject; 2 | 3 | function displayError(error, loc, offset) { 4 | var link = document.createElement("link"), pre = document.body.firstChild.firstChild, text = pre.textContent.substring(offset), start = 0, ranges = [], idx = 0, end, range = document 5 | .createRange(), imgError = document.createElement("img"), content = document.createElement("div"), errorPosition = document.createElement("span"), container = document 6 | .createElement("div"), closeButton = document.createElement("div"); 7 | link.rel = "stylesheet"; 8 | link.type = "text/css"; 9 | link.href = chrome.runtime.getURL("content_error.css"); 10 | document.head.appendChild(link); 11 | while (idx != -1) { 12 | idx = text.indexOf("\n", start); 13 | ranges.push(start); 14 | start = idx + 1; 15 | } 16 | start = ranges[loc.first_line - 1] + loc.first_column + offset; 17 | end = ranges[loc.last_line - 1] + loc.last_column + offset; 18 | range.setStart(pre, start); 19 | if (start == end - 1) 20 | range.setEnd(pre, start); 21 | else 22 | range.setEnd(pre, end); 23 | errorPosition.className = "error-position"; 24 | errorPosition.id = "error-position"; 25 | range.surroundContents(errorPosition); 26 | imgError.src = chrome.runtime.getURL("error.gif"); 27 | errorPosition.insertBefore(imgError, errorPosition.firstChild); 28 | content.className = "content"; 29 | closeButton.className = "close-error"; 30 | closeButton.onclick = function() { 31 | content.parentElement.removeChild(content); 32 | }; 33 | content.textContent = error; 34 | content.appendChild(closeButton); 35 | container.className = "container"; 36 | container.appendChild(content); 37 | errorPosition.parentNode.insertBefore(container, errorPosition.nextSibling); 38 | location.hash = "error-position"; 39 | history.replaceState({}, "", "#"); 40 | } 41 | 42 | function displayUI(theme, html) { 43 | var statusElement, toolboxElement, expandElement, reduceElement, viewSourceElement, optionsElement, content = ""; 44 | content += ''; 45 | content += ""; 46 | content += html; 47 | document.body.innerHTML = content; 48 | collapsers = document.querySelectorAll("#json .collapsible .collapsible"); 49 | statusElement = document.createElement("div"); 50 | statusElement.className = "status"; 51 | copyPathElement = document.createElement("div"); 52 | copyPathElement.className = "copy-path"; 53 | statusElement.appendChild(copyPathElement); 54 | document.body.appendChild(statusElement); 55 | toolboxElement = document.createElement("div"); 56 | toolboxElement.className = "toolbox"; 57 | expandElement = document.createElement("span"); 58 | expandElement.title = "expand all"; 59 | expandElement.innerText = "+"; 60 | reduceElement = document.createElement("span"); 61 | reduceElement.title = "reduce all"; 62 | reduceElement.innerText = "-"; 63 | viewSourceElement = document.createElement("a"); 64 | viewSourceElement.innerText = "View source"; 65 | viewSourceElement.target = "_blank"; 66 | viewSourceElement.href = "view-source:" + location.href; 67 | optionsElement = document.createElement("img"); 68 | optionsElement.title = "options"; 69 | optionsElement.src = chrome.runtime.getURL("options.png"); 70 | toolboxElement.appendChild(expandElement); 71 | toolboxElement.appendChild(reduceElement); 72 | toolboxElement.appendChild(viewSourceElement); 73 | toolboxElement.appendChild(optionsElement); 74 | document.body.appendChild(toolboxElement); 75 | document.body.addEventListener('click', ontoggle, false); 76 | document.body.addEventListener('mouseover', onmouseMove, false); 77 | document.body.addEventListener('click', onmouseClick, false); 78 | document.body.addEventListener('contextmenu', onContextMenu, false); 79 | expandElement.addEventListener('click', onexpand, false); 80 | reduceElement.addEventListener('click', onreduce, false); 81 | optionsElement.addEventListener("click", function() { 82 | window.open(chrome.runtime.getURL("options.html")); 83 | }, false); 84 | copyPathElement.addEventListener("click", function() { 85 | port.postMessage({ 86 | copyPropertyPath : true, 87 | path : statusElement.innerText 88 | }); 89 | }, false); 90 | } 91 | 92 | function extractData(rawText) { 93 | var tokens, text = rawText.trim(); 94 | 95 | function test(text) { 96 | return ((text.charAt(0) == "[" && text.charAt(text.length - 1) == "]") || (text.charAt(0) == "{" && text.charAt(text.length - 1) == "}")); 97 | } 98 | 99 | if (test(text)) 100 | return { 101 | text : rawText, 102 | offset : 0 103 | }; 104 | tokens = text.match(/^([^\s\(]*)\s*\(([\s\S]*)\)\s*;?$/); 105 | if (tokens && tokens[1] && tokens[2]) { 106 | if (test(tokens[2].trim())) 107 | return { 108 | fnName : tokens[1], 109 | text : tokens[2], 110 | offset : rawText.indexOf(tokens[2]) 111 | }; 112 | } 113 | } 114 | 115 | function processData(data) { 116 | var xhr, jsonText; 117 | 118 | function formatToHTML(fnName, offset) { 119 | if (!jsonText) 120 | return; 121 | port.postMessage({ 122 | jsonToHTML : true, 123 | json : jsonText, 124 | fnName : fnName, 125 | offset : offset 126 | }); 127 | try { 128 | jsonObject = JSON.parse(jsonText); 129 | } catch (e) { 130 | } 131 | } 132 | 133 | if (window == top || options.injectInFrame) 134 | if (options.safeMethod) { 135 | xhr = new XMLHttpRequest(); 136 | xhr.onreadystatechange = function() { 137 | if (this.readyState == 4) { 138 | data = extractData(this.responseText); 139 | if (data) { 140 | jsonText = data.text; 141 | formatToHTML(data.fnName, data.offset); 142 | } 143 | } 144 | }; 145 | xhr.open("GET", document.location.href, true); 146 | xhr.send(null); 147 | } else if (data) { 148 | jsonText = data.text; 149 | formatToHTML(data.fnName, data.offset); 150 | } 151 | } 152 | 153 | function ontoggle(event) { 154 | var collapsed, target = event.target; 155 | if (event.target.className == 'collapser') { 156 | collapsed = target.parentNode.getElementsByClassName('collapsible')[0]; 157 | if (collapsed.parentNode.classList.contains("collapsed")) 158 | collapsed.parentNode.classList.remove("collapsed"); 159 | else 160 | collapsed.parentNode.classList.add("collapsed"); 161 | } 162 | } 163 | 164 | function onexpand() { 165 | Array.prototype.forEach.call(collapsers, function(collapsed) { 166 | if (collapsed.parentNode.classList.contains("collapsed")) 167 | collapsed.parentNode.classList.remove("collapsed"); 168 | }); 169 | } 170 | 171 | function onreduce() { 172 | Array.prototype.forEach.call(collapsers, function(collapsed) { 173 | if (!collapsed.parentNode.classList.contains("collapsed")) 174 | collapsed.parentNode.classList.add("collapsed"); 175 | }); 176 | } 177 | 178 | function getParentLI(element) { 179 | if (element.tagName != "LI") 180 | while (element && element.tagName != "LI") 181 | element = element.parentNode; 182 | if (element && element.tagName == "LI") 183 | return element; 184 | } 185 | 186 | var onmouseMove = (function() { 187 | var hoveredLI; 188 | 189 | function onmouseOut() { 190 | var statusElement = document.querySelector(".status"); 191 | if (hoveredLI) { 192 | hoveredLI.firstChild.classList.remove("hovered"); 193 | hoveredLI = null; 194 | statusElement.innerText = ""; 195 | } 196 | } 197 | 198 | return function(event) { 199 | var str = "", statusElement = document.querySelector(".status"); 200 | element = getParentLI(event.target); 201 | if (element) { 202 | if (hoveredLI) 203 | hoveredLI.firstChild.classList.remove("hovered"); 204 | hoveredLI = element; 205 | element.firstChild.classList.add("hovered"); 206 | do { 207 | if (element.parentNode.classList.contains("array")) { 208 | var index = [].indexOf.call(element.parentNode.children, element); 209 | str = "[" + index + "]" + str; 210 | } 211 | if (element.parentNode.classList.contains("obj")) { 212 | str = "." + element.firstChild.firstChild.innerText + str; 213 | } 214 | element = element.parentNode.parentNode.parentNode; 215 | } while (element.tagName == "LI"); 216 | if (str.charAt(0) == '.') 217 | str = str.substring(1); 218 | statusElement.innerText = str; 219 | return; 220 | } 221 | onmouseOut(); 222 | }; 223 | })(); 224 | 225 | var selectedLI; 226 | 227 | function onmouseClick() { 228 | if (selectedLI) 229 | selectedLI.firstChild.classList.remove("selected"); 230 | selectedLI = getParentLI(event.target); 231 | if (selectedLI) { 232 | selectedLI.firstChild.classList.add("selected"); 233 | } 234 | } 235 | 236 | function onContextMenu() { 237 | var currentLI, statusElement, selection = "", i, value; 238 | currentLI = getParentLI(event.target); 239 | statusElement = document.querySelector(".status"); 240 | if (currentLI) { 241 | if (Array.isArray(jsonObject)) 242 | value = eval("(jsonObject" + statusElement.innerText + ")"); 243 | else 244 | value = eval("(jsonObject." + statusElement.innerText + ")"); 245 | port.postMessage({ 246 | copyPropertyPath : true, 247 | path : statusElement.innerText, 248 | value : typeof value == "object" ? JSON.stringify(value) : value 249 | }); 250 | } 251 | } 252 | 253 | function init(data) { 254 | port.onMessage.addListener(function(msg) { 255 | if (msg.oninit) { 256 | options = msg.options; 257 | processData(data); 258 | } 259 | if (msg.onjsonToHTML) 260 | if (msg.html) { 261 | displayUI(msg.theme, msg.html); 262 | } else if (msg.json) 263 | port.postMessage({ 264 | getError : true, 265 | json : json, 266 | fnName : fnName 267 | }); 268 | if (msg.ongetError) { 269 | displayError(msg.error, msg.loc, msg.offset); 270 | } 271 | }); 272 | port.postMessage({ 273 | init : true 274 | }); 275 | } 276 | 277 | function load() { 278 | var child, data; 279 | if (document.body && (document.body.childNodes[0] && document.body.childNodes[0].tagName == "PRE" || document.body.children.length == 0)) { 280 | child = document.body.children.length ? document.body.childNodes[0] : document.body; 281 | data = extractData(child.innerText); 282 | if (data) 283 | init(data); 284 | } 285 | } 286 | 287 | load(); 288 | -------------------------------------------------------------------------------- /WebContent/workerJSONLint.js: -------------------------------------------------------------------------------- 1 | /* Jison generated parser */ 2 | var jsonlint = (function(){ 3 | var parser = {trace: function trace() { }, 4 | yy: {}, 5 | symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, 6 | terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, 7 | productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], 8 | performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { 9 | 10 | var $0 = $$.length - 1; 11 | switch (yystate) { 12 | case 1:this.$ = yytext; 13 | break; 14 | case 2:this.$ = Number(yytext); 15 | break; 16 | case 3:this.$ = null; 17 | break; 18 | case 4:this.$ = true; 19 | break; 20 | case 5:this.$ = false; 21 | break; 22 | case 6:return this.$ = $$[$0-1]; 23 | break; 24 | case 13:this.$ = {}; 25 | break; 26 | case 14:this.$ = $$[$0-1]; 27 | break; 28 | case 15:this.$ = [$$[$0-2], $$[$0]]; 29 | break; 30 | case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; 31 | break; 32 | case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; 33 | break; 34 | case 18:this.$ = []; 35 | break; 36 | case 19:this.$ = $$[$0-1]; 37 | break; 38 | case 20:this.$ = [$$[$0]]; 39 | break; 40 | case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); 41 | break; 42 | } 43 | }, 44 | table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], 45 | defaultActions: {16:[2,6]}, 46 | parseError: function parseError(str, hash) { 47 | throw new Error(str); 48 | }, 49 | parse: function parse(input) { 50 | var self = this, 51 | stack = [0], 52 | vstack = [null], // semantic value stack 53 | lstack = [], // location stack 54 | table = this.table, 55 | yytext = '', 56 | yylineno = 0, 57 | yyleng = 0, 58 | recovering = 0, 59 | TERROR = 2, 60 | EOF = 1; 61 | 62 | // this.reductionCount = this.shiftCount = 0; 63 | 64 | this.lexer.setInput(input); 65 | this.lexer.yy = this.yy; 66 | this.yy.lexer = this.lexer; 67 | if (typeof this.lexer.yylloc == 'undefined') 68 | this.lexer.yylloc = {}; 69 | var yyloc = this.lexer.yylloc; 70 | lstack.push(yyloc); 71 | 72 | if (typeof this.yy.parseError === 'function') 73 | this.parseError = this.yy.parseError; 74 | 75 | function popStack (n) { 76 | stack.length = stack.length - 2*n; 77 | vstack.length = vstack.length - n; 78 | lstack.length = lstack.length - n; 79 | } 80 | 81 | function lex() { 82 | var token; 83 | token = self.lexer.lex() || 1; // $end = 1 84 | // if token isn't its numeric value, convert 85 | if (typeof token !== 'number') { 86 | token = self.symbols_[token] || token; 87 | } 88 | return token; 89 | }; 90 | 91 | var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; 92 | while (true) { 93 | // retreive state number from top of stack 94 | state = stack[stack.length-1]; 95 | 96 | // use default actions if available 97 | if (this.defaultActions[state]) { 98 | action = this.defaultActions[state]; 99 | } else { 100 | if (symbol == null) 101 | symbol = lex(); 102 | // read action for current state and first input 103 | action = table[state] && table[state][symbol]; 104 | } 105 | 106 | // handle parse error 107 | if (typeof action === 'undefined' || !action.length || !action[0]) { 108 | 109 | if (!recovering) { 110 | // Report error 111 | expected = []; 112 | for (p in table[state]) if (this.terminals_[p] && p > 2) { 113 | expected.push("'"+this.terminals_[p]+"'"); 114 | } 115 | var errStr = ''; 116 | if (this.lexer.showPosition) { 117 | errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', '); 118 | } else { 119 | errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + 120 | (symbol == 1 /* EOF */ ? "end of input" : 121 | ("'"+(this.terminals_[symbol] || symbol)+"'")); 122 | } 123 | this.parseError(errStr, 124 | {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); 125 | } 126 | 127 | // just recovered from another error 128 | if (recovering == 3) { 129 | if (symbol == EOF) { 130 | throw new Error(errStr || 'Parsing halted.'); 131 | } 132 | 133 | // discard current lookahead and grab another 134 | yyleng = this.lexer.yyleng; 135 | yytext = this.lexer.yytext; 136 | yylineno = this.lexer.yylineno; 137 | yyloc = this.lexer.yylloc; 138 | symbol = lex(); 139 | } 140 | 141 | // try to recover from error 142 | while (1) { 143 | // check for error recovery rule in this state 144 | if ((TERROR.toString()) in table[state]) { 145 | break; 146 | } 147 | if (state == 0) { 148 | throw new Error(errStr || 'Parsing halted.'); 149 | } 150 | popStack(1); 151 | state = stack[stack.length-1]; 152 | } 153 | 154 | preErrorSymbol = symbol; // save the lookahead token 155 | symbol = TERROR; // insert generic error symbol as new lookahead 156 | state = stack[stack.length-1]; 157 | action = table[state] && table[state][TERROR]; 158 | recovering = 3; // allow 3 real symbols to be shifted before reporting a new error 159 | } 160 | 161 | // this shouldn't happen, unless resolve defaults are off 162 | if (action[0] instanceof Array && action.length > 1) { 163 | throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); 164 | } 165 | 166 | switch (action[0]) { 167 | 168 | case 1: // shift 169 | // this.shiftCount++; 170 | 171 | stack.push(symbol); 172 | vstack.push(this.lexer.yytext); 173 | lstack.push(this.lexer.yylloc); 174 | stack.push(action[1]); // push state 175 | symbol = null; 176 | if (!preErrorSymbol) { // normal execution/no error 177 | yyleng = this.lexer.yyleng; 178 | yytext = this.lexer.yytext; 179 | yylineno = this.lexer.yylineno; 180 | yyloc = this.lexer.yylloc; 181 | if (recovering > 0) 182 | recovering--; 183 | } else { // error just occurred, resume old lookahead f/ before error 184 | symbol = preErrorSymbol; 185 | preErrorSymbol = null; 186 | } 187 | break; 188 | 189 | case 2: // reduce 190 | // this.reductionCount++; 191 | 192 | len = this.productions_[action[1]][1]; 193 | 194 | // perform semantic action 195 | yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 196 | // default location, uses first token for firsts, last for lasts 197 | yyval._$ = { 198 | first_line: lstack[lstack.length-(len||1)].first_line, 199 | last_line: lstack[lstack.length-1].last_line, 200 | first_column: lstack[lstack.length-(len||1)].first_column, 201 | last_column: lstack[lstack.length-1].last_column 202 | }; 203 | r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); 204 | 205 | if (typeof r !== 'undefined') { 206 | return r; 207 | } 208 | 209 | // pop off stack 210 | if (len) { 211 | stack = stack.slice(0,-1*len*2); 212 | vstack = vstack.slice(0, -1*len); 213 | lstack = lstack.slice(0, -1*len); 214 | } 215 | 216 | stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) 217 | vstack.push(yyval.$); 218 | lstack.push(yyval._$); 219 | // goto new state = table[STATE][NONTERMINAL] 220 | newState = table[stack[stack.length-2]][stack[stack.length-1]]; 221 | stack.push(newState); 222 | break; 223 | 224 | case 3: // accept 225 | return true; 226 | } 227 | 228 | } 229 | 230 | return true; 231 | }};/* Jison generated lexer */ 232 | var lexer = (function(){var lexer = ({EOF:1, 233 | parseError:function parseError(str, hash) { 234 | if (this.yy.parseError) { 235 | this.yy.parseError(str, hash); 236 | } else { 237 | throw new Error(str); 238 | } 239 | }, 240 | setInput:function (input) { 241 | this._input = input; 242 | this._more = this._less = this.done = false; 243 | this.yylineno = this.yyleng = 0; 244 | this.yytext = this.matched = this.match = ''; 245 | this.conditionStack = ['INITIAL']; 246 | this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; 247 | return this; 248 | }, 249 | input:function () { 250 | var ch = this._input[0]; 251 | this.yytext+=ch; 252 | this.yyleng++; 253 | this.match+=ch; 254 | this.matched+=ch; 255 | var lines = ch.match(/\n/); 256 | if (lines) this.yylineno++; 257 | this._input = this._input.slice(1); 258 | return ch; 259 | }, 260 | unput:function (ch) { 261 | this._input = ch + this._input; 262 | return this; 263 | }, 264 | more:function () { 265 | this._more = true; 266 | return this; 267 | }, 268 | pastInput:function () { 269 | var past = this.matched.substr(0, this.matched.length - this.match.length); 270 | return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); 271 | }, 272 | upcomingInput:function () { 273 | var next = this.match; 274 | if (next.length < 20) { 275 | next += this._input.substr(0, 20-next.length); 276 | } 277 | return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); 278 | }, 279 | showPosition:function () { 280 | var pre = this.pastInput(); 281 | var c = new Array(pre.length + 1).join("-"); 282 | return pre + this.upcomingInput() + "\n" + c+"^"; 283 | }, 284 | next:function () { 285 | if (this.done) { 286 | return this.EOF; 287 | } 288 | if (!this._input) this.done = true; 289 | 290 | var token, 291 | match, 292 | col, 293 | lines; 294 | if (!this._more) { 295 | this.yytext = ''; 296 | this.match = ''; 297 | } 298 | var rules = this._currentRules(); 299 | for (var i=0;i < rules.length; i++) { 300 | match = this._input.match(this.rules[rules[i]]); 301 | if (match) { 302 | lines = match[0].match(/\n.*/g); 303 | if (lines) this.yylineno += lines.length; 304 | this.yylloc = {first_line: this.yylloc.last_line, 305 | last_line: this.yylineno+1, 306 | first_column: this.yylloc.last_column, 307 | last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}; 308 | this.yytext += match[0]; 309 | this.match += match[0]; 310 | this.matches = match; 311 | this.yyleng = this.yytext.length; 312 | this._more = false; 313 | this._input = this._input.slice(match[0].length); 314 | this.matched += match[0]; 315 | token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); 316 | if (token) return token; 317 | else return; 318 | } 319 | } 320 | if (this._input === "") { 321 | return this.EOF; 322 | } else { 323 | this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), 324 | {text: "", token: null, line: this.yylineno}); 325 | } 326 | }, 327 | lex:function lex() { 328 | var r = this.next(); 329 | if (typeof r !== 'undefined') { 330 | return r; 331 | } else { 332 | return this.lex(); 333 | } 334 | }, 335 | begin:function begin(condition) { 336 | this.conditionStack.push(condition); 337 | }, 338 | popState:function popState() { 339 | return this.conditionStack.pop(); 340 | }, 341 | _currentRules:function _currentRules() { 342 | return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; 343 | }}); 344 | lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { 345 | 346 | var YYSTATE=YY_START; 347 | switch($avoiding_name_collisions) { 348 | case 0:/* skip whitespace */ 349 | break; 350 | case 1:return 6; 351 | break; 352 | case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4; 353 | break; 354 | case 3: return 17; 355 | break; 356 | case 4: return 18; 357 | break; 358 | case 5:return 23; 359 | break; 360 | case 6:return 24; 361 | break; 362 | case 7:return 22; 363 | break; 364 | case 8:return 21; 365 | break; 366 | case 9:return 10; 367 | break; 368 | case 10:return 11; 369 | break; 370 | case 11:return 8; 371 | break; 372 | case 12:return 14; 373 | break; 374 | case 13:return 'INVALID'; 375 | break; 376 | } 377 | }; 378 | lexer.rules = [/^\s+/,/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][-+]?[0-9]+)?\b/,/^"(\\["bfnrt/\\]|\\u[a-fA-F0-9]{4}|[^\0-\x09\x0a-\x1f"\\])*"/,/^\{/,/^\}/,/^\[/,/^\]/,/^,/,/^:/,/^true\b/,/^false\b/,/^null\b/,/^$/,/^./]; 379 | lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}};return lexer;})() 380 | parser.lexer = lexer; 381 | return parser; 382 | })(); 383 | if (typeof require !== 'undefined' && typeof exports !== 'undefined') { 384 | exports.parser = jsonlint; 385 | exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); } 386 | exports.main = function commonjsMain(args) { 387 | if (!args[1]) 388 | throw new Error('Usage: '+args[0]+' FILE'); 389 | if (typeof process !== 'undefined') { 390 | var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); 391 | } else { 392 | var cwd = require("file").path(require("file").cwd()); 393 | var source = cwd.join(args[1]).read({charset: "utf-8"}); 394 | } 395 | return exports.parser.parse(source); 396 | } 397 | if (typeof module !== 'undefined' && require.main === module) { 398 | exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); 399 | } 400 | } 401 | 402 | addEventListener("message", function(event) { 403 | var errorMessage; 404 | try { 405 | jsonlint.parse(event.data); 406 | } catch (errorMessage) { 407 | postMessage(JSON.stringify({error: errorMessage.toString(), loc: jsonlint.lexer.yylloc})); 408 | } 409 | }, false); -------------------------------------------------------------------------------- /WebContent/codemirror/css.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode("css", function(config) { 2 | var indentUnit = config.indentUnit, type; 3 | 4 | var atMediaTypes = keySet([ 5 | "all", "aural", "braille", "handheld", "print", "projection", "screen", 6 | "tty", "tv", "embossed" 7 | ]); 8 | 9 | var atMediaFeatures = keySet([ 10 | "width", "min-width", "max-width", "height", "min-height", "max-height", 11 | "device-width", "min-device-width", "max-device-width", "device-height", 12 | "min-device-height", "max-device-height", "aspect-ratio", 13 | "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", 14 | "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", 15 | "max-color", "color-index", "min-color-index", "max-color-index", 16 | "monochrome", "min-monochrome", "max-monochrome", "resolution", 17 | "min-resolution", "max-resolution", "scan", "grid" 18 | ]); 19 | 20 | var propertyKeywords = keySet([ 21 | "align-content", "align-items", "align-self", "alignment-adjust", 22 | "alignment-baseline", "anchor-point", "animation", "animation-delay", 23 | "animation-direction", "animation-duration", "animation-iteration-count", 24 | "animation-name", "animation-play-state", "animation-timing-function", 25 | "appearance", "azimuth", "backface-visibility", "background", 26 | "background-attachment", "background-clip", "background-color", 27 | "background-image", "background-origin", "background-position", 28 | "background-repeat", "background-size", "baseline-shift", "binding", 29 | "bleed", "bookmark-label", "bookmark-level", "bookmark-state", 30 | "bookmark-target", "border", "border-bottom", "border-bottom-color", 31 | "border-bottom-left-radius", "border-bottom-right-radius", 32 | "border-bottom-style", "border-bottom-width", "border-collapse", 33 | "border-color", "border-image", "border-image-outset", 34 | "border-image-repeat", "border-image-slice", "border-image-source", 35 | "border-image-width", "border-left", "border-left-color", 36 | "border-left-style", "border-left-width", "border-radius", "border-right", 37 | "border-right-color", "border-right-style", "border-right-width", 38 | "border-spacing", "border-style", "border-top", "border-top-color", 39 | "border-top-left-radius", "border-top-right-radius", "border-top-style", 40 | "border-top-width", "border-width", "bottom", "box-decoration-break", 41 | "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", 42 | "caption-side", "clear", "clip", "color", "color-profile", "column-count", 43 | "column-fill", "column-gap", "column-rule", "column-rule-color", 44 | "column-rule-style", "column-rule-width", "column-span", "column-width", 45 | "columns", "content", "counter-increment", "counter-reset", "crop", "cue", 46 | "cue-after", "cue-before", "cursor", "direction", "display", 47 | "dominant-baseline", "drop-initial-after-adjust", 48 | "drop-initial-after-align", "drop-initial-before-adjust", 49 | "drop-initial-before-align", "drop-initial-size", "drop-initial-value", 50 | "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", 51 | "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", 52 | "float", "float-offset", "font", "font-feature-settings", "font-family", 53 | "font-kerning", "font-language-override", "font-size", "font-size-adjust", 54 | "font-stretch", "font-style", "font-synthesis", "font-variant", 55 | "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", 56 | "font-variant-ligatures", "font-variant-numeric", "font-variant-position", 57 | "font-weight", "grid-cell", "grid-column", "grid-column-align", 58 | "grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow", 59 | "grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span", 60 | "grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens", 61 | "icon", "image-orientation", "image-rendering", "image-resolution", 62 | "inline-box-align", "justify-content", "left", "letter-spacing", 63 | "line-break", "line-height", "line-stacking", "line-stacking-ruby", 64 | "line-stacking-shift", "line-stacking-strategy", "list-style", 65 | "list-style-image", "list-style-position", "list-style-type", "margin", 66 | "margin-bottom", "margin-left", "margin-right", "margin-top", 67 | "marker-offset", "marks", "marquee-direction", "marquee-loop", 68 | "marquee-play-count", "marquee-speed", "marquee-style", "max-height", 69 | "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", 70 | "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline", 71 | "outline-color", "outline-offset", "outline-style", "outline-width", 72 | "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", 73 | "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", 74 | "page", "page-break-after", "page-break-before", "page-break-inside", 75 | "page-policy", "pause", "pause-after", "pause-before", "perspective", 76 | "perspective-origin", "pitch", "pitch-range", "play-during", "position", 77 | "presentation-level", "punctuation-trim", "quotes", "rendering-intent", 78 | "resize", "rest", "rest-after", "rest-before", "richness", "right", 79 | "rotation", "rotation-point", "ruby-align", "ruby-overhang", 80 | "ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header", 81 | "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", 82 | "tab-size", "table-layout", "target", "target-name", "target-new", 83 | "target-position", "text-align", "text-align-last", "text-decoration", 84 | "text-decoration-color", "text-decoration-line", "text-decoration-skip", 85 | "text-decoration-style", "text-emphasis", "text-emphasis-color", 86 | "text-emphasis-position", "text-emphasis-style", "text-height", 87 | "text-indent", "text-justify", "text-outline", "text-shadow", 88 | "text-space-collapse", "text-transform", "text-underline-position", 89 | "text-wrap", "top", "transform", "transform-origin", "transform-style", 90 | "transition", "transition-delay", "transition-duration", 91 | "transition-property", "transition-timing-function", "unicode-bidi", 92 | "vertical-align", "visibility", "voice-balance", "voice-duration", 93 | "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", 94 | "voice-volume", "volume", "white-space", "widows", "width", "word-break", 95 | "word-spacing", "word-wrap", "z-index" 96 | ]); 97 | 98 | var colorKeywords = keySet([ 99 | "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", 100 | "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua" 101 | ]); 102 | 103 | var valueKeywords = keySet([ 104 | "above", "absolute", "activeborder", "activecaption", "afar", 105 | "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", 106 | "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", 107 | "arabic-indic", "armenian", "asterisks", "auto", "avoid", "background", 108 | "backwards", "baseline", "below", "bidi-override", "binary", "bengali", 109 | "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", 110 | "both", "bottom", "break-all", "break-word", "button", "button-bevel", 111 | "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", 112 | "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", 113 | "cell", "center", "checkbox", "circle", "cjk-earthly-branch", 114 | "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", 115 | "col-resize", "collapse", "compact", "condensed", "contain", "content", 116 | "content-box", "context-menu", "continuous", "copy", "cover", "crop", 117 | "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", 118 | "decimal-leading-zero", "default", "default-button", "destination-atop", 119 | "destination-in", "destination-out", "destination-over", "devanagari", 120 | "disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted", 121 | "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", 122 | "element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", 123 | "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", 124 | "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", 125 | "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", 126 | "ethiopic-halehame-gez", "ethiopic-halehame-om-et", 127 | "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", 128 | "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", 129 | "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed", 130 | "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", 131 | "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", 132 | "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", 133 | "help", "hidden", "hide", "higher", "highlight", "highlighttext", 134 | "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", 135 | "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", 136 | "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", 137 | "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", 138 | "italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer", 139 | "landscape", "lao", "large", "larger", "left", "level", "lighter", 140 | "line-through", "linear", "lines", "list-item", "listbox", "listitem", 141 | "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", 142 | "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", 143 | "lower-roman", "lowercase", "ltr", "malayalam", "match", 144 | "media-controls-background", "media-current-time-display", 145 | "media-fullscreen-button", "media-mute-button", "media-play-button", 146 | "media-return-to-realtime-button", "media-rewind-button", 147 | "media-seek-back-button", "media-seek-forward-button", "media-slider", 148 | "media-sliderthumb", "media-time-remaining-display", "media-volume-slider", 149 | "media-volume-slider-container", "media-volume-sliderthumb", "medium", 150 | "menu", "menulist", "menulist-button", "menulist-text", 151 | "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", 152 | "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize", 153 | "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", 154 | "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", 155 | "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", 156 | "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", 157 | "outside", "overlay", "overline", "padding", "padding-box", "painted", 158 | "paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait", 159 | "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", 160 | "radio", "read-only", "read-write", "read-write-plaintext-only", "relative", 161 | "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba", 162 | "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", 163 | "s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield", 164 | "searchfield-cancel-button", "searchfield-decoration", 165 | "searchfield-results-button", "searchfield-results-decoration", 166 | "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", 167 | "single", "skip-white-space", "slide", "slider-horizontal", 168 | "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", 169 | "small", "small-caps", "small-caption", "smaller", "solid", "somali", 170 | "source-atop", "source-in", "source-out", "source-over", "space", "square", 171 | "square-button", "start", "static", "status-bar", "stretch", "stroke", 172 | "sub", "subpixel-antialiased", "super", "sw-resize", "table", 173 | "table-caption", "table-cell", "table-column", "table-column-group", 174 | "table-footer-group", "table-header-group", "table-row", "table-row-group", 175 | "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", 176 | "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", 177 | "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", 178 | "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", 179 | "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", 180 | "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", 181 | "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", 182 | "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", 183 | "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", 184 | "window", "windowframe", "windowtext", "x-large", "x-small", "xor", 185 | "xx-large", "xx-small", "yellow" 186 | ]); 187 | 188 | function keySet(array) { var keys = {}; for (var i = 0; i < array.length; ++i) keys[array[i]] = true; return keys; } 189 | function ret(style, tp) {type = tp; return style;} 190 | 191 | function tokenBase(stream, state) { 192 | var ch = stream.next(); 193 | if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());} 194 | else if (ch == "/" && stream.eat("*")) { 195 | state.tokenize = tokenCComment; 196 | return tokenCComment(stream, state); 197 | } 198 | else if (ch == "<" && stream.eat("!")) { 199 | state.tokenize = tokenSGMLComment; 200 | return tokenSGMLComment(stream, state); 201 | } 202 | else if (ch == "=") ret(null, "compare"); 203 | else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); 204 | else if (ch == "\"" || ch == "'") { 205 | state.tokenize = tokenString(ch); 206 | return state.tokenize(stream, state); 207 | } 208 | else if (ch == "#") { 209 | stream.eatWhile(/[\w\\\-]/); 210 | return ret("atom", "hash"); 211 | } 212 | else if (ch == "!") { 213 | stream.match(/^\s*\w*/); 214 | return ret("keyword", "important"); 215 | } 216 | else if (/\d/.test(ch)) { 217 | stream.eatWhile(/[\w.%]/); 218 | return ret("number", "unit"); 219 | } 220 | else if (ch === "-") { 221 | if (/\d/.test(stream.peek())) { 222 | stream.eatWhile(/[\w.%]/); 223 | return ret("number", "unit"); 224 | } else if (stream.match(/^[^-]+-/)) { 225 | return ret("meta", type); 226 | } 227 | } 228 | else if (/[,+>*\/]/.test(ch)) { 229 | return ret(null, "select-op"); 230 | } 231 | else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { 232 | return ret("qualifier", type); 233 | } 234 | else if (ch == ":") { 235 | return ret("operator", ch); 236 | } 237 | else if (/[;{}\[\]\(\)]/.test(ch)) { 238 | return ret(null, ch); 239 | } 240 | else { 241 | stream.eatWhile(/[\w\\\-]/); 242 | return ret("property", "variable"); 243 | } 244 | } 245 | 246 | function tokenCComment(stream, state) { 247 | var maybeEnd = false, ch; 248 | while ((ch = stream.next()) != null) { 249 | if (maybeEnd && ch == "/") { 250 | state.tokenize = tokenBase; 251 | break; 252 | } 253 | maybeEnd = (ch == "*"); 254 | } 255 | return ret("comment", "comment"); 256 | } 257 | 258 | function tokenSGMLComment(stream, state) { 259 | var dashes = 0, ch; 260 | while ((ch = stream.next()) != null) { 261 | if (dashes >= 2 && ch == ">") { 262 | state.tokenize = tokenBase; 263 | break; 264 | } 265 | dashes = (ch == "-") ? dashes + 1 : 0; 266 | } 267 | return ret("comment", "comment"); 268 | } 269 | 270 | function tokenString(quote) { 271 | return function(stream, state) { 272 | var escaped = false, ch; 273 | while ((ch = stream.next()) != null) { 274 | if (ch == quote && !escaped) 275 | break; 276 | escaped = !escaped && ch == "\\"; 277 | } 278 | if (!escaped) state.tokenize = tokenBase; 279 | return ret("string", "string"); 280 | }; 281 | } 282 | 283 | return { 284 | startState: function(base) { 285 | return {tokenize: tokenBase, 286 | baseIndent: base || 0, 287 | stack: []}; 288 | }, 289 | 290 | token: function(stream, state) { 291 | 292 | // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50) 293 | // 294 | // rule** or **ruleset: 295 | // A selector + braces combo, or an at-rule. 296 | // 297 | // declaration block: 298 | // A sequence of declarations. 299 | // 300 | // declaration: 301 | // A property + colon + value combo. 302 | // 303 | // property value: 304 | // The entire value of a property. 305 | // 306 | // component value: 307 | // A single piece of a property value. Like the 5px in 308 | // text-shadow: 0 0 5px blue;. Can also refer to things that are 309 | // multiple terms, like the 1-4 terms that make up the background-size 310 | // portion of the background shorthand. 311 | // 312 | // term: 313 | // The basic unit of author-facing CSS, like a single number (5), 314 | // dimension (5px), string ("foo"), or function. Officially defined 315 | // by the CSS 2.1 grammar (look for the 'term' production) 316 | // 317 | // 318 | // simple selector: 319 | // A single atomic selector, like a type selector, an attr selector, a 320 | // class selector, etc. 321 | // 322 | // compound selector: 323 | // One or more simple selectors without a combinator. div.example is 324 | // compound, div > .example is not. 325 | // 326 | // complex selector: 327 | // One or more compound selectors chained with combinators. 328 | // 329 | // combinator: 330 | // The parts of selectors that express relationships. There are four 331 | // currently - the space (descendant combinator), the greater-than 332 | // bracket (child combinator), the plus sign (next sibling combinator), 333 | // and the tilda (following sibling combinator). 334 | // 335 | // sequence of selectors: 336 | // One or more of the named type of selector chained with commas. 337 | 338 | if (stream.eatSpace()) return null; 339 | var style = state.tokenize(stream, state); 340 | 341 | // Changing style returned based on context 342 | var context = state.stack[state.stack.length-1]; 343 | if (style == "property") { 344 | if (context == "propertyValue"){ 345 | if (valueKeywords[stream.current()]) { 346 | style = "string-2"; 347 | } else if (colorKeywords[stream.current()]) { 348 | style = "keyword"; 349 | } else { 350 | style = "variable-2"; 351 | } 352 | } else if (context == "rule") { 353 | if (!propertyKeywords[stream.current()]) { 354 | style += " error"; 355 | } 356 | } else if (!context || context == "@media{") { 357 | style = "tag"; 358 | } else if (context == "@media") { 359 | if (atMediaTypes[stream.current()]) { 360 | style = "attribute"; // Known attribute 361 | } else if (/^(only|not)$/i.test(stream.current())) { 362 | style = "keyword"; 363 | } else if (stream.current().toLowerCase() == "and") { 364 | style = "error"; // "and" is only allowed in @mediaType 365 | } else if (atMediaFeatures[stream.current()]) { 366 | style = "error"; // Known property, should be in @mediaType( 367 | } else { 368 | // Unknown, expecting keyword or attribute, assuming attribute 369 | style = "attribute error"; 370 | } 371 | } else if (context == "@mediaType") { 372 | if (atMediaTypes[stream.current()]) { 373 | style = "attribute"; 374 | } else if (stream.current().toLowerCase() == "and") { 375 | style = "operator"; 376 | } else if (/^(only|not)$/i.test(stream.current())) { 377 | style = "error"; // Only allowed in @media 378 | } else if (atMediaFeatures[stream.current()]) { 379 | style = "error"; // Known property, should be in parentheses 380 | } else { 381 | // Unknown attribute or property, but expecting property (preceded 382 | // by "and"). Should be in parentheses 383 | style = "error"; 384 | } 385 | } else if (context == "@mediaType(") { 386 | if (propertyKeywords[stream.current()]) { 387 | // do nothing, remains "property" 388 | } else if (atMediaTypes[stream.current()]) { 389 | style = "error"; // Known property, should be in parentheses 390 | } else if (stream.current().toLowerCase() == "and") { 391 | style = "operator"; 392 | } else if (/^(only|not)$/i.test(stream.current())) { 393 | style = "error"; // Only allowed in @media 394 | } else { 395 | style += " error"; 396 | } 397 | } else { 398 | style = "error"; 399 | } 400 | } else if (style == "atom") { 401 | if(!context || context == "@media{") { 402 | style = "builtin"; 403 | } else if (context == "propertyValue") { 404 | if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { 405 | style += " error"; 406 | } 407 | } else { 408 | style = "error"; 409 | } 410 | } else if (context == "@media" && type == "{") { 411 | style = "error"; 412 | } 413 | 414 | // Push/pop context stack 415 | if (type == "{") { 416 | if (context == "@media" || context == "@mediaType") { 417 | state.stack.pop(); 418 | state.stack[state.stack.length-1] = "@media{"; 419 | } 420 | else state.stack.push("rule"); 421 | } 422 | else if (type == "}") { 423 | state.stack.pop(); 424 | if (context == "propertyValue") state.stack.pop(); 425 | } 426 | else if (type == "@media") state.stack.push("@media"); 427 | else if (context == "@media" && /\b(keyword|attribute)\b/.test(style)) 428 | state.stack.push("@mediaType"); 429 | else if (context == "@mediaType" && stream.current() == ",") state.stack.pop(); 430 | else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType("); 431 | else if (context == "@mediaType(" && type == ")") state.stack.pop(); 432 | else if (context == "rule" && type == ":") state.stack.push("propertyValue"); 433 | else if (context == "propertyValue" && type == ";") state.stack.pop(); 434 | return style; 435 | }, 436 | 437 | indent: function(state, textAfter) { 438 | var n = state.stack.length; 439 | if (/^\}/.test(textAfter)) 440 | n -= state.stack[state.stack.length-1] == "propertyValue" ? 2 : 1; 441 | return state.baseIndent + n * indentUnit; 442 | }, 443 | 444 | electricChars: "}" 445 | }; 446 | }); 447 | 448 | CodeMirror.defineMIME("text/css", "css"); 449 | --------------------------------------------------------------------------------