Merge pull request #103 from tophf/editor-theme
Editor: option to select CodeMirror CSS theme
This commit is contained in:
commit
b6444c86ec
|
@ -96,10 +96,18 @@
|
|||
"message": "Tab size",
|
||||
"description": "Label for the text box controlling tab size option for the style editor."
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Theme",
|
||||
"description": "Label for the style editor's CSS theme."
|
||||
},
|
||||
"dbError": {
|
||||
"message": "An error has occurred using the Stylish database. Would you like to visit a web page with possible solutions?",
|
||||
"description": "Prompt when a DB error is encountered"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "default",
|
||||
"description": "Default CodeMirror CSS theme option on the edit style page"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Delete",
|
||||
"description": "Label for the button to delete a style"
|
||||
|
|
23
apply.js
23
apply.js
|
@ -1,7 +1,18 @@
|
|||
var request = {method: "getStyles", matchUrl: location.href, enabled: true, asHash: true};
|
||||
if (location.href.indexOf(chrome.extension.getURL("")) == 0) {
|
||||
chrome.extension.getBackgroundPage().getStyles(request, applyStyles);
|
||||
} else {
|
||||
requestStyles();
|
||||
|
||||
function requestStyles() {
|
||||
// If this is a Stylish page (Edit Style or Manage Styles),
|
||||
// we'll request the styles directly to minimize delay and flicker,
|
||||
// unless Chrome still starts up and the background page isn't fully loaded.
|
||||
// (Note: in this case the function may be invoked again from applyStyles.)
|
||||
var request = {method: "getStyles", matchUrl: location.href, enabled: true, asHash: true};
|
||||
if (location.href.indexOf(chrome.extension.getURL("")) == 0) {
|
||||
var bg = chrome.extension.getBackgroundPage();
|
||||
if (bg && bg.getStyles) {
|
||||
bg.getStyles(request, applyStyles);
|
||||
return;
|
||||
}
|
||||
}
|
||||
chrome.extension.sendMessage(request, applyStyles);
|
||||
}
|
||||
|
||||
|
@ -63,6 +74,10 @@ function removeStyle(id, doc) {
|
|||
}
|
||||
|
||||
function applyStyles(styleHash) {
|
||||
if (!styleHash) { // Chrome is starting up
|
||||
requestStyles();
|
||||
return;
|
||||
}
|
||||
if ("disableAll" in styleHash) {
|
||||
disableAll(styleHash.disableAll);
|
||||
delete styleHash.disableAll;
|
||||
|
|
|
@ -392,3 +392,8 @@ function openURL(options) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
var codeMirrorThemes;
|
||||
getCodeMirrorThemes(function(themes) {
|
||||
codeMirrorThemes = themes;
|
||||
});
|
||||
|
|
18
edit.html
18
edit.html
|
@ -276,12 +276,25 @@
|
|||
#sections > *:not(h2) {
|
||||
padding-left: 0.4rem;
|
||||
}
|
||||
.applies-type {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
@media(max-width:500px) {
|
||||
#options {
|
||||
-webkit-column-count: 1;
|
||||
}
|
||||
#options #tabSize-label {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<link id="cm-theme" rel="stylesheet">
|
||||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
<script src="localization.js"></script>
|
||||
<script src="apply.js"></script>
|
||||
<script src="edit.js"></script>
|
||||
</head>
|
||||
<body id="stylish-edit">
|
||||
<div id="header">
|
||||
|
@ -322,11 +335,14 @@
|
|||
<label id="keyMap-label" for="editor.keyMap" i18n-text="cm_keyMap"></label>
|
||||
<select data-option="keyMap" id="editor.keyMap"></select>
|
||||
</div>
|
||||
<div class="option aligned">
|
||||
<label id="theme-label" for="editor.theme" i18n-text="cm_theme"></label>
|
||||
<select data-option="theme" id="editor.theme"></select>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<section id="sections">
|
||||
<h2><span id="sections-heading" i18n-text="styleSectionsTitle"></span><img id="sections-help" src="help.png" i18n-alt="helpAlt"></h2>
|
||||
</section>
|
||||
<script src="edit.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
105
edit.js
105
edit.js
|
@ -128,6 +128,7 @@ function initCodeMirror() {
|
|||
matchBrackets: true,
|
||||
lint: CodeMirror.lint.css,
|
||||
keyMap: "sublime",
|
||||
theme: "default",
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"}
|
||||
}
|
||||
mergeOptions(stylishOptions, CM.defaults);
|
||||
|
@ -169,31 +170,80 @@ function initCodeMirror() {
|
|||
});
|
||||
}
|
||||
|
||||
// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->loadPrefs()
|
||||
var theme = prefs.getPref("editor.theme");
|
||||
document.getElementById("cm-theme").href = theme == "default" ? "" : "codemirror/theme/" + theme + ".css";
|
||||
|
||||
// initialize global editor controls
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
function optionsHtmlFromArray(options) {
|
||||
return options.map(function(opt) { return "<option>" + opt + "</option>"; }).join("");
|
||||
}
|
||||
var themeControl = document.getElementById("editor.theme");
|
||||
var bg = chrome.extension.getBackgroundPage();
|
||||
if (bg && bg.codeMirrorThemes) {
|
||||
themeControl.innerHTML = optionsHtmlFromArray(bg.codeMirrorThemes);
|
||||
} else {
|
||||
// Chrome is starting up and shows our edit.html, but the background page isn't loaded yet
|
||||
themeControl.innerHTML = optionsHtmlFromArray([theme == "default" ? t("defaultTheme") : theme]);
|
||||
getCodeMirrorThemes(function(themes) {
|
||||
themeControl.innerHTML = optionsHtmlFromArray(themes);
|
||||
themeControl.selectedIndex = Math.max(0, themes.indexOf(theme));
|
||||
});
|
||||
}
|
||||
document.getElementById("editor.keyMap").innerHTML = optionsHtmlFromArray(Object.keys(CM.keyMap).sort());
|
||||
var controlPrefs = {};
|
||||
document.querySelectorAll("#options *[data-option][id^='editor.']").forEach(function(option) {
|
||||
controlPrefs[option.id] = CM.defaults[option.dataset.option];
|
||||
});
|
||||
document.getElementById("options").addEventListener("change", acmeEventListener, false);
|
||||
|
||||
var keymapControl = document.getElementById("editor.keyMap");
|
||||
Object.keys(CodeMirror.keyMap).sort().forEach(function(map) {
|
||||
keymapControl.appendChild(document.createElement("option")).textContent = map;
|
||||
});
|
||||
|
||||
var controlPrefs = {},
|
||||
controlOptions = ["smartIndent", "indentWithTabs", "tabSize", "keyMap", "lineWrapping"];
|
||||
controlOptions.forEach(function(option) {
|
||||
controlPrefs["editor." + option] = CM.defaults[option];
|
||||
});
|
||||
loadPrefs(controlPrefs);
|
||||
|
||||
});
|
||||
}
|
||||
initCodeMirror();
|
||||
|
||||
function acmeEventListener(event) {
|
||||
var option = event.target.dataset.option;
|
||||
console.log("acmeEventListener heard %s on %s", event.type, event.target.id);
|
||||
if (!option) console.error("acmeEventListener: no 'cm_option' %O", event.target);
|
||||
else CodeMirror.setOption(option, event.target[isCheckbox(event.target) ? "checked" : "value"]);
|
||||
|
||||
if ("tabSize" === option) CodeMirror.setOption("indentUnit", CodeMirror.getOption("tabSize"));
|
||||
var el = event.target;
|
||||
var option = el.dataset.option;
|
||||
//console.log("acmeEventListener heard %s on %s", event.type, el.id);
|
||||
if (!option) {
|
||||
console.error("acmeEventListener: no 'cm_option' %O", el);
|
||||
return;
|
||||
}
|
||||
var value = el.type == "checkbox" ? el.checked : el.value;
|
||||
switch (option) {
|
||||
case "tabSize":
|
||||
CodeMirror.setOption("indentUnit", value);
|
||||
break;
|
||||
case "theme":
|
||||
var themeLink = document.getElementById("cm-theme");
|
||||
// use non-localized "default" internally
|
||||
if (!value || value == "default" || value == t("defaultTheme")) {
|
||||
value = "default";
|
||||
if (prefs.getPref(el.id) != value) {
|
||||
prefs.setPref(el.id, value);
|
||||
}
|
||||
themeLink.href = "";
|
||||
el.selectedIndex = 0;
|
||||
break;
|
||||
}
|
||||
var url = chrome.extension.getURL("codemirror/theme/" + value + ".css");
|
||||
if (themeLink.href == url) { // preloaded in initCodeMirror()
|
||||
break;
|
||||
}
|
||||
// avoid flicker: wait for the second stylesheet to load, then apply the theme
|
||||
document.head.insertAdjacentHTML("beforeend",
|
||||
'<link id="cm-theme2" rel="stylesheet" href="' + url + '">');
|
||||
(function() {
|
||||
setTimeout(function() {
|
||||
CodeMirror.setOption(option, value);
|
||||
themeLink.remove();
|
||||
document.getElementById("cm-theme2").id = "cm-theme";
|
||||
}, 100);
|
||||
})();
|
||||
return;
|
||||
}
|
||||
CodeMirror.setOption(option, value);
|
||||
}
|
||||
|
||||
// replace given textarea with the CodeMirror editor
|
||||
|
@ -598,11 +648,18 @@ function init() {
|
|||
return;
|
||||
}
|
||||
// This is an edit
|
||||
chrome.extension.sendMessage({method: "getStyles", id: params.id}, function(styles) {
|
||||
requestStyle();
|
||||
function requestStyle() {
|
||||
chrome.extension.sendMessage({method: "getStyles", id: params.id}, function callback(styles) {
|
||||
if (!styles) { // Chrome is starting up and shows edit.html
|
||||
requestStyle();
|
||||
return;
|
||||
}
|
||||
var style = styles[0];
|
||||
styleId = style.id;
|
||||
initWithStyle(style);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initWithStyle(style) {
|
||||
|
@ -626,6 +683,10 @@ function initHooks() {
|
|||
node.addEventListener("change", onChange);
|
||||
node.addEventListener("input", onChange);
|
||||
});
|
||||
document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false);
|
||||
document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false);
|
||||
document.getElementById("save-button").addEventListener("click", save, false);
|
||||
document.getElementById("sections-help").addEventListener("click", showSectionHelp, false);
|
||||
|
||||
setupGlobalSearch();
|
||||
setCleanGlobal();
|
||||
|
@ -787,7 +848,6 @@ function getParams() {
|
|||
}
|
||||
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
var installed = document.getElementById("installed");
|
||||
switch (request.method) {
|
||||
case "styleUpdated":
|
||||
if (styleId == request.id) {
|
||||
|
@ -806,8 +866,3 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("to-mozilla").addEventListener("click", showMozillaFormat, false);
|
||||
document.getElementById("to-mozilla-help").addEventListener("click", showToMozillaHelp, false);
|
||||
document.getElementById("save-button").addEventListener("click", save, false);
|
||||
document.getElementById("sections-help").addEventListener("click", showSectionHelp, false);
|
||||
|
|
14
health.js
14
health.js
|
@ -1,7 +1,11 @@
|
|||
chrome.extension.sendMessage({method: "healthCheck"}, function(ok) {
|
||||
if (!ok) {
|
||||
if (confirm(t("dbError"))) {
|
||||
healthCheck();
|
||||
|
||||
function healthCheck() {
|
||||
chrome.extension.sendMessage({method: "healthCheck"}, function(ok) {
|
||||
if (ok === undefined) { // Chrome is starting up
|
||||
healthCheck();
|
||||
} else if (!ok && confirm(t("dbError"))) {
|
||||
window.open("http://userstyles.org/dberror");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ loadPrefs({
|
|||
});
|
||||
|
||||
function showStyles(styles) {
|
||||
if (!styles) { // Chrome is starting up
|
||||
chrome.extension.sendMessage({method: "getStyles"}, showStyles);
|
||||
return;
|
||||
}
|
||||
styles.sort(function(a, b) { return a.name.localeCompare(b.name)});
|
||||
var installed = document.getElementById("installed");
|
||||
styles.map(createStyleElement).forEach(function(e) {
|
||||
|
|
20
storage.js
20
storage.js
|
@ -178,6 +178,7 @@ var prefs = {
|
|||
"editor.indentWithTabs": false,// smart indent with tabs
|
||||
"editor.tabSize": 4, // tab width, in spaces
|
||||
"editor.keyMap": "sublime", // keymap
|
||||
"editor.theme": "default", // CSS theme
|
||||
|
||||
NO_DEFAULT_PREFERENCE: "No default preference for '%s'",
|
||||
UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?",
|
||||
|
@ -222,3 +223,22 @@ var prefs = {
|
|||
},
|
||||
removePref: function(key) { setPref(key, undefined) }
|
||||
};
|
||||
|
||||
function getCodeMirrorThemes(callback) {
|
||||
chrome.runtime.getPackageDirectoryEntry(function(rootDir) {
|
||||
rootDir.getDirectory("codemirror/theme", {create: false}, function(themeDir) {
|
||||
themeDir.createReader().readEntries(function(entries) {
|
||||
var themes = [chrome.i18n.getMessage("defaultTheme")];
|
||||
entries
|
||||
.filter(function(entry) { return entry.isFile })
|
||||
.sort(function(a, b) { return a.name < b.name ? -1 : 1 })
|
||||
.forEach(function(entry) {
|
||||
themes.push(entry.name.replace(/\.css$/, ""));
|
||||
});
|
||||
if (callback) {
|
||||
callback(themes);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user