Skip to content

Commit

Permalink
Allow users to add custom stylesheet and JavaScript
Browse files Browse the repository at this point in the history
Ref #31 and #39
  • Loading branch information
ggrossetie committed Aug 10, 2014
1 parent f8d3e8b commit fd4b7c6
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 94 deletions.
23 changes: 22 additions & 1 deletion js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,29 @@ function refreshOptions() {
chrome.storage.local.set({
'CUSTOM_ATTRIBUTES':localStorage['CUSTOM_ATTRIBUTES'],
'SAFE_MODE':localStorage['SAFE_MODE'],
'THEME':localStorage['THEME']
'THEME':localStorage['THEME'],
'JS':localStorage['JS']
});
var customThemeNames = JSON.parse(localStorage['CUSTOM_THEME_NAMES'] || '[]');
if (customThemeNames.length > 0) {
for (var index in customThemeNames) {
var themeName = customThemeNames[index];
var themeNameKey = 'CUSTOM_THEME_' + themeName;
var themeObj = {};
themeObj[themeNameKey] = localStorage[themeNameKey];
chrome.storage.local.set(themeObj);
}
}
var customJavaScriptNames = JSON.parse(localStorage['CUSTOM_JS_NAMES'] || '[]');
if (customThemeNames.length > 0) {
for (var index in customJavaScriptNames) {
var javaScriptName = customJavaScriptNames[index];
var javaScriptNameKey = 'CUSTOM_JS_' + javaScriptName;
var javaScriptObj = {};
javaScriptObj[javaScriptNameKey] = localStorage[javaScriptNameKey];
chrome.storage.local.set(javaScriptObj);
}
}
}

chrome.browserAction.onClicked.addListener(enableDisableRender);
Expand Down
210 changes: 156 additions & 54 deletions js/options.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,178 @@
// Saves options to localStorage.
function save_options() {
var inputCustomAttributes = document.getElementById('inputCustomAttributes');
localStorage['CUSTOM_ATTRIBUTES'] = inputCustomAttributes.value;
var selectTheme = $('#selectTheme');
var selectJavaScript = $('#selectJavaScript');
var selectSafeMode = $('#selectSafeMode');
var inputCustomAttributes = $('#inputCustomAttributes');
var inputCustomTheme = $('#inputCustomTheme');
var inputCustomJavaScript = $('#inputCustomJavaScript');

var selectSafeMode = document.getElementById('selectSafeMode');
localStorage['SAFE_MODE'] = selectSafeMode.value;
var addCustomThemeAlert = $('#addCustomThemeAlert');
var addCustomJavaScriptAlert = $('#addCustomJavaScriptAlert');
var saveAlert = $('#saveAlert');
var saveBtn = $('#saveBtn');

var selectTheme = document.getElementById('selectTheme');
localStorage['THEME'] = selectTheme.value;
saveBtn.click(saveOptions);
$(document).bind('ready', restoreOptions);

/**
* Saves options to localStorage.
*/
function saveOptions() {
localStorage['CUSTOM_ATTRIBUTES'] = inputCustomAttributes.val();
localStorage['SAFE_MODE'] = selectSafeMode.val();
localStorage['THEME'] = selectTheme.val();
localStorage['JS'] = selectJavaScript.val();

// Update status to let user know options were saved.
var alert = '<div class="alert alert-success alert-dismissable fade in"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button><b>{{message}}</b></div>';
var html = alert.replace('{{message}}', 'Options saved!');
$('#status').html(html);
saveAlert.find('.content').html('<b>Options saved!</b>');
saveAlert.show();
chrome.extension.getBackgroundPage().refreshOptions()
}

// Restores options to saved value from localStorage.
function restore_options() {
var customAttributes = localStorage['CUSTOM_ATTRIBUTES'];
if (customAttributes) {
var inputCustomAttributes = document.getElementById('inputCustomAttributes');
inputCustomAttributes.value = customAttributes;
}

var safeMode = localStorage['SAFE_MODE'] || 'secure';
var selectSafeMode = document.getElementById('selectSafeMode');
selectSafeMode.value = safeMode;
/**
* Restores options to saved value from localStorage.
*/
function restoreOptions() {
inputCustomAttributes.val(localStorage['CUSTOM_ATTRIBUTES'] || '');
selectSafeMode.val(localStorage['SAFE_MODE'] || 'secure');

var theme = localStorage['THEME'] || 'asciidoctor';
var selectTheme = document.getElementById('selectTheme');
selectTheme.value = theme;

var customThemes = localStorage['CUSTOM_THEMES'];
// Themes
var customThemeNames = JSON.parse(localStorage['CUSTOM_THEME_NAMES'] || '[]');
if (customThemeNames.length > 0) {
var customThemesOptGroup = getCustomThemeOptGroup();
for (var index in customThemeNames) {
customThemesOptGroup.append('<option>' + customThemeNames[index] + '</option>');
}
}
selectTheme.val(localStorage['THEME'] || 'asciidoctor');

if (customThemes) {
var customThemesOptGroup = document.createElement('optgroup');
customThemesOptGroup.label = 'Custom';
for (var index in customThemes) {
var customTheme = customThemes[index];
var option = document.createElement('option');
option.innerText = customTheme;
customThemesOptGroup.appendChild(option);
// JavaScripts
var customJavaScriptNames = JSON.parse(localStorage['CUSTOM_JS_NAMES'] || '[]');
if (customJavaScriptNames.length > 0) {
for (var index in customJavaScriptNames) {
selectJavaScript.append('<option>' + customJavaScriptNames[index] + '</option>');
}
document.getElementById('selectTheme').appendChild(customThemesOptGroup);
}
selectJavaScript.val(localStorage['JS']);
}

function initAlert(element) {
element.find('.close').click(function () {
element.hide();
});
element.hide();
}

var addCustomCSSBtn = $('#addCustomCSS');
var addCustomJavaScriptBtn = $('#addCustomJavaScript');
addCustomCSSBtn.hide();
addCustomJavaScriptBtn.hide();
initAlert(saveAlert);
initAlert(addCustomThemeAlert);
initAlert(addCustomJavaScriptAlert);

$('#inputCustomTheme').change(function () {
inputCustomTheme.change(function () {
resetAlert(addCustomThemeAlert);
var hasNoFiles = this.files.length == 0;
if (hasNoFiles) {
addCustomCSSBtn.hide();
} else {
// TODO Check extension
addCustomCSSBtn.show();
if (!hasNoFiles) {
var file = this.files[0];
var themeName = getFileNameWithoutExtension(file);
var customThemeOptGroup = getCustomThemeOptGroup();
var themeExists = customThemeOptGroup.find('option:contains(' + themeName + ')').length == 0;
var alert = buildAlert(themeExists, themeName, 'theme');
if (themeExists) {
addNewOpt(customThemeOptGroup, themeName);
}
selectOpt(customThemeOptGroup, themeName);
updateThemeFile(file, themeName);
showAlert(addCustomThemeAlert, alert);
this.value = '';
}
});

$('#inputCustomJavaScript').change(function () {
inputCustomJavaScript.change(function () {
resetAlert(addCustomJavaScriptAlert);
var hasNoFiles = this.files.length == 0;
if (hasNoFiles) {
addCustomJavaScriptBtn.hide();
} else {
// TODO Check extension
addCustomJavaScriptBtn.show();
if (!hasNoFiles) {
var file = this.files[0];
var javaScriptName = getFileNameWithoutExtension(file);
var javaScriptExists = selectJavaScript.find('option:contains(' + javaScriptName + ')').length == 0;
var alert = buildAlert(javaScriptExists, javaScriptName, 'JavaScript');
if (javaScriptExists) {
addNewOpt(selectJavaScript, javaScriptName);
}
selectOpt(selectJavaScript, javaScriptName);
updateJavaScriptFile(file, javaScriptName);
showAlert(addCustomJavaScriptAlert, alert);
this.value = '';
}
});

document.addEventListener('DOMContentLoaded', restore_options);
document.querySelector('#save').addEventListener('click', save_options);
function addNewOpt(parentElement, name) {
parentElement.append('<option>' + name + '</option>');
}

function getCustomThemeOptGroup() {
var customThemesOptGroup = $("#customThemeOptGroup");
if (customThemesOptGroup.length == 0) {
customThemesOptGroup = $('<optgroup id="customThemeOptGroup" label="Custom"></optgroup>');
selectTheme.append(customThemesOptGroup);
}
return customThemesOptGroup;
}

function updateThemeFile(themeFile, themeName) {
var reader = new FileReader();
reader.onload = function (evt) {
var fileString = evt.target.result;
var customThemeNames = JSON.parse(localStorage['CUSTOM_THEME_NAMES'] || '[]');
if ($.inArray(themeName, customThemeNames) === -1) {
customThemeNames.push(themeName);
localStorage['CUSTOM_THEME_NAMES'] = JSON.stringify(customThemeNames);
}
localStorage['CUSTOM_THEME_' + themeName] = fileString;
};
reader.readAsText(themeFile);
}

function updateJavaScriptFile(themeFile, javaScriptName) {
var reader = new FileReader();
reader.onload = function (evt) {
var fileString = evt.target.result;
var customJavaScriptNames = JSON.parse(localStorage['CUSTOM_JS_NAMES'] || '[]');
if ($.inArray(javaScriptName, customJavaScriptNames) === -1) {
customJavaScriptNames.push(javaScriptName);
localStorage['CUSTOM_JS_NAMES'] = JSON.stringify(customJavaScriptNames);
}
localStorage['CUSTOM_JS_' + javaScriptName] = fileString;
};
reader.readAsText(themeFile);
}

function getFileNameWithoutExtension(file) {
var fileName = file.name;
return fileName.substr(0, fileName.lastIndexOf('.')) || fileName;
}

function buildAlert(exists, name, type) {
var alertClasses;
var alertMessage;
if (exists) {
alertClasses = 'alert alert-sm alert-info';
alertMessage = 'New ' + type + ' <b>' + name + '</b> has been added!';
} else {
alertClasses = 'alert alert-sm alert-warning';
alertMessage = 'Existing ' + type + ' <b>' + name + '</b> has been replaced!';
}
return {classes:alertClasses, message:alertMessage};
}

function showAlert(element, alert) {
element.addClass(alert.classes);
element.find('.content').html(alert.message);
element.show();
}

function resetAlert(element) {
element.hide();
element.removeClass();
}

function selectOpt(parentElement, name) {
parentElement.find('option:contains(' + name + ')').prop('selected', true);
}
58 changes: 53 additions & 5 deletions js/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ var SAFE_MODE_KEY = 'SAFE_MODE';
var LIVERELOADJS_DETECTED_KEY = 'LIVERELOADJS_DETECTED';
var LIVERELOADJS_FILENAME = 'livereload.js';
var THEME_KEY = 'THEME';
var CUSTOM_THEME_PREFIX = 'CUSTOM_THEME_';
var JS_KEY = 'JS';

/**
* Render AsciiDoc content as HTML
Expand All @@ -15,6 +17,7 @@ asciidoctor.chrome.convert = function (data) {
chrome.storage.local.get([CUSTOM_ATTRIBUTES_KEY, SAFE_MODE_KEY], function (settings) {
try {
removeMathJaxRefreshJs();
removeCustomJs();
var body = $(document.body);
var scripts = body.find('script');
detectLiveReloadJs(scripts);
Expand All @@ -30,6 +33,7 @@ asciidoctor.chrome.convert = function (data) {

refreshMathJax();
appendScripts(scripts);
appendCustomJavaScript();
syntaxHighlighting();
}
catch (e) {
Expand Down Expand Up @@ -116,6 +120,22 @@ function syntaxHighlighting() {
});
}

function appendCustomJavaScript() {
chrome.storage.local.get(JS_KEY, function (items) {
var javaScriptName = items[JS_KEY];
if (javaScriptName) {
var customJavaScriptKey = 'CUSTOM_JS_' + javaScriptName;
chrome.storage.local.get(customJavaScriptKey, function (items) {
if (items[customJavaScriptKey]) {
var customJavaScript = $('<script id="asciidoctor-custom-js" type="text/javascript"></script>');
customJavaScript.html(items[customJavaScriptKey]);
$(document.body).append(customJavaScript);
}
});
}
});
}

function appendFontAwesomeStyle() {
if ($('#font-awesome-style').length == 0) {
var fontAwesomeLink = document.createElement('link');
Expand All @@ -136,18 +156,42 @@ function appendHighlightJsScript() {
document.head.appendChild(highlightJsScript);
}

function getDefaultThemeNames() {
var web_accessible_resources = chrome.runtime.getManifest().web_accessible_resources;
var themeRegexp = /^css\/themes\/(.*)\.css$/i;
var themes = $.grep(web_accessible_resources, function (item) {
return themeRegexp.test(item);
});
return themes.map(function (item) {
return item.replace(themeRegexp, "$1");
});
}

/**
* Append css files
*/
function appendStyles() {
// Theme
chrome.storage.local.get(THEME_KEY, function (settings) {
var theme = settings[THEME_KEY] || 'asciidoctor';
var themeLink = document.createElement('link');
themeLink.rel = 'stylesheet';
themeLink.id = 'asciidoctor-style';
themeLink.href = chrome.extension.getURL('css/themes/' + theme + '.css');
document.head.appendChild(themeLink);
var themeNames = getDefaultThemeNames();
// Check if the theme is packaged in the extension... if not it's a custom theme
if ($.inArray(theme, themeNames) !== -1) {
var themeLink = document.createElement('link');
themeLink.rel = 'stylesheet';
themeLink.id = 'asciidoctor-style';
themeLink.href = chrome.extension.getURL('css/themes/' + theme + '.css');
document.head.appendChild(themeLink);
} else {
var customThemeKey = CUSTOM_THEME_PREFIX + theme;
chrome.storage.local.get(customThemeKey, function (items) {
if (items[customThemeKey]) {
var themeStyle = $('<style id="asciidoctor-custom-style"></style>');
themeStyle.html(items[customThemeKey]);
$(document.head).append(themeStyle);
}
});
}
});
// Highlight
var highlightTheme = 'default';
Expand Down Expand Up @@ -190,6 +234,10 @@ function removeMathJaxRefreshJs() {
$('#mathjax-refresh-js').remove();
}

function removeCustomJs() {
$('#asciidoctor-custom-js').remove();
}

function refreshMathJax() {
var mathJaxJsScript = document.createElement('script');
mathJaxJsScript.id = 'mathjax-refresh-js';
Expand Down
Loading

0 comments on commit fd4b7c6

Please sign in to comment.