<commit_before>function parseHash() {
    var hash = location.hash.substring(1);
    if (!hash) return {};

    var parts = hash.split('&');
    var keys = {};
    parts.forEach(function(part) {
        var splits = part.split('=');
        keys[splits[0]] = decodeURIComponent(splits[1]);
    });
    return keys;
}

function saveOnHash() {
    var regexp = regExpEditor.getValue();
    var input = editor.getValue();
    location.hash = 'regexp=' + encodeURIComponent(regexp) + '&' + 'input=' + encodeURIComponent(input);

    alert('Stored current RegExp and input on the URL. Feel free to pass the URL to someone else for sharing.')
}

var lastRes = null;
var currentTrace = null;

function selectRegExpDom(from, to) {
    regExpDom.selectionStart = from;
    regExpDom.selectionEnd = to;
}

function reflectSelection(trace) {
    var selection;
    var pos;
    currentTrace = trace;
    if (!trace || !trace.node || !trace.node.parseEntry) {
        selection = { from: 0, to: 0 };
    } else {
        selection = trace.node.parseEntry;
    }
    if (trace) {
        pos = { from: trace.pos, to: trace.pos + 1 };
    } else {
        pos = { from: 0, to: 0 };
    }

    if (editor._overlay) {
        editor._overlay.clear();
        editor.removeOverlay(editor._overlay);
        regExpEditor._overlay.clear();
        regExpEditor.removeOverlay(editor._overlay);
    }
    var doc = editor.getDoc();
    editor._overlay = doc.markText(
        doc.posFromIndex(pos.from),
        doc.posFromIndex(pos.to),
        {className: 'matchhighlight'}
    );

    var doc = regExpEditor.getDoc();
    regExpEditor._overlay = doc.markText(
        doc.posFromIndex(selection.from),
        doc.posFromIndex(selection.to),
        {className: 'matchhighlight'}
    );
}

function traceToHTML(trace) {
    function traceNodeToHTML(traceNode, className) {
        if (traceNode == null || traceNode.node.dontCountTraceNode ) {
            return '';
        }
        var display = '';

        if (traceNode.node.type == 'GROUP_BEGIN') {
            display = ''; //(';
        } else if (traceNode.node.type == 'GROUP_END') {
            display = ''; //')';
        } else if (traceNode.node.type == 'BACK') {
            display = 'B';
            className += 'arrow_box';
        } else if (traceNode.node.type == 'FORWARD') {
            display = '>>';
        } else {
            display = traceNode.node.parseEntry.raw;
        }

        display = display.replace(/\s/g, ' ');

        var html = '';
        if (display) {
            html = '' + display + '';
        }
        return html;
    }

    var html = '';
    var forkIdx = trace.lastBackIdx;
    var lastVisibleNodeIdx = trace.length;

    for (var i = trace.length - 1; i >= 0; i--) {
        if (!trace[i].node.dontCountTraceNode) {
            lastVisibleNodeIdx = i;
            break;
        }
    }

    for (var i = 0; i < trace.length; i++) {
        var className = '';
        if (i <= forkIdx) {
            className = 'hide ';
        } else if (trace.isEndTrace && i === lastVisibleNodeIdx) {
            className = trace.isEndTrace + ' ';
        }
        html += traceNodeToHTML(trace[i], className);
    }

    return html;
}

function matchIt() {
    try {
        var regExp = new RegExpJS(regExpEditor.getValue());
    } catch (e) {
        regExpErrorDom.textContent = e.toString();
        return;
    }
    regExpErrorDom.textContent = '';

    var input = editor.getValue();

    try {
        var res = window.res = lastRes = regExp.execDebug(input, regexp);
    } catch (exp) {
        alert('Sorry: ' + exp);
        return;
    }

    var resOutput;
    if (res.matches) {
        resOutput = JSON.stringify(res.matches, null, 4);
    } else {
        resOutput = 'null';
    }

    var traceOutput = '';
    traceOutput += res.traces.filter(function(trace) {
        return trace.isEndTrace;
    }).map(function(trace) {
        var html = traceToHTML(trace);
        return '
<nobr>' + html + '</nobr>
';
    }).join('\n');
    tracesDom.innerHTML = traceOutput;

    document.getElementById('result').value = resOutput;
    document.getElementById('parseTree').value = JSON.stringify(res.parseTree, null, 4);
}

var editor;
var regExpEditor;
var regExpErrorDom;
var tracesDom;

window.onload = function() {
    // Leak globally.
    editor = null;
    regExpDom = document.getElementById('regexp');
    regExpErrorDom = document.getElementById('regexperror');
    tracesDom = document.getElementById('traces');

    tracesDom.addEventListener('mouseover', function(e) {
        var target = e.target;
        var traceId = target.getAttribute('data-trace-id');
        var trace = lastRes.traces.data.traceHash[traceId];

        reflectSelection(trace);
    });

    var inputDom = document.getElementById('area');

    regExpEditor = CodeMirror.fromTextArea(regExpDom);

    editor = CodeMirror.fromTextArea(inputDom);
    editor.setSize(null, '100px');
    editor._overlay = null;

    var hashData = parseHash();
    if ('regexp' in hashData) regExpDom.value = hashData.regexp;
    if ('input' in hashData) editor.setValue(hashData.input);

    var matchItTimer = null;
    function scheduleMatchIt() {
        if (matchItTimer) {
            clearTimeout(matchItTimer);
        }
        matchItTimer = setTimeout(matchIt, 200);
    }

    regExpEditor.on('change', scheduleMatchIt);
    editor.on('change', scheduleMatchIt);

    var previousRegExpDomValue = null;
    regExpDom.addEventListener('keyup', scheduleMatchIt);

    matchIt();
}<commit_msg>Fix permalinks that contain a regexp<commit_after>function parseHash() {
    var hash = location.hash.substring(1);
    if (!hash) return {};

    var parts = hash.split('&');
    var keys = {};
    parts.forEach(function(part) {
        var splits = part.split('=');
        keys[splits[0]] = decodeURIComponent(splits[1]);
    });
    return keys;
}

function saveOnHash() {
    var regexp = regExpEditor.getValue();
    var input = editor.getValue();
    location.hash = 'regexp=' + encodeURIComponent(regexp) + '&' + 'input=' + encodeURIComponent(input);

    alert('Stored current RegExp and input on the URL. Feel free to pass the URL to someone else for sharing.')
}

var lastRes = null;
var currentTrace = null;

function selectRegExpDom(from, to) {
    regExpDom.selectionStart = from;
    regExpDom.selectionEnd = to;
}

function reflectSelection(trace) {
    var selection;
    var pos;
    currentTrace = trace;
    if (!trace || !trace.node || !trace.node.parseEntry) {
        selection = { from: 0, to: 0 };
    } else {
        selection = trace.node.parseEntry;
    }
    if (trace) {
        pos = { from: trace.pos, to: trace.pos + 1 };
    } else {
        pos = { from: 0, to: 0 };
    }

    if (editor._overlay) {
        editor._overlay.clear();
        editor.removeOverlay(editor._overlay);
        regExpEditor._overlay.clear();
        regExpEditor.removeOverlay(editor._overlay);
    }
    var doc = editor.getDoc();
    editor._overlay = doc.markText(
        doc.posFromIndex(pos.from),
        doc.posFromIndex(pos.to),
        {className: 'matchhighlight'}
    );

    var doc = regExpEditor.getDoc();
    regExpEditor._overlay = doc.markText(
        doc.posFromIndex(selection.from),
        doc.posFromIndex(selection.to),
        {className: 'matchhighlight'}
    );
}

function traceToHTML(trace) {
    function traceNodeToHTML(traceNode, className) {
        if (traceNode == null || traceNode.node.dontCountTraceNode ) {
            return '';
        }
        var display = '';

        if (traceNode.node.type == 'GROUP_BEGIN') {
            display = ''; //(';
        } else if (traceNode.node.type == 'GROUP_END') {
            display = ''; //')';
        } else if (traceNode.node.type == 'BACK') {
            display = 'B';
            className += 'arrow_box';
        } else if (traceNode.node.type == 'FORWARD') {
            display = '>>';
        } else {
            display = traceNode.node.parseEntry.raw;
        }

        display = display.replace(/\s/g, ' ');

        var html = '';
        if (display) {
            html = '' + display + '';
        }
        return html;
    }

    var html = '';
    var forkIdx = trace.lastBackIdx;
    var lastVisibleNodeIdx = trace.length;

    for (var i = trace.length - 1; i >= 0; i--) {
        if (!trace[i].node.dontCountTraceNode) {
            lastVisibleNodeIdx = i;
            break;
        }
    }

    for (var i = 0; i < trace.length; i++) {
        var className = '';
        if (i <= forkIdx) {
            className = 'hide ';
        } else if (trace.isEndTrace && i === lastVisibleNodeIdx) {
            className = trace.isEndTrace + ' ';
        }
        html += traceNodeToHTML(trace[i], className);
    }

    return html;
}

function matchIt() {
    try {
        var regExp = new RegExpJS(regExpEditor.getValue());
    } catch (e) {
        regExpErrorDom.textContent = e.toString();
        return;
    }
    regExpErrorDom.textContent = '';

    var input = editor.getValue();

    try {
        var res = window.res = lastRes = regExp.execDebug(input, regexp);
    } catch (exp) {
        alert('Sorry: ' + exp);
        return;
    }

    var resOutput;
    if (res.matches) {
        resOutput = JSON.stringify(res.matches, null, 4);
    } else {
        resOutput = 'null';
    }

    var traceOutput = '';
    traceOutput += res.traces.filter(function(trace) {
        return trace.isEndTrace;
    }).map(function(trace) {
        var html = traceToHTML(trace);
        return '
<nobr>' + html + '</nobr>
';
    }).join('\n');
    tracesDom.innerHTML = traceOutput;

    document.getElementById('result').value = resOutput;
    document.getElementById('parseTree').value = JSON.stringify(res.parseTree, null, 4);
}

var editor;
var regExpEditor;
var regExpErrorDom;
var tracesDom;

window.onload = function() {
    // Leak globally.
    editor = null;
    regExpDom = document.getElementById('regexp');
    regExpErrorDom = document.getElementById('regexperror');
    tracesDom = document.getElementById('traces');

    tracesDom.addEventListener('mouseover', function(e) {
        var target = e.target;
        var traceId = target.getAttribute('data-trace-id');
        var trace = lastRes.traces.data.traceHash[traceId];

        reflectSelection(trace);
    });

    var inputDom = document.getElementById('area');

    regExpEditor = CodeMirror.fromTextArea(regExpDom);

    editor = CodeMirror.fromTextArea(inputDom);
    editor.setSize(null, '100px');
    editor._overlay = null;

    var hashData = parseHash();
    if ('regexp' in hashData) regExpEditor.setValue(hashData.regexp);
    if ('input' in hashData) editor.setValue(hashData.input);

    var matchItTimer = null;
    function scheduleMatchIt() {
        if (matchItTimer) {
            clearTimeout(matchItTimer);
        }
        matchItTimer = setTimeout(matchIt, 200);
    }

    regExpEditor.on('change', scheduleMatchIt);
    editor.on('change', scheduleMatchIt);

    var previousRegExpDomValue = null;
    regExpDom.addEventListener('keyup', scheduleMatchIt);

    matchIt();
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
/* eslint-disable no-console */

frappe.provide("website");
frappe.provide("frappe.awesome_bar_path");
window.cur_frm = null;

$.extend(frappe, {
	boot: {
		lang: 'en'
	},
	_assets_loaded: [],
	require: function(url) {
		if(frappe._assets_loaded.indexOf(url)!==-1) return;
		return $.ajax({
			url: url,
			async: false,
			dataType: "text",
			success: function(data) {
				var el;
				if(url.split(".").splice(-1) == "js") {
					el = document.createElement('script');
				} else {
					el = document.createElement('style');
				}
				el.appendChild(document.createTextNode(data));
				document.getElementsByTagName('head')[0].appendChild(el);
				frappe._assets_loaded.push(url);
			}
		});
	},
	hide_message: function() {
		$('.message-overlay').remove();
	},
	call: function(opts) {
		// opts = {"method": "PYTHON MODULE STRING", "args": {}, "callback": function(r) {}}
		if (typeof arguments[0]==='string') {
			opts = {
				method: arguments[0],
				args: arguments[1],
				callback: arguments[2]
			}
		}

		frappe.prepare_call(opts);
		if(opts.freeze) {
			frappe.freeze();
		}
		return $.ajax({
			type: opts.type || "POST",
			url: "/",
			data: opts.args,
			dataType: "json",
			headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
			statusCode: opts.statusCode || {
				404: function() {
					frappe.msgprint(__("Not found"));
				},
				403: function() {
					frappe.msgprint(__("Not permitted"));
				},
				200: function(data) {
					if(opts.callback)
						opts.callback(data);
					if(opts.success)
						opts.success(data);
				}
			}
		}).always(function(data) {
			if(opts.freeze) {
				frappe.unfreeze();
			}

			// executed before statusCode functions
			if(data.responseText) {
				try {
					data = JSON.parse(data.responseText);
				} catch (e) {
					data = {};
				}
			}
			frappe.process_response(opts, data);
		});
	},
	prepare_call: function(opts) {
		if(opts.btn) {
			$(opts.btn).prop("disabled", true);
		}

		if(opts.msg) {
			$(opts.msg).toggle(false);
		}

		if(!opts.args) opts.args = {};

		// method
		if(opts.method) {
			opts.args.cmd = opts.method;
		}

		// stringify
		$.each(opts.args, function(key, val) {
			if(typeof val != "string") {
				opts.args[key] = JSON.stringify(val);
			}
		});

		if(!opts.no_spinner) {
			//NProgress.start();
		}
	},
	process_response: function(opts, data) {
		//if(!opts.no_spinner) NProgress.done();

		if(opts.btn) {
			$(opts.btn).prop("disabled", false);
		}

		if (data._server_messages) {
			var server_messages = JSON.parse(data._server_messages || '[]');
			server_messages = $.map(server_messages, function(v) {
				// temp fix for messages sent as dict
				try {
					return JSON.parse(v).message;
				} catch (e) {
					return v;
				}
			}).join('
');

			if(opts.error_msg) {
				$(opts.error_msg).html(server_messages).toggle(true);
			} else {
				frappe.msgprint(server_messages);
			}
		}

		if(data.exc) {
			// if(opts.btn) {
			// 	$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-danger" : "text-danger");
			// 	setTimeout(function() { $(opts.btn).removeClass("btn-danger text-danger"); }, 1000);
			// }
			try {
				var err = JSON.parse(data.exc);
				if($.isArray(err)) {
					err = err.join("\n");
				}
				console.error ? console.error(err) : console.log(err);
			} catch(e) {
				console.log(data.exc);
			}

		} else{
			// if(opts.btn) {
			// 	$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-success" : "text-success");
			// 	setTimeout(function() { $(opts.btn).removeClass("btn-success text-success"); }, 1000);
			// }
		}
		if(opts.msg && data.message) {
			$(opts.msg).html(data.message).toggle(true);
		}

		if(opts.always) {
			opts.always(data);
		}
	},
	show_message: function(text, icon) {
		if(!icon) icon="fa fa-refresh fa-spin";
		frappe.hide_message();
		$('

')
			.html('

'
				+text+'
').appendTo(document.body);
	},
	get_sid: function() {
		var sid = frappe.get_cookie("sid");
		return sid && sid !== "Guest";
	},
	get_modal: function(title, body_html) {
		var modal = $('
\

\

\

\
						×\

'+title+'
\

\

'+body_html+'\

\

\

\

').appendTo(document.body);

		return modal;
	},
	msgprint: function(html, title) {
		if(html.substr(0,1)==="[") html = JSON.parse(html);
		if($.isArray(html)) {
			html = html.join("
");
		}

		return frappe.get_modal(title || "Message", html).modal("show");
	},
	send_message: function(opts, btn) {
		return frappe.call({
			type: "POST",
			method: "frappe.www.contact.send_message",
			btn: btn,
			args: opts,
			callback: opts.callback
		});
	},
	has_permission: function(doctype, docname, perm_type, callback) {
		return frappe.call({
			type: "GET",
			method: "frappe.client.has_permission",
			no_spinner: true,
			args: {doctype: doctype, docname: docname, perm_type: perm_type},
			callback: function(r) {
				if(!r.exc && r.message.has_permission) {
					if(callback) {
						return callback(r);
					}
				}
			}
		});
	},
	render_user: function() {
		var sid = frappe.get_cookie("sid");
		if(sid && sid!=="Guest") {
			$(".btn-login-area").toggle(false);
			$(".logged-in").toggle(true);
			$(".full-name").html(frappe.get_cookie("full_name"));
			$(".user-image").attr("src", frappe.get_cookie("user_image"));

			$('.user-image-wrapper').html(frappe.avatar(null, 'avatar-small'));
			$('.user-image-sidebar').html(frappe.avatar(null, 'avatar-small'));
			$('.user-image-myaccount').html(frappe.avatar(null, 'avatar-large'));
		}
	},
	freeze_count: 0,
	freeze: function(msg) {
		// blur
		if(!$('#freeze').length) {
			var freeze = $('

')
				.appendTo("body");

			freeze.html(repl('

%(msg)s

',
				{msg: msg || ""}));

			setTimeout(function() {
				freeze.addClass("in");
			}, 1);

		} else {
			$("#freeze").addClass("in");
		}
		frappe.freeze_count++;
	},
	unfreeze: function() {
		if(!frappe.freeze_count) return; // anything open?
		frappe.freeze_count--;
		if(!frappe.freeze_count) {
			var freeze = $('#freeze').removeClass("in");
			setTimeout(function() {
				if(!frappe.freeze_count) {
					freeze.remove();
				}
			}, 150);
		}
	},

	trigger_ready: function() {
		frappe.ready_events.forEach(function(fn) {
			fn();
		});
	},

	highlight_code_blocks: function() {
		if(window.hljs) {
			$('pre code').each(function(i, block) {
				hljs.highlightBlock(block);
			});
		}
	},
	bind_filters: function() {
		// set in select
		$(".filter").each(function() {
			var key = $(this).attr("data-key");
			var val = get_url_arg(key).replace(/\+/g, " ");

			if(val) $(this).val(val);
		});

		// search url
		var search = function() {
			var args = {};
			$(".filter").each(function() {
				var val = $(this).val();
				if(val) args[$(this).attr("data-key")] = val;
			});

			window.location.href = location.pathname + "?" + $.param(args);
		};

		$(".filter").on("change", function() {
			search();
		});
	},
	bind_navbar_search: function() {
		frappe.get_navbar_search().on("keypress", function(e) {
			var val = $(this).val();
			if(e.which===13 && val) {
				$(this).val("").blur();
				frappe.do_search(val);
				return false;
			}
		});
	},
	do_search: function(val) {
		var path = (frappe.awesome_bar_path && frappe.awesome_bar_path[location.pathname]
			|| window.search_path || location.pathname);

		window.location.href = path + "?txt=" + encodeURIComponent(val);
	},
	set_search_path: function(path) {
		frappe.awesome_bar_path[location.pathname] = path;
	},
	make_navbar_active: function() {
		var pathname = window.location.pathname;
		$(".navbar-nav a.active").removeClass("active");
		$(".navbar-nav a").each(function() {
			var href = $(this).attr("href");
			if(href===pathname) {
				$(this).addClass("active");
				return false;
			}
		});
	},
	get_navbar_search: function() {
		return $(".navbar .search, .sidebar .search");
	},
	is_user_logged_in: function() {
		return window.full_name ? true : false;
	},
	add_switch_to_desk: function() {
		$('.switch-to-desk').removeClass('hidden');
	}
});

// Utility functions

function valid_email(id) {
	// eslint-disable-next-line
	return (id.toLowerCase().search("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")==-1) ? 0 : 1;
}

window.validate_email = valid_email;

function cstr(s) {
	return s==null ? '' : s+'';
}

window.is_null = function is_null(v) {
	if(v===null || v===undefined || cstr(v).trim()==="") return true;
};

window.is_html = function is_html(txt) {
	if(txt.indexOf("
")==-1 && txt.indexOf("<p")==-1
		&& txt.indexOf("<img")==-1 && txt.indexOf("<div")==-1) {
		return false;
	}
	return true;
};

window.ask_to_login = function ask_to_login() {
	if(!frappe.is_user_logged_in()) {
		if(localStorage) {
			localStorage.setItem("last_visited",
				window.location.href.replace(window.location.origin, ""));
		}
		window.location.href = "login";
	}
};

// check if logged in?
$(document).ready(function() {
	window.full_name = frappe.get_cookie("full_name");
	var logged_in = frappe.get_cookie("sid") && frappe.get_cookie("sid") !== "Guest";
	$("#website-login").toggleClass("hide", logged_in ? true : false);
	$("#website-post-login").toggleClass("hide", logged_in ? false : true);
	$(".logged-in").toggleClass("hide", logged_in ? false : true);

	frappe.bind_navbar_search();

	// switch to app link
	if(frappe.get_cookie("system_user")==="yes" && logged_in) {
		frappe.add_switch_to_desk();
	}

	frappe.render_user();

	$(document).trigger("page-change");
});

$(document).on("page-change", function() {
	$(document).trigger("apply_permissions");
	$('.dropdown-toggle').dropdown();

	//multilevel dropdown fix
	$('.dropdown-menu .dropdown-submenu .dropdown-toggle').on('click', function(e) {
		e.stopPropagation();
		$(this).parent().parent().parent().addClass('open');
	});

	$.extend(frappe, frappe.get_cookies());
	frappe.session = {'user': frappe.user_id};

	frappe.datetime.refresh_when();
	frappe.trigger_ready();
	frappe.bind_filters();
	frappe.highlight_code_blocks();
	frappe.make_navbar_active();
	// scroll to hash
	if (window.location.hash) {
		var element = document.getElementById(window.location.hash.substring(1));
		element && element.scrollIntoView(true);
	}
});

$(document).ready(function( ) {
	// frappe.Chat
	// const chat = new frappe.Chat();
	// chat.render();
	// end frappe.Chat
});<commit_msg>[fix] globals<commit_after>// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
/* eslint-disable no-console */

frappe.provide("website");
frappe.provide("frappe.awesome_bar_path");
window.cur_frm = null;

$.extend(frappe, {
	boot: {
		lang: 'en'
	},
	_assets_loaded: [],
	require: function(url) {
		if(frappe._assets_loaded.indexOf(url)!==-1) return;
		return $.ajax({
			url: url,
			async: false,
			dataType: "text",
			success: function(data) {
				var el;
				if(url.split(".").splice(-1) == "js") {
					el = document.createElement('script');
				} else {
					el = document.createElement('style');
				}
				el.appendChild(document.createTextNode(data));
				document.getElementsByTagName('head')[0].appendChild(el);
				frappe._assets_loaded.push(url);
			}
		});
	},
	hide_message: function() {
		$('.message-overlay').remove();
	},
	call: function(opts) {
		// opts = {"method": "PYTHON MODULE STRING", "args": {}, "callback": function(r) {}}
		if (typeof arguments[0]==='string') {
			opts = {
				method: arguments[0],
				args: arguments[1],
				callback: arguments[2]
			}
		}

		frappe.prepare_call(opts);
		if(opts.freeze) {
			frappe.freeze();
		}
		return $.ajax({
			type: opts.type || "POST",
			url: "/",
			data: opts.args,
			dataType: "json",
			headers: { "X-Frappe-CSRF-Token": frappe.csrf_token },
			statusCode: opts.statusCode || {
				404: function() {
					frappe.msgprint(__("Not found"));
				},
				403: function() {
					frappe.msgprint(__("Not permitted"));
				},
				200: function(data) {
					if(opts.callback)
						opts.callback(data);
					if(opts.success)
						opts.success(data);
				}
			}
		}).always(function(data) {
			if(opts.freeze) {
				frappe.unfreeze();
			}

			// executed before statusCode functions
			if(data.responseText) {
				try {
					data = JSON.parse(data.responseText);
				} catch (e) {
					data = {};
				}
			}
			frappe.process_response(opts, data);
		});
	},
	prepare_call: function(opts) {
		if(opts.btn) {
			$(opts.btn).prop("disabled", true);
		}

		if(opts.msg) {
			$(opts.msg).toggle(false);
		}

		if(!opts.args) opts.args = {};

		// method
		if(opts.method) {
			opts.args.cmd = opts.method;
		}

		// stringify
		$.each(opts.args, function(key, val) {
			if(typeof val != "string") {
				opts.args[key] = JSON.stringify(val);
			}
		});

		if(!opts.no_spinner) {
			//NProgress.start();
		}
	},
	process_response: function(opts, data) {
		//if(!opts.no_spinner) NProgress.done();

		if(opts.btn) {
			$(opts.btn).prop("disabled", false);
		}

		if (data._server_messages) {
			var server_messages = JSON.parse(data._server_messages || '[]');
			server_messages = $.map(server_messages, function(v) {
				// temp fix for messages sent as dict
				try {
					return JSON.parse(v).message;
				} catch (e) {
					return v;
				}
			}).join('
');

			if(opts.error_msg) {
				$(opts.error_msg).html(server_messages).toggle(true);
			} else {
				frappe.msgprint(server_messages);
			}
		}

		if(data.exc) {
			// if(opts.btn) {
			// 	$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-danger" : "text-danger");
			// 	setTimeout(function() { $(opts.btn).removeClass("btn-danger text-danger"); }, 1000);
			// }
			try {
				var err = JSON.parse(data.exc);
				if($.isArray(err)) {
					err = err.join("\n");
				}
				console.error ? console.error(err) : console.log(err);
			} catch(e) {
				console.log(data.exc);
			}

		} else{
			// if(opts.btn) {
			// 	$(opts.btn).addClass($(opts.btn).is('button') || $(opts.btn).hasClass('btn') ? "btn-success" : "text-success");
			// 	setTimeout(function() { $(opts.btn).removeClass("btn-success text-success"); }, 1000);
			// }
		}
		if(opts.msg && data.message) {
			$(opts.msg).html(data.message).toggle(true);
		}

		if(opts.always) {
			opts.always(data);
		}
	},
	show_message: function(text, icon) {
		if(!icon) icon="fa fa-refresh fa-spin";
		frappe.hide_message();
		$('

')
			.html('

'
				+text+'
').appendTo(document.body);
	},
	get_sid: function() {
		var sid = frappe.get_cookie("sid");
		return sid && sid !== "Guest";
	},
	get_modal: function(title, body_html) {
		var modal = $('
\

\

\

\
						×\

'+title+'
\

\

'+body_html+'\

\

\

\

').appendTo(document.body);

		return modal;
	},
	msgprint: function(html, title) {
		if(html.substr(0,1)==="[") html = JSON.parse(html);
		if($.isArray(html)) {
			html = html.join("
");
		}

		return frappe.get_modal(title || "Message", html).modal("show");
	},
	send_message: function(opts, btn) {
		return frappe.call({
			type: "POST",
			method: "frappe.www.contact.send_message",
			btn: btn,
			args: opts,
			callback: opts.callback
		});
	},
	has_permission: function(doctype, docname, perm_type, callback) {
		return frappe.call({
			type: "GET",
			method: "frappe.client.has_permission",
			no_spinner: true,
			args: {doctype: doctype, docname: docname, perm_type: perm_type},
			callback: function(r) {
				if(!r.exc && r.message.has_permission) {
					if(callback) {
						return callback(r);
					}
				}
			}
		});
	},
	render_user: function() {
		var sid = frappe.get_cookie("sid");
		if(sid && sid!=="Guest") {
			$(".btn-login-area").toggle(false);
			$(".logged-in").toggle(true);
			$(".full-name").html(frappe.get_cookie("full_name"));
			$(".user-image").attr("src", frappe.get_cookie("user_image"));

			$('.user-image-wrapper').html(frappe.avatar(null, 'avatar-small'));
			$('.user-image-sidebar').html(frappe.avatar(null, 'avatar-small'));
			$('.user-image-myaccount').html(frappe.avatar(null, 'avatar-large'));
		}
	},
	freeze_count: 0,
	freeze: function(msg) {
		// blur
		if(!$('#freeze').length) {
			var freeze = $('

')
				.appendTo("body");

			freeze.html(repl('

%(msg)s

',
				{msg: msg || ""}));

			setTimeout(function() {
				freeze.addClass("in");
			}, 1);

		} else {
			$("#freeze").addClass("in");
		}
		frappe.freeze_count++;
	},
	unfreeze: function() {
		if(!frappe.freeze_count) return; // anything open?
		frappe.freeze_count--;
		if(!frappe.freeze_count) {
			var freeze = $('#freeze').removeClass("in");
			setTimeout(function() {
				if(!frappe.freeze_count) {
					freeze.remove();
				}
			}, 150);
		}
	},

	trigger_ready: function() {
		frappe.ready_events.forEach(function(fn) {
			fn();
		});
	},

	highlight_code_blocks: function() {
		if(window.hljs) {
			$('pre code').each(function(i, block) {
				hljs.highlightBlock(block);
			});
		}
	},
	bind_filters: function() {
		// set in select
		$(".filter").each(function() {
			var key = $(this).attr("data-key");
			var val = frappe.utils.get_url_arg(key).replace(/\+/g, " ");

			if(val) $(this).val(val);
		});

		// search url
		var search = function() {
			var args = {};
			$(".filter").each(function() {
				var val = $(this).val();
				if(val) args[$(this).attr("data-key")] = val;
			});

			window.location.href = location.pathname + "?" + $.param(args);
		};

		$(".filter").on("change", function() {
			search();
		});
	},
	bind_navbar_search: function() {
		frappe.get_navbar_search().on("keypress", function(e) {
			var val = $(this).val();
			if(e.which===13 && val) {
				$(this).val("").blur();
				frappe.do_search(val);
				return false;
			}
		});
	},
	do_search: function(val) {
		var path = (frappe.awesome_bar_path && frappe.awesome_bar_path[location.pathname]
			|| window.search_path || location.pathname);

		window.location.href = path + "?txt=" + encodeURIComponent(val);
	},
	set_search_path: function(path) {
		frappe.awesome_bar_path[location.pathname] = path;
	},
	make_navbar_active: function() {
		var pathname = window.location.pathname;
		$(".navbar-nav a.active").removeClass("active");
		$(".navbar-nav a").each(function() {
			var href = $(this).attr("href");
			if(href===pathname) {
				$(this).addClass("active");
				return false;
			}
		});
	},
	get_navbar_search: function() {
		return $(".navbar .search, .sidebar .search");
	},
	is_user_logged_in: function() {
		return window.full_name ? true : false;
	},
	add_switch_to_desk: function() {
		$('.switch-to-desk').removeClass('hidden');
	}
});

// Utility functions

window.valid_email = function(id) {
	// eslint-disable-next-line
	return (id.toLowerCase().search("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")==-1) ? 0 : 1;
}

window.validate_email = valid_email;

window.cstr = function(s) {
	return s==null ? '' : s+'';
}

window.is_null = function is_null(v) {
	if(v===null || v===undefined || cstr(v).trim()==="") return true;
};

window.is_html = function is_html(txt) {
	if(txt.indexOf("
")==-1 && txt.indexOf("<p")==-1
		&& txt.indexOf("<img")==-1 && txt.indexOf("<div")==-1) {
		return false;
	}
	return true;
};

window.ask_to_login = function ask_to_login() {
	if(!frappe.is_user_logged_in()) {
		if(localStorage) {
			localStorage.setItem("last_visited",
				window.location.href.replace(window.location.origin, ""));
		}
		window.location.href = "login";
	}
};

// check if logged in?
$(document).ready(function() {
	window.full_name = frappe.get_cookie("full_name");
	var logged_in = frappe.get_cookie("sid") && frappe.get_cookie("sid") !== "Guest";
	$("#website-login").toggleClass("hide", logged_in ? true : false);
	$("#website-post-login").toggleClass("hide", logged_in ? false : true);
	$(".logged-in").toggleClass("hide", logged_in ? false : true);

	frappe.bind_navbar_search();

	// switch to app link
	if(frappe.get_cookie("system_user")==="yes" && logged_in) {
		frappe.add_switch_to_desk();
	}

	frappe.render_user();

	$(document).trigger("page-change");
});

$(document).on("page-change", function() {
	$(document).trigger("apply_permissions");
	$('.dropdown-toggle').dropdown();

	//multilevel dropdown fix
	$('.dropdown-menu .dropdown-submenu .dropdown-toggle').on('click', function(e) {
		e.stopPropagation();
		$(this).parent().parent().parent().addClass('open');
	});

	$.extend(frappe, frappe.get_cookies());
	frappe.session = {'user': frappe.user_id};

	frappe.datetime.refresh_when();
	frappe.trigger_ready();
	frappe.bind_filters();
	frappe.highlight_code_blocks();
	frappe.make_navbar_active();
	// scroll to hash
	if (window.location.hash) {
		var element = document.getElementById(window.location.hash.substring(1));
		element && element.scrollIntoView(true);
	}
});

$(document).ready(function( ) {
	// frappe.Chat
	// const chat = new frappe.Chat();
	// chat.render();
	// end frappe.Chat
});<|endoftext|>


<commit_before>/* jshint node: true */
var path = require("path"),
    fineUploaderModules = require("../../modules");

module.exports = function(paths) {
    "use strict";

    return {
        options: {
            banner: "(function(global) {\n",
            footer:
                "if (typeof define === 'function' && define.amd) {\n" +
                "   define(function() {\n" +
                "       return qq;\n" +
                "   });\n" +
                "}\n" +
                "else if (typeof module !== 'undefined' && module.exports) {\n" +
                "   module.exports = qq;\n" +
                "}\n" +
                "else {\n" +
                "   global.qq = qq;\n" +
                "}\n" +
                "}(window));\n"
        },
        core: {
            src: fineUploaderModules.mergeModules(true, "fuTraditional"),
            dest: "" + paths.build + "/<%= pkg.name %>.js"
        },
        coreS3: {
            src: fineUploaderModules.mergeModules(true, "fuS3"),
            dest: "" + paths.build + "/s3.<%= pkg.name %>.js"
        },
        coreAzure: {
            src: fineUploaderModules.mergeModules(true, "fuAzure"),
            dest: "" + paths.build + "/azure.<%= pkg.name %>.js"
        },
        jquery: {
            src: fineUploaderModules.mergeModules(true, "fuTraditionalJquery"),
            dest: "" + paths.build + "/jquery.<%= pkg.name %>.js"
        },
        jqueryS3: {
            src: fineUploaderModules.mergeModules(true, "fuS3Jquery"),
            dest: "" + paths.build + "/s3.jquery.<%= pkg.name %>.js"
        },
        jqueryAzure: {
            src: fineUploaderModules.mergeModules(true, "fuAzureJquery"),
            dest: "" + paths.build + "/azure.jquery.<%= pkg.name %>.js"
        },
        all: {
            src: fineUploaderModules.mergeModules(true, "fuAll"),
            dest: paths.build + "/all.<%= pkg.name %>.js"
        },
        css: {
            src: fineUploaderModules.mergeModules(true, "fuCss"),
            dest: "" + paths.build + "/<%= pkg.name %>-new.css"
        },
        cssGallery: {
            src: fineUploaderModules.mergeModules(true, "fuCssGallery"),
            dest: "" + paths.build + "/<%= pkg.name %>-gallery.css"
        },
        cssLegacy: {
            src: fineUploaderModules.mergeModules(true, "fuCssLegacy"),
            dest: "" + paths.build + "/<%= pkg.name %>.css"
        }
    };
};
<commit_msg>refactor(concat.js): cleanup banner/footer for bundles #789<commit_after>/* jshint node: true */
var path = require("path"),
    fineUploaderModules = require("../../modules");

module.exports = function(paths) {
    "use strict";

    return {
        options: {
            banner: (
                "(function(global) {\n"
            ),
            footer: (
                "if (typeof define === 'function' && define.amd) {\n" +
                "   define(function() {\n" +
                "       return qq;\n" +
                "   });\n" +
                "}\n" +
                "else if (typeof module !== 'undefined' && module.exports) {\n" +
                "   module.exports = qq;\n" +
                "}\n" +
                "else {\n" +
                "   global.qq = qq;\n" +
                "}\n" +
                "}(window));\n"
            )
        },
        core: {
            src: fineUploaderModules.mergeModules(true, "fuTraditional"),
            dest: "" + paths.build + "/<%= pkg.name %>.js"
        },
        coreS3: {
            src: fineUploaderModules.mergeModules(true, "fuS3"),
            dest: "" + paths.build + "/s3.<%= pkg.name %>.js"
        },
        coreAzure: {
            src: fineUploaderModules.mergeModules(true, "fuAzure"),
            dest: "" + paths.build + "/azure.<%= pkg.name %>.js"
        },
        jquery: {
            src: fineUploaderModules.mergeModules(true, "fuTraditionalJquery"),
            dest: "" + paths.build + "/jquery.<%= pkg.name %>.js"
        },
        jqueryS3: {
            src: fineUploaderModules.mergeModules(true, "fuS3Jquery"),
            dest: "" + paths.build + "/s3.jquery.<%= pkg.name %>.js"
        },
        jqueryAzure: {
            src: fineUploaderModules.mergeModules(true, "fuAzureJquery"),
            dest: "" + paths.build + "/azure.jquery.<%= pkg.name %>.js"
        },
        all: {
            src: fineUploaderModules.mergeModules(true, "fuAll"),
            dest: paths.build + "/all.<%= pkg.name %>.js"
        },
        css: {
            src: fineUploaderModules.mergeModules(true, "fuCss"),
            dest: "" + paths.build + "/<%= pkg.name %>-new.css"
        },
        cssGallery: {
            src: fineUploaderModules.mergeModules(true, "fuCssGallery"),
            dest: "" + paths.build + "/<%= pkg.name %>-gallery.css"
        },
        cssLegacy: {
            src: fineUploaderModules.mergeModules(true, "fuCssLegacy"),
            dest: "" + paths.build + "/<%= pkg.name %>.css"
        }
    };
};
<|endoftext|>


<commit_before>import React, { isValidElement, cloneElement } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import icBEM from './utils/icBEM';
import prefixClass from './utils/prefixClass';

import Icon from './Icon';
import Overlay from './Overlay';
import escapable from './mixins/escapable';
import renderToLayer from './mixins/renderToLayer';

import './styles/Popup.scss';

export const COMPONENT_NAME = prefixClass('popup');
const ROOT_BEM = icBEM(COMPONENT_NAME);
const BEM = {
    root: ROOT_BEM,
    container: ROOT_BEM.element('container'),
    body: ROOT_BEM.element('body'),
    message: ROOT_BEM.element('message'),
    button: ROOT_BEM.element('button'),
    buttonsGroup: ROOT_BEM.element('buttons-group')
};

/**
 * Render popup's icon
 *
 * @param  {String|Element} icon
 * @return {Element}
 */
function renderPopupIcon(icon) {
    if (!icon) {
        return null;
    }

    if (typeof icon === 'string') {
        return <Icon large type={icon} />;
    }

    return icon;
}

/**
 * Render popup's message
 *
 * @param  {Element|String} message
 * @return {Element}
 */
function renderPopupMessage(message) {
    if (!message) {
        return null;
    }

    return (

            {message}

    );
}

/**
 * Render popup's buttons
 *
 * @param  {Array} buttons
 * @return {Array}
 */
function renderPopupButtons(buttons) {
    if (!buttons || buttons.length === 0) {
        return null;
    }

    const popupButtons = buttons.map((button) => {
        // Render as expanded button
        if (isValidElement(button)) {
            return cloneElement(button, {
                className: `${BEM.button}`,
                align: 'center',
                minified: false
            });
        }

        return button;
    });

    return (

            {popupButtons}

    );
}

function Popup({
    icon,
    message,
    buttons,
    // React props
    className,
    children,
    ...popupProps
}) {
    const rootClassName = classNames(className, `${BEM.root}`);

    return (

            <Overlay />

                    {renderPopupIcon(icon)}
                    {renderPopupMessage(message)}

                {renderPopupButtons(buttons)}
                {children}

    );
}

Popup.propTypes = {
    icon: PropTypes.node,
    message: PropTypes.node,
    buttons: PropTypes.arrayOf(PropTypes.element)
};

Popup.defaultProps = {
    icon: null,
    message: null,
    buttons: []
};

// export for tests
export { Popup as PurePopup };
export const EscapablePopup = escapable(Popup);

export default renderToLayer(EscapablePopup);
<commit_msg>[Popup] Set 'blue' as icon default color<commit_after>import React, { isValidElement, cloneElement } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import icBEM from './utils/icBEM';
import prefixClass from './utils/prefixClass';

import Icon from './Icon';
import Overlay from './Overlay';
import escapable from './mixins/escapable';
import renderToLayer from './mixins/renderToLayer';

import './styles/Popup.scss';

export const COMPONENT_NAME = prefixClass('popup');
const ROOT_BEM = icBEM(COMPONENT_NAME);
const BEM = {
    root: ROOT_BEM,
    container: ROOT_BEM.element('container'),
    body: ROOT_BEM.element('body'),
    message: ROOT_BEM.element('message'),
    button: ROOT_BEM.element('button'),
    buttonsGroup: ROOT_BEM.element('buttons-group')
};

/**
 * Render popup's icon
 *
 * @param  {String|Element} icon
 * @return {Element}
 */
function renderPopupIcon(icon) {
    if (!icon) {
        return null;
    }

    if (typeof icon === 'string') {
        return (
            <Icon
                large
                color="blue"
                type={icon} />
        );
    }

    return icon;
}

/**
 * Render popup's message
 *
 * @param  {Element|String} message
 * @return {Element}
 */
function renderPopupMessage(message) {
    if (!message) {
        return null;
    }

    return (

            {message}

    );
}

/**
 * Render popup's buttons
 *
 * @param  {Array} buttons
 * @return {Array}
 */
function renderPopupButtons(buttons) {
    if (!buttons || buttons.length === 0) {
        return null;
    }

    const popupButtons = buttons.map((button) => {
        // Render as expanded button
        if (isValidElement(button)) {
            return cloneElement(button, {
                className: `${BEM.button}`,
                align: 'center',
                minified: false
            });
        }

        return button;
    });

    return (

            {popupButtons}

    );
}

function Popup({
    icon,
    message,
    buttons,
    // React props
    className,
    children,
    ...popupProps
}) {
    const rootClassName = classNames(className, `${BEM.root}`);

    return (

            <Overlay />

                    {renderPopupIcon(icon)}
                    {renderPopupMessage(message)}

                {renderPopupButtons(buttons)}
                {children}

    );
}

Popup.propTypes = {
    icon: PropTypes.node,
    message: PropTypes.node,
    buttons: PropTypes.arrayOf(PropTypes.element)
};

Popup.defaultProps = {
    icon: null,
    message: null,
    buttons: []
};

// export for tests
export { Popup as PurePopup };
export const EscapablePopup = escapable(Popup);

export default renderToLayer(EscapablePopup);
<|endoftext|>


<commit_before>import {DOMSerializer} from "prosemirror-model"
import {RenderCitations} from "../../../citations/render"
import {docCopySchema, fnCopySchema} from "./schema"

// Wrap around DOMSerializer, allowing post processing.
class ClipboardDOMSerializer {
    constructor(nodes, marks, editor) {
        this.domSerializer = new DOMSerializer(nodes, marks)
        this.editor = editor
    }

    serializeFragment(fragment, options) {
        const domFragment = this.domSerializer.serializeFragment(fragment, options)
        return this.postProcessFragment(domFragment)
    }

    postProcessFragment(domFragment) {
        const citationFormatter = this.renderCitations(domFragment)
        this.renderFootnotes(domFragment, citationFormatter)
        this.removeTrackingData(domFragment)
        return domFragment
    }

    renderCitations(domFragment) {
        const citRenderer = new RenderCitations(
            domFragment,
            this.editor.view.state.doc.firstChild.attrs.citationstyle,
            this.editor.mod.db.bibDB,
            this.editor.mod.styles.citationStyles,
            this.editor.mod.styles.citationLocales
        )
        citRenderer.init()
        citRenderer.renderCitations()
        if (citRenderer.fm.bibHTML.length) {
            let bibDiv = document.createElement('div')
            bibDiv.classList.add('fiduswriter-clipboard-bibliography')
            bibDiv.innerHTML = citRenderer.fm.bibHTML
            bibDiv.firstElementChild.innerHTML = gettext('Bibliography')
            domFragment.appendChild(bibDiv)
        }
        return citRenderer.fm
    }

    renderFootnotes(domFragment, citationFormatter) {
        const footnoteSelector = citationFormatter.citationType === 'note' ?
            '.footnote-marker, .citation' :
            '.footnote-marker'
        // Inside of footnote markers add anchors and put footnotes with contents
        // at the back of the document.
        // Also, link the footnote anchor with the footnote.
        const footnotes = domFragment.querySelectorAll(footnoteSelector)
        const footnotesContainer = document.createElement('section')
        let citationCount = 0
        footnotesContainer.id = 'fnlist'
        footnotesContainer.setAttribute('role', 'doc-footnotes')
        footnotesContainer.classList.add('fiduswriter-clipboard-footnotes')
        footnotes.forEach(
            (footnote, index) => {
                const counter = index + 1, id = this.getRandomID()
                const footnoteAnchor = this.getFootnoteAnchor(counter, id)
                footnote.appendChild(footnoteAnchor)
                const newFootnote = document.createElement('h6') // We use H6 as Wordpress Gutenberg only allows IDs on H1-6 elements.
                newFootnote.setAttribute('role', 'doc-footnote')
                newFootnote.innerHTML = footnote.matches('.footnote-marker') ?
                    footnote.dataset.footnote :
                    `<p>${citationFormatter.citationTexts[citationCount++] || " "}</p>`
                if (newFootnote.firstElementChild && newFootnote.firstElementChild.matches('p')) {
                    newFootnote.firstElementChild.insertAdjacentHTML('afterbegin', `${counter}. `)
                } else {
                    newFootnote.insertAdjacentHTML('afterbegin', `<p>${counter}. </p>`)
                }
                newFootnote.id = `fn-${id}`
                footnotesContainer.appendChild(newFootnote)
            }
        )
        if (footnotes.length) {
            domFragment.appendChild(footnotesContainer)
        }
    }

    getRandomID() {
        return (0|Math.random()*9e6).toString(36)
    }

    getFootnoteAnchor(counter, id) {
        const footnoteAnchor = document.createElement('a')
        footnoteAnchor.setAttribute('href',`#fn-${id}`)
        footnoteAnchor.classList.add('fn')
        footnoteAnchor.innerHTML = `<sup>${counter}</sup>`
        return footnoteAnchor
    }

    removeTrackingData(domFragment) {
        domFragment.querySelectorAll('.approved-insertion, .insertion').forEach(el => el.outerHTML = el.innerHTML)
        domFragment.querySelectorAll('.deletion').forEach(el => el.parentElement.remoChild(el))
    }

    static fromSchema(schema, editor) {
        return new ClipboardDOMSerializer(
            DOMSerializer.nodesFromSchema(schema),
            DOMSerializer.marksFromSchema(schema),
            editor
        )
    }
}

export const docClipboardSerializer = editor => ClipboardDOMSerializer.fromSchema(docCopySchema, editor)
export const fnClipboardSerializer = editor => ClipboardDOMSerializer.fromSchema(fnCopySchema, editor)
<commit_msg>add figure data<commit_after>import {DOMSerializer} from "prosemirror-model"
import {RenderCitations} from "../../../citations/render"
import {docCopySchema, fnCopySchema} from "./schema"

// Wrap around DOMSerializer, allowing post processing.
class ClipboardDOMSerializer {
    constructor(nodes, marks, editor) {
        this.domSerializer = new DOMSerializer(nodes, marks)
        this.editor = editor
    }

    serializeFragment(fragment, options) {
        const domFragment = this.domSerializer.serializeFragment(fragment, options)
        return this.postProcessFragment(domFragment)
    }

    postProcessFragment(domFragment) {
        const citationFormatter = this.renderCitations(domFragment)
        this.renderFootnotes(domFragment, citationFormatter)
        this.removeTrackingData(domFragment)
        this.addBaseUrlToImages(domFragment)
        this.addFigureNumbers(domFragment)
        return domFragment
    }

    renderCitations(domFragment) {
        const citRenderer = new RenderCitations(
            domFragment,
            this.editor.view.state.doc.firstChild.attrs.citationstyle,
            this.editor.mod.db.bibDB,
            this.editor.mod.styles.citationStyles,
            this.editor.mod.styles.citationLocales
        )
        citRenderer.init()
        citRenderer.renderCitations()
        if (citRenderer.fm.bibHTML.length) {
            let bibDiv = document.createElement('div')
            bibDiv.classList.add('fiduswriter-clipboard-bibliography')
            bibDiv.innerHTML = citRenderer.fm.bibHTML
            bibDiv.firstElementChild.innerHTML = gettext('Bibliography')
            domFragment.appendChild(bibDiv)
        }
        return citRenderer.fm
    }

    renderFootnotes(domFragment, citationFormatter) {
        const footnoteSelector = citationFormatter.citationType === 'note' ?
            '.footnote-marker, .citation' :
            '.footnote-marker'
        // Inside of footnote markers add anchors and put footnotes with contents
        // at the back of the document.
        // Also, link the footnote anchor with the footnote.
        const footnotes = domFragment.querySelectorAll(footnoteSelector)
        const footnotesContainer = document.createElement('section')
        let citationCount = 0
        footnotesContainer.id = 'fnlist'
        footnotesContainer.setAttribute('role', 'doc-footnotes')
        footnotesContainer.classList.add('fiduswriter-clipboard-footnotes')
        footnotes.forEach(
            (footnote, index) => {
                const counter = index + 1, id = this.getRandomID()
                const footnoteAnchor = this.getFootnoteAnchor(counter, id)
                footnote.appendChild(footnoteAnchor)
                const newFootnote = document.createElement('h6') // We use H6 as Wordpress Gutenberg only allows IDs on H1-6 elements.
                newFootnote.setAttribute('role', 'doc-footnote')
                newFootnote.innerHTML = footnote.matches('.footnote-marker') ?
                    footnote.dataset.footnote :
                    `<p>${citationFormatter.citationTexts[citationCount++] || " "}</p>`
                if (newFootnote.firstElementChild && newFootnote.firstElementChild.matches('p')) {
                    newFootnote.firstElementChild.insertAdjacentHTML('afterbegin', `${counter}. `)
                } else {
                    newFootnote.insertAdjacentHTML('afterbegin', `<p>${counter}. </p>`)
                }
                newFootnote.id = `fn-${id}`
                footnotesContainer.appendChild(newFootnote)
            }
        )
        if (footnotes.length) {
            domFragment.appendChild(footnotesContainer)
        }
    }

    addFigureNumbers(domFragment) {
        domFragment.querySelectorAll('figcaption .figure-cat-figure').forEach(
            (el, index) => {
                el.innerHTML += ' ' + (index + 1) + ': '
            }
        )

        domFragment.querySelectorAll('figcaption .figure-cat-photo').forEach(
            (el, index) => {
                el.innerHTML += ' ' + (index + 1) + ': '
            }
        )

        domFragment.querySelectorAll('figcaption .figure-cat-table').forEach(
            (el, index) => {
                el.innerHTML += ' ' + (index + 1) + ': '
            }
        )
    }

    addBaseUrlToImages(domFragment) {
        domFragment.querySelectorAll('img').forEach(el => el.setAttribute('src', el.src))
    }

    getRandomID() {
        return (0|Math.random()*9e6).toString(36)
    }

    getFootnoteAnchor(counter, id) {
        const footnoteAnchor = document.createElement('a')
        footnoteAnchor.setAttribute('href',`#fn-${id}`)
        footnoteAnchor.classList.add('fn')
        footnoteAnchor.innerHTML = `<sup>${counter}</sup>`
        return footnoteAnchor
    }

    removeTrackingData(domFragment) {
        domFragment.querySelectorAll('.approved-insertion, .insertion').forEach(el => el.outerHTML = el.innerHTML)
        domFragment.querySelectorAll('.deletion').forEach(el => el.parentElement.remoChild(el))
    }

    static fromSchema(schema, editor) {
        return new ClipboardDOMSerializer(
            DOMSerializer.nodesFromSchema(schema),
            DOMSerializer.marksFromSchema(schema),
            editor
        )
    }
}

export const docClipboardSerializer = editor => ClipboardDOMSerializer.fromSchema(docCopySchema, editor)
export const fnClipboardSerializer = editor => ClipboardDOMSerializer.fromSchema(fnCopySchema, editor)
<|endoftext|>


<commit_before>/*
* Copyright (c) 2013 DataTorrent, Inc. ALL Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var _ = require('underscore');
var kt = require('knights-templar');
var Notifier = require('../Notifier');
var BaseView = require('bassview');
var SingleFileUploadView = require('./SingleFileUploadView');

/**
 * UploadFilesView
 *
 * View in FileListWidget for uploading file(s).
 *
 * Usage:
 *
 *     var view = new UploadFilesView({
 *
 *         // Files must be DT.lib.UploadFileCollection
 *         // or a child class. Will hold all new files
 *         collection: new UploadFileCollection([]),
 *
 *         // optional: another UploadFileCollection
 *         // or child,
 *         uploaded: myUploadedFiles // optional
 *     });
 *
 *     $('body').append(view.render().el);
 *
 * The 'collection' should be empty at
 * Pass an 'uploaded' collection to test for overwrites.
 *
*/
var UploadFilesView = BaseView.extend({

    initialize: function(options) {

        this.uploaded = options.uploaded;

        // Listen for upload progress and complete on the model
        this.listenTo(this.collection, 'reset', this.render);
        this.listenTo(this.collection, 'remove', function(model, collection) {
            if (collection.length === 0) {
                this.render();
            }
        });
    },

    FileView: SingleFileUploadView,

    // file type restrictions
    // eg. ['.jar','.zip']
    accept: [],

    multiple: true,

    uploadBtnConfirm: 'upload',

    uploadBtnCancel: 'cancel',

    uploadTitle: 'drag and drop files here',

    uploadText: '(click to choose files)',

    events: {
        'change .file_upload': 'onFileChange',
        'click .file_upload_target': 'onClick',
        'dragover .file_upload_target': 'onDragOver',
        'drop .file_upload_target': 'onDrop',
        'click .cancel_file_btn': 'clearFiles',
        'click .upload_file_btn': 'uploadFiles',
        'click .file-to-upload': function(evt) {
            evt.stopPropagation();
        },
        'submit .file_upload_form': 'preventDefault'
    },

    render: function() {

        var html = this.template({
            files: this.collection.toJSON(),
            accept: this.accept.join(','),
            multiple: _.result(this, 'multiple'),
            uploadTitle: _.result(this, 'uploadTitle'),
            uploadText: _.result(this, 'uploadText'),
            uploadBtnConfirm: _.result(this, 'uploadBtnConfirm'),
            uploadBtnCancel: _.result(this, 'uploadBtnCancel')
        });
        this.$el.html(html);
        var $files = this.$('.files-to-upload');
        this.collection.each(function(file) {

            // Create view for individual file
            var view = new this.FileView({
                model: file,
                collection: this.collection,
                uploaded: this.uploaded
            });

            // Append single view to this view
            $files.append(view.render().el);

        }, this);

        return this;
    },

    onFileChange: function() {

        var files = this.el.querySelector('.file_upload').files;

        var filteredFiles = [];

        var hasFileChangeCheck = typeof this.fileChangeCheck === 'function';

        for (var i = files.length - 1; i >= 0; i--) {

            var file = files[i];

            if (hasFileChangeCheck) {
                var passed = this.fileChangeCheck(file);
                if (!passed) {
                    this.render();
                    return;
                }
            }

            filteredFiles.push({
                'name': file.name,
                'size': file.size,
                'type': file.type,
                'file': file
            });
        }

        this.collection.reset(filteredFiles, { remove: true });
    },

    onClick: function() {

        this.el.querySelector('.file_upload').click();

    },

    onDragOver: function(evt) {
        evt.preventDefault();
    },

    onDrop: function(evt) {
        evt.preventDefault();
        evt.stopPropagation();

        // Get the file dropped
        var files = evt.originalEvent.dataTransfer.files;

        // Set them to the input.files object
        this.el.querySelector('.file_upload').files = files;
    },

    onProgress: function(progress) {
        var bar = this.$('.file_upload_progress');

        bar.css('width', progress + '%');

        if (progress === 100) {
            bar.removeClass('progress-striped').removeClass('active');
        }
    },

    onSuccess: function(file) {
        // clear out the model
        this.model.clear();
        // notify success
        Notifier.success({
            'title': 'Successfully uploaded file',
            'text': 'It should be visible on the list of uploaded file.'
        });

        // remove buttons
        this.$('.upload-buttons').html('');
        this.$('.file_upload_target .progress').removeClass('progress-striped').removeClass('active');

        // render and clear
        setTimeout(_.bind(function() {
            this.render();
        }, this), 2000);
    },

    onComplete: function() {
        this.$('.upload_file_btn').attr('disabled', false);
    },

    onError: function(xhr, err, responseText) {
        this.$('.file_upload_progress').css('width', '0%');
        Notifier.error({
            'title': 'An error occurred uploading file',
            'text': 'Server responded with: ' + responseText
        });
    },

    uploadFiles: function(evt) {
        evt.preventDefault();
        evt.stopPropagation();

        var pending = this.collection.length;

        this.listenTo(this.collection, 'upload_success', function() {
            if (--pending === 0) {
                this.collection.reset([]);
            }
        });

        this.collection.each(function(file) {
            file.upload();
        });
    },

    clearFiles: function(evt) {
        evt.stopPropagation();
        evt.preventDefault();
        this.collection.reset([]);
    },

    preventDefault: function(evt) {
        evt.preventDefault();
    },

    template: kt.make(__dirname+'/UploadFilesView.html','_')

});

exports = module.exports = UploadFilesView;
<commit_msg>improved documentation of upload files view<commit_after>/*
* Copyright (c) 2013 DataTorrent, Inc. ALL Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var _ = require('underscore');
var kt = require('knights-templar');
var Notifier = require('../Notifier');
var BaseView = require('bassview');
var SingleFileUploadView = require('./SingleFileUploadView');

/**
 * UploadFilesView
 *
 * View in FileListWidget for uploading file(s).
 *
 * Usage:
 *
 *     var view = new UploadFilesView({
 *         collection: new DT.lib.UploadFileCollection([])
 *     });
 *
 *     $('body').append(view.render().el);
 *
 *
*/
var UploadFilesView = BaseView.extend({

    /**
     * @param  {DT.lib.UploadFileCollection} options.collection  Holds files to be uploaded, and clears on upload success.
     * @param  {DT.lib.UploadFileCollection} options.uploaded    (optional) Reference to files on server to check against for overwrites.
     */
    initialize: function(options) {

        this.uploaded = options.uploaded;

        // Listen for upload progress and complete on the model
        this.listenTo(this.collection, 'reset', this.render);
        this.listenTo(this.collection, 'remove', function(model, collection) {
            if (collection.length === 0) {
                this.render();
            }
        });
    },

    FileView: SingleFileUploadView,

    // file type restrictions
    // eg. ['.jar','.zip']
    accept: [],

    multiple: true,

    uploadBtnConfirm: 'upload',

    uploadBtnCancel: 'cancel',

    uploadTitle: 'drag and drop files here',

    uploadText: '(click to choose files)',

    events: {
        'change .file_upload': 'onFileChange',
        'click .file_upload_target': 'onClick',
        'dragover .file_upload_target': 'onDragOver',
        'drop .file_upload_target': 'onDrop',
        'click .cancel_file_btn': 'clearFiles',
        'click .upload_file_btn': 'uploadFiles',
        'click .file-to-upload': function(evt) {
            evt.stopPropagation();
        },
        'submit .file_upload_form': 'preventDefault'
    },

    render: function() {

        var html = this.template({
            files: this.collection.toJSON(),
            accept: this.accept.join(','),
            multiple: _.result(this, 'multiple'),
            uploadTitle: _.result(this, 'uploadTitle'),
            uploadText: _.result(this, 'uploadText'),
            uploadBtnConfirm: _.result(this, 'uploadBtnConfirm'),
            uploadBtnCancel: _.result(this, 'uploadBtnCancel')
        });
        this.$el.html(html);
        var $files = this.$('.files-to-upload');
        this.collection.each(function(file) {

            // Create view for individual file
            var view = new this.FileView({
                model: file,
                collection: this.collection,
                uploaded: this.uploaded
            });

            // Append single view to this view
            $files.append(view.render().el);

        }, this);

        return this;
    },

    onFileChange: function() {

        var files = this.el.querySelector('.file_upload').files;

        var filteredFiles = [];

        var hasFileChangeCheck = typeof this.fileChangeCheck === 'function';

        for (var i = files.length - 1; i >= 0; i--) {

            var file = files[i];

            if (hasFileChangeCheck) {
                var passed = this.fileChangeCheck(file);
                if (!passed) {
                    this.render();
                    return;
                }
            }

            filteredFiles.push({
                'name': file.name,
                'size': file.size,
                'type': file.type,
                'file': file
            });
        }

        this.collection.reset(filteredFiles, { remove: true });
    },

    onClick: function() {

        this.el.querySelector('.file_upload').click();

    },

    onDragOver: function(evt) {
        evt.preventDefault();
    },

    onDrop: function(evt) {
        evt.preventDefault();
        evt.stopPropagation();

        // Get the file dropped
        var files = evt.originalEvent.dataTransfer.files;

        // Set them to the input.files object
        this.el.querySelector('.file_upload').files = files;
    },

    onProgress: function(progress) {
        var bar = this.$('.file_upload_progress');

        bar.css('width', progress + '%');

        if (progress === 100) {
            bar.removeClass('progress-striped').removeClass('active');
        }
    },

    onSuccess: function(file) {
        // clear out the model
        this.model.clear();
        // notify success
        Notifier.success({
            'title': 'Successfully uploaded file',
            'text': 'It should be visible on the list of uploaded file.'
        });

        // remove buttons
        this.$('.upload-buttons').html('');
        this.$('.file_upload_target .progress').removeClass('progress-striped').removeClass('active');

        // render and clear
        setTimeout(_.bind(function() {
            this.render();
        }, this), 2000);
    },

    onComplete: function() {
        this.$('.upload_file_btn').attr('disabled', false);
    },

    onError: function(xhr, err, responseText) {
        this.$('.file_upload_progress').css('width', '0%');
        Notifier.error({
            'title': 'An error occurred uploading file',
            'text': 'Server responded with: ' + responseText
        });
    },

    uploadFiles: function(evt) {
        evt.preventDefault();
        evt.stopPropagation();

        var pending = this.collection.length;

        this.listenTo(this.collection, 'upload_success', function() {
            if (--pending === 0) {
                this.collection.reset([]);
            }
        });

        this.collection.each(function(file) {
            file.upload();
        });
    },

    clearFiles: function(evt) {
        evt.stopPropagation();
        evt.preventDefault();
        this.collection.reset([]);
    },

    preventDefault: function(evt) {
        evt.preventDefault();
    },

    template: kt.make(__dirname+'/UploadFilesView.html','_')

});

exports = module.exports = UploadFilesView;
<|endoftext|>


<commit_before>/*
 openBD Chrome Extension
 Copyright (c) 2017 CALIL Inc.
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
 */

// 対応サイトの定義
const SITES = [
  {
    url: 'https?://ilisod001.apsel.jp/', // 対象にするURL 正規表現 /(スラッシュ)は\/(バックスラッシュ)付きに置換される
    isbnSelector: document.querySelectorAll('.normal-td'), // ISBNが含まれるエレメント 複数でも可
    targetElement: document.querySelectorAll('.contents')[2], // 書誌情報を挿入するエレメント
    insert: 'after' // after or beofre ターゲットの前後どちらに挿入するか
  },
  {
    url: 'https?://.*?/opac/wopc/pc/pages/SearchResultList.jsp',
    isbnSelector: document.querySelectorAll('.normal-td'),
    targetElement: document.querySelectorAll('.contents')[2],
    insert: 'after'
  },
  {
    url: 'https?://.*?/WebOpac/webopac/searchdetail.do',
    isbnSelector: document.querySelectorAll('#highlight_keyword td'),
    targetElement: document.querySelectorAll('#highlight_keyword')[0],
    insert: 'after'
  },
  {
    url: 'https?://www.amazon.co.jp/?.*?/dp/',
    isbnSelector: document.querySelectorAll('.content li'),
    targetElement: document.querySelectorAll('#productDescription_feature_div')[0],
    insert: 'after'
  },
  {
    url: 'https://calil.jp/book/',
    isbnSelector: document.querySelectorAll('.bookarea')[2],
    targetElement: document.querySelectorAll('.detailheader')[1],
    insert: 'before'
  },
];

// ISBNの抽出
const parseISBN = (isbnSelector)=> {
  let isbn = null;
  let list = isbnSelector.length ? isbnSelector : [isbnSelector];
  for(let item of list) {
    let match = item.innerHTML.replace(/-/g, '').match(/[0-9\-]{12}[0-9X]/);
    // console.log(match)
    if (match) {
      isbn = match[0];
      break;
    }
  };
  return isbn;
};

let isbn = null;
let targetElement = null;
let insert = null;

SITES.forEach((site)=> {
  let url = site.url.replace(/\//g, '\\/');
  // console.log(url);
  if (location.href.match(url)) {
    isbn = parseISBN(site.isbnSelector);
    targetElement = site.targetElement;
    insert = site.insert;
  }
});

// 本のデータをパース
const parseBook = (book)=>{
  // console.log(book.onix);
  // 書影
  let thumbnail = null;
  // タイトル
  let title = book.onix.DescriptiveDetail.TitleDetail.TitleElement.TitleText.content;
  let titleYomi = book.onix.DescriptiveDetail.TitleDetail.TitleElement.TitleText.collationkey;
  // 紹介・目次
  let description = null;
  let descriptionLong = null;
  let tableOfContents = null;
  // console.log(book.onix.CollateralDetail.SupportingResource)
  if(book.summary.cover){
    thumbnail = book.summary.cover;
  }
  // console.log(book.onix.CollateralDetail.TextContent)
  if(book.onix.CollateralDetail.TextContent){
    book.onix.CollateralDetail.TextContent.forEach((text)=>{
      // console.log(text)
      if(text.TextType==='02'){
        description = text.Text;
      }
      if(text.TextType==='03'){
        descriptionLong = text.Text;
      }
      if(text.TextType==='04'){
        tableOfContents = text.Text;
      }
    });
  }
  // 著者
  let parseAuthor = (author)=>{
    if(typeof author.PersonName === 'string'){
      authors.push({
        name: author.PersonName,
        yomi: null,
        profile: author.BiographicalNote
      });
    }else{
      authors.push({
        name: author.PersonName.content,
        yomi: author.PersonName.collationkey,
        profile: author.BiographicalNote
      });
    }
  };
  let authors = [];
  if(book.onix.DescriptiveDetail.Contributor instanceof Array){
    book.onix.DescriptiveDetail.Contributor.forEach((author)=>{
      parseAuthor(author);
    });
  }else{
    parseAuthor(book.onix.DescriptiveDetail.Contributor);
  }

  // console.log(title, titleYomi);
  // console.log(authors);
  // console.log(description, descriptionLong, tableOfContents)
  return {
    thumbnail: thumbnail,
    title: title,
    titleYomi: titleYomi,
    authors: authors,
    description: description.replace(/\n/g, '
'),
    descriptionLong: descriptionLong.replace(/\n/g, '
'),
    tableOfContents: tableOfContents.replace(/\n/g, '
'),
    isbn: book.summary.isbn,
    publisher: book.summary.publisher,
    pubdate: book.summary.pubdate.replace(/(\d{4})(\d{2})(\d{2})/g , "$1/$2/$3"),
    author: book.summary.author
  };
};

// 本の追加
const renderBook = (book)=>{
  let content = document.createElement('div');
  content.className = 'openbd_content';

  let authorContent = '';
  // 著者情報の追加
  if(book.authors.length>0){
    authorContent = '
著者
';
    book.authors.forEach((author)=> {
      let authorYomi = author.yomi ? '(' + author.yomi + ')' : '';
      authorContent += `<h3 class="openbd_author_header">${author.name}${authorYomi}</h3>`;
      if(author.profile){
        authorContent += `<div class="openbd_author_profile">${author.profile}</div>`;
      }
    });
  }

  if(book.thumbnail){
    content.innerHTML += `<img src="${book.thumbnail}" />`;
  }
  let titleYomi = (book.titleYomi) ? '(' + book.titleYomi + ')' : '';
  content.innerHTML += `

タイトル

${book.title}${titleYomi}

  `;
  if(book.description || book.descriptionLong){
    content.innerHTML += '
紹介
';
  }
  if(book.description){
    content.innerHTML += `<div class="openbd_description">${book.description}</div>`;
  }
  if(book.descriptionLong){
    content.innerHTML += `<div class="openbd_description">${book.descriptionLong}</div>`;
  }
  if(book.tableOfContents){
    content.innerHTML += `

目次

${book.tableOfContents}

    `;
  }
  content.innerHTML += authorContent;
  let pubdate = book.pubdate!=='' ?` <span class="openbd_pubdate">(${book.pubdate})</span>` : '';
  content.innerHTML += `

出版社

${book.publisher}${pubdate}

ISBN

${book.isbn}

  `;
  content.innerHTML += `

by openBD

  `;
  if(insert==='after'){
    targetElement.parentNode.insertBefore(content, targetElement.nextSibling);
  }else if(insert==='before'){
    targetElement.parentNode.insertBefore(content, targetElement);
  }
};

// スタイルの追加
const renderStyle = ()=>{
  let style = document.createElement('style');
  style.innerHTML = `
  .openbd_content {
    font-size: 1em;
    margin: 3em auto;
    padding: 10px;
    background-color: #ffffff;
    color: #636363;
    border-radius: 0.25em;
  }
  .openbd_header {
    font-size: 1.25em;
    font-weight: bold !important;
    color: #000000;
    margin: 1em 0 0.5em;
  }
  .openbd_header:after {
    content:"";
    display:block;
    height:1px;
    width:100%;
    background-color: #dddddd;
    background-image: -moz-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: -webkit-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: -ms-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
  }
  .openbd_author_header {
    font-size: 1em;
    color: #000000;
    margin: 0.5em 0 0.5em;
  }
  .openbd_author_profile {
    font-size: 1em
  }
  .openbd_powered, .openbd_powered a {
    color: #999999;
    font-size: 0.8em;
    text-align: right;
  }
  `;
  if(insert==='after'){
    targetElement.parentNode.insertBefore(style, targetElement.nextSibling);
  }else if(insert==='before'){
    targetElement.parentNode.insertBefore(style, targetElement);
  }
};

// APIから書誌を取得
if (isbn) {
  // console.log('ISBN:' + isbn);
  new api([isbn], (data)=> {
    // document.body.append(JSON.stringify(data));
    renderStyle();
    data.forEach(function (book) {
      // 書誌があれば
      if (book !== null){
        let b = parseBook(book);
        renderBook(b);
      };
    })
  });
}

// // sample api data
// console.log(chrome.extension.getURL('/api.json'))
// superagent
// .get(chrome.extension.getURL('/api.json'))
// .end(function(err, res){
//   if(!err){
//     let data = JSON.parse(res.text);
//     // console.log(data);
//     renderStyle();
//     data.forEach((book)=>{
//       if(book!==null){
//         let b = parseBook(book);
//         b.isbn = isbn;
//         renderBook(b);
//       }
//     });
//   }
// });

// var injectScript;
//
// injectScript = function(file, node) {
//   var s, th;
//   th = document.getElementsByTagName(node)[0];
//   s = document.createElement('script');
//   s.setAttribute('type', 'text/javascript');
//   s.setAttribute('src', file);
//   return th.appendChild(s);
// };

// injectScript(chrome.extension.getURL('/api.js'), 'body');
// injectScript(chrome.extension.getURL('/embeded-script.js'), 'body');
// injectScript('http://lab.calil.jp/demo/openbd/superagent.js', 'body');
// injectScript('http://lab.calil.jp/demo/openbd/api.js?isbn='+isbn.join(','), 'body');
<commit_msg>改行変換の位置を修正<commit_after>/*
 openBD Chrome Extension
 Copyright (c) 2017 CALIL Inc.
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
 */

// 対応サイトの定義
const SITES = [
  {
    url: 'https?://ilisod001.apsel.jp/', // 対象にするURL 正規表現 /(スラッシュ)は\/(バックスラッシュ)付きに置換される
    isbnSelector: document.querySelectorAll('.normal-td'), // ISBNが含まれるエレメント 複数でも可
    targetElement: document.querySelectorAll('.contents')[2], // 書誌情報を挿入するエレメント
    insert: 'after' // after or beofre ターゲットの前後どちらに挿入するか
  },
  {
    url: 'https?://.*?/opac/wopc/pc/pages/SearchResultList.jsp',
    isbnSelector: document.querySelectorAll('.normal-td'),
    targetElement: document.querySelectorAll('.contents')[2],
    insert: 'after'
  },
  {
    url: 'https?://.*?/WebOpac/webopac/searchdetail.do',
    isbnSelector: document.querySelectorAll('#highlight_keyword td'),
    targetElement: document.querySelectorAll('#highlight_keyword')[0],
    insert: 'after'
  },
  {
    url: 'https?://www.amazon.co.jp/?.*?/dp/',
    isbnSelector: document.querySelectorAll('.content li'),
    targetElement: document.querySelectorAll('#productDescription_feature_div')[0],
    insert: 'after'
  },
  {
    url: 'https://calil.jp/book/',
    isbnSelector: document.querySelectorAll('.bookarea')[2],
    targetElement: document.querySelectorAll('.detailheader')[1],
    insert: 'before'
  },
];

// ISBNの抽出
const parseISBN = (isbnSelector)=> {
  let isbn = null;
  let list = isbnSelector.length ? isbnSelector : [isbnSelector];
  for(let item of list) {
    let match = item.innerHTML.replace(/-/g, '').match(/[0-9\-]{12}[0-9X]/);
    // console.log(match)
    if (match) {
      isbn = match[0];
      break;
    }
  };
  return isbn;
};

let isbn = null;
let targetElement = null;
let insert = null;

SITES.forEach((site)=> {
  let url = site.url.replace(/\//g, '\\/');
  // console.log(url);
  if (location.href.match(url)) {
    isbn = parseISBN(site.isbnSelector);
    targetElement = site.targetElement;
    insert = site.insert;
  }
});

// 本のデータをパース
const parseBook = (book)=>{
  // console.log(book.onix);
  // 書影
  let thumbnail = null;
  // タイトル
  let title = book.onix.DescriptiveDetail.TitleDetail.TitleElement.TitleText.content;
  let titleYomi = book.onix.DescriptiveDetail.TitleDetail.TitleElement.TitleText.collationkey;
  // 紹介・目次
  let description = null;
  let descriptionLong = null;
  let tableOfContents = null;
  // console.log(book.onix.CollateralDetail.SupportingResource)
  if(book.summary.cover){
    thumbnail = book.summary.cover;
  }
  // console.log(book.onix.CollateralDetail.TextContent)
  if(book.onix.CollateralDetail.TextContent){
    book.onix.CollateralDetail.TextContent.forEach((text)=>{
      // console.log(text)
      if(text.TextType==='02'){
        description = text.Text.replace(/\n/g, '
');
      }
      if(text.TextType==='03'){
        descriptionLong = text.Text.replace(/\n/g, '
');
      }
      if(text.TextType==='04'){
        tableOfContents = text.Text.replace(/\n/g, '
');
      }
    });
  }
  // 著者
  let parseAuthor = (author)=>{
    if(typeof author.PersonName === 'string'){
      authors.push({
        name: author.PersonName,
        yomi: null,
        profile: author.BiographicalNote
      });
    }else{
      authors.push({
        name: author.PersonName.content,
        yomi: author.PersonName.collationkey,
        profile: author.BiographicalNote
      });
    }
  };
  let authors = [];
  if(book.onix.DescriptiveDetail.Contributor instanceof Array){
    book.onix.DescriptiveDetail.Contributor.forEach((author)=>{
      parseAuthor(author);
    });
  }else{
    parseAuthor(book.onix.DescriptiveDetail.Contributor);
  }

  // console.log(title, titleYomi);
  // console.log(authors);
  // console.log(description, descriptionLong, tableOfContents)
  return {
    thumbnail: thumbnail,
    title: title,
    titleYomi: titleYomi,
    authors: authors,
    description: description,
    descriptionLong: descriptionLong,
    tableOfContents: tableOfContents,
    isbn: book.summary.isbn,
    publisher: book.summary.publisher,
    pubdate: book.summary.pubdate.replace(/(\d{4})(\d{2})(\d{2})/g , "$1/$2/$3"),
    author: book.summary.author
  };
};

// 本の追加
const renderBook = (book)=>{
  let content = document.createElement('div');
  content.className = 'openbd_content';

  let authorContent = '';
  // 著者情報の追加
  if(book.authors.length>0){
    authorContent = '
著者
';
    book.authors.forEach((author)=> {
      let authorYomi = author.yomi ? '(' + author.yomi + ')' : '';
      authorContent += `<h3 class="openbd_author_header">${author.name}${authorYomi}</h3>`;
      if(author.profile){
        authorContent += `<div class="openbd_author_profile">${author.profile}</div>`;
      }
    });
  }

  if(book.thumbnail){
    content.innerHTML += `<img src="${book.thumbnail}" />`;
  }
  let titleYomi = (book.titleYomi) ? '(' + book.titleYomi + ')' : '';
  content.innerHTML += `

タイトル

${book.title}${titleYomi}

  `;
  if(book.description || book.descriptionLong){
    content.innerHTML += '
紹介
';
  }
  if(book.description){
    content.innerHTML += `<div class="openbd_description">${book.description}</div>`;
  }
  if(book.descriptionLong){
    content.innerHTML += `<div class="openbd_description">${book.descriptionLong}</div>`;
  }
  if(book.tableOfContents){
    content.innerHTML += `

目次

${book.tableOfContents}

    `;
  }
  content.innerHTML += authorContent;
  let pubdate = book.pubdate!=='' ?` <span class="openbd_pubdate">(${book.pubdate})</span>` : '';
  content.innerHTML += `

出版社

${book.publisher}${pubdate}

ISBN

${book.isbn}

  `;
  content.innerHTML += `

by openBD

  `;
  if(insert==='after'){
    targetElement.parentNode.insertBefore(content, targetElement.nextSibling);
  }else if(insert==='before'){
    targetElement.parentNode.insertBefore(content, targetElement);
  }
};

// スタイルの追加
const renderStyle = ()=>{
  let style = document.createElement('style');
  style.innerHTML = `
  .openbd_content {
    font-size: 1em;
    margin: 3em auto;
    padding: 10px;
    background-color: #ffffff;
    color: #636363;
    border-radius: 0.25em;
  }
  .openbd_header {
    font-size: 1.25em;
    font-weight: bold !important;
    color: #000000;
    margin: 1em 0 0.5em;
  }
  .openbd_header:after {
    content:"";
    display:block;
    height:1px;
    width:100%;
    background-color: #dddddd;
    background-image: -moz-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: -webkit-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: -ms-linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
    background-image: linear-gradient(90deg, #efa8b0, #a89cc8, #8cc9f0);
  }
  .openbd_author_header {
    font-size: 1em;
    color: #000000;
    margin: 0.5em 0 0.5em;
  }
  .openbd_author_profile {
    font-size: 1em
  }
  .openbd_powered, .openbd_powered a {
    color: #999999;
    font-size: 0.8em;
    text-align: right;
  }
  `;
  if(insert==='after'){
    targetElement.parentNode.insertBefore(style, targetElement.nextSibling);
  }else if(insert==='before'){
    targetElement.parentNode.insertBefore(style, targetElement);
  }
};

// APIから書誌を取得
if (isbn) {
  // console.log('ISBN:' + isbn);
  new api([isbn], (data)=> {
    // document.body.append(JSON.stringify(data));
    renderStyle();
    data.forEach(function (book) {
      // 書誌があれば
      if (book !== null){
        let b = parseBook(book);
        renderBook(b);
      };
    })
  });
}

// // sample api data
// console.log(chrome.extension.getURL('/api.json'))
// superagent
// .get(chrome.extension.getURL('/api.json'))
// .end(function(err, res){
//   if(!err){
//     let data = JSON.parse(res.text);
//     // console.log(data);
//     renderStyle();
//     data.forEach((book)=>{
//       if(book!==null){
//         let b = parseBook(book);
//         b.isbn = isbn;
//         renderBook(b);
//       }
//     });
//   }
// });

// var injectScript;
//
// injectScript = function(file, node) {
//   var s, th;
//   th = document.getElementsByTagName(node)[0];
//   s = document.createElement('script');
//   s.setAttribute('type', 'text/javascript');
//   s.setAttribute('src', file);
//   return th.appendChild(s);
// };

// injectScript(chrome.extension.getURL('/api.js'), 'body');
// injectScript(chrome.extension.getURL('/embeded-script.js'), 'body');
// injectScript('http://lab.calil.jp/demo/openbd/superagent.js', 'body');
// injectScript('http://lab.calil.jp/demo/openbd/api.js?isbn='+isbn.join(','), 'body');
<|endoftext|>


<commit_before>import createTest, { isTestLibrarySupported } from './create-test';

const _returnChildState(stateKey, stateObj) => {
  if (!stateKey) {
    return stateObj;
  };
  const splitState = stateKey.split('.');
  return splitState.reduce((currentLevelObj, levelLabel) => {
    return currentLevelObj[levelLabel] || {};
  }, stateObj);
};

const reduxRecord = function({
  reducer,
  includeReducer = false,
  stateKey,
  actionSubset,
  equality = '(result, nextState) => result === nextState',
  imports = '',
  testLib = 'tape',
  numTestsToSave = 5,
  includeShowTestsButton = false
}) {
  let actions = [];
  let recording = false;
  let showingTest = false;
  let testIndex = undefined;
  let prevTests = [];
  let listeners = [];
  let stringifiedReducer = '/* import reducer from YOUR_REDUCER_LOCATION_HERE */';
  if (includeReducer) {
    stringifiedReducer = `var reducer = ${reducer.toString()}`;
  }

  const updateListeners = () => {
    if (listeners.length) {
      let newTestState = {
        recording,
        showingTest,
        tests: prevTests,
        testIndex
      }
      listeners.forEach(fn => fn(newTestState));
    }
  }

  // we can skip type checking to see if equality arg is a string since string.toString() returns same string
  const equalityFunction = equality.toString();
  const startRecord = () => {
    recording = true;
    updateListeners();
  };
  const stopRecord = () =>  {
    recording = false;
    showingTest = true;
    updateListeners();
  }

  const hideTest = () => {
    showingTest = false;
    updateListeners();
  };

  const showTest = () => {
    showingTest = true;
    updateListeners();
  };

  const emptyActions = () => {
    actions = [];
    updateListeners();
  };

  const updateTestIndex = (index) => {
    testIndex = index;
    updateListeners();
  }

  const genTest = typeof testLib === 'function' ? testLib : createTest;
  if (typeof testLib !== 'string' && typeof testLib !== 'function') {
    throw new Error('testLib argument must be a string or a function');
  }
  if (typeof testLib === 'string' && !isTestLibrarySupported(testLib)) {
    throw new Error('testLib argument does not contain a supported testing library. ' +
      'Feel free to make a pr adding support or use a custom test generation function for testLib arg');
  }

  const createNewTest = () => {
    const test = (
      genTest({
        actions,
        imports,
        equalityFunction,
        reducer: stringifiedReducer,
        testLib: testLib
      })
    );
    if (prevTests.length === numTestsToSave) {
      prevTests = prevTests.slice(1, prevTests.length);
    }
    prevTests.push(test);
    testIndex = prevTests.length - 1;
    updateListeners();
    return test;
  }

  const middleware = ({getState}) => (next) => (action) => {
    if (recording) {
      const prevState = _returnChildState(stateKey, getState());
      next(action);
      const nextState = _returnChildState(stateKey, getState());
      if (!actionSubset || actionSubset[action.type]) {
        actions.push({action, prevState, nextState});
      }
    }
    else {
      next(action);
    }
  };

  const listen = (fn) => {
    listeners.push(fn);
    updateListeners();
    return () => listeners.splice(listeners.splice(listeners.indexOf(fn), 1));
  }
  const props = {
    startRecord,
    stopRecord,
    createNewTest,
    hideTest,
    showTest,
    emptyActions,
    updateTestIndex,
    listen,
    includeShowTestsButton
  };
  return { middleware, props };
};

export default reduxRecord;
<commit_msg>fix state to default only for undefined values<commit_after>import createTest, { isTestLibrarySupported } from './create-test';

const _returnChildState = (stateKey, stateObj) => {
  if (!stateKey) {
    return stateObj;
  };
  const splitState = stateKey.split('.');
  return splitState.reduce((higherLeveLobject, levelLabel) => {
    const currentLevelObject = higherLeveLobject[levelLabel]
    return currentLevelObject === undefined ? {} : currentLevelObject;
  }, stateObj);
};

const reduxRecord = function({
  reducer,
  includeReducer = false,
  stateKey,
  actionSubset,
  equality = '(result, nextState) => result === nextState',
  imports = '',
  testLib = 'tape',
  numTestsToSave = 5,
  includeShowTestsButton = false
}) {
  let actions = [];
  let recording = false;
  let showingTest = false;
  let testIndex = undefined;
  let prevTests = [];
  let listeners = [];
  let stringifiedReducer = '/* import reducer from YOUR_REDUCER_LOCATION_HERE */';
  if (includeReducer) {
    stringifiedReducer = `var reducer = ${reducer.toString()}`;
  }

  const updateListeners = () => {
    if (listeners.length) {
      let newTestState = {
        recording,
        showingTest,
        tests: prevTests,
        testIndex
      }
      listeners.forEach(fn => fn(newTestState));
    }
  }

  // we can skip type checking to see if equality arg is a string since string.toString() returns same string
  const equalityFunction = equality.toString();
  const startRecord = () => {
    recording = true;
    updateListeners();
  };
  const stopRecord = () =>  {
    recording = false;
    showingTest = true;
    updateListeners();
  }

  const hideTest = () => {
    showingTest = false;
    updateListeners();
  };

  const showTest = () => {
    showingTest = true;
    updateListeners();
  };

  const emptyActions = () => {
    actions = [];
    updateListeners();
  };

  const updateTestIndex = (index) => {
    testIndex = index;
    updateListeners();
  }

  const genTest = typeof testLib === 'function' ? testLib : createTest;
  if (typeof testLib !== 'string' && typeof testLib !== 'function') {
    throw new Error('testLib argument must be a string or a function');
  }
  if (typeof testLib === 'string' && !isTestLibrarySupported(testLib)) {
    throw new Error('testLib argument does not contain a supported testing library. ' +
      'Feel free to make a pr adding support or use a custom test generation function for testLib arg');
  }

  const createNewTest = () => {
    const test = (
      genTest({
        actions,
        imports,
        equalityFunction,
        reducer: stringifiedReducer,
        testLib: testLib
      })
    );
    if (prevTests.length === numTestsToSave) {
      prevTests = prevTests.slice(1, prevTests.length);
    }
    prevTests.push(test);
    testIndex = prevTests.length - 1;
    updateListeners();
    return test;
  }

  const middleware = ({getState}) => (next) => (action) => {
    if (recording) {
      const prevState = _returnChildState(stateKey, getState());
      next(action);
      const nextState = _returnChildState(stateKey, getState());
      if (!actionSubset || actionSubset[action.type]) {
        actions.push({action, prevState, nextState});
      }
    }
    else {
      next(action);
    }
  };

  const listen = (fn) => {
    listeners.push(fn);
    updateListeners();
    return () => listeners.splice(listeners.splice(listeners.indexOf(fn), 1));
  }
  const props = {
    startRecord,
    stopRecord,
    createNewTest,
    hideTest,
    showTest,
    emptyActions,
    updateTestIndex,
    listen,
    includeShowTestsButton
  };
  return { middleware, props };
};

export default reduxRecord;
<|endoftext|>


<commit_before>"use strict";

var settingsController;
var userController;
var appController;
var appsView;
var chartView;
// Google Analytics
var gaPlugin;

function GAStartupSuccess() {
  googleAnalytics("startup");
}

// construct and execute a System setup class
(function System() {

  var onDeviceReady = function() {
    settingsController = new SettingsController();
    appsView = new AppsView();
    chartView = new ChartView();
    appController = new AppController();
    userController = new UserController();
    userController.init();
    document.addEventListener("menubutton", function(){$('#menu').collapse('toggle')}, false);
    if (window.plugins != undefined) {
      gaPlugin = window.plugins.gaPlugin;
      gaPlugin.init(GAStartupSuccess, emptyCallback, "UA-28850866-8", 5);
    }
    setTimeout(preventDim, 2000);
  };

  var init = function() {
    $(document).ready(function() {
      if (isMobile()) {
        document.addEventListener('deviceready', onDeviceReady, false);
      } else {
        onDeviceReady();
      }
    });
  };

  init();
})();

// stoopid test for screen dimming prevention
function preventDim() {
  $(document).trigger("menubutton");
  setTimeout(preventDim, 10000);
}<commit_msg>I know this will not work..<commit_after>"use strict";

var settingsController;
var userController;
var appController;
var appsView;
var chartView;
// Google Analytics
var gaPlugin;

function GAStartupSuccess() {
  googleAnalytics("startup");
}

// construct and execute a System setup class
(function System() {

  var onDeviceReady = function() {
    settingsController = new SettingsController();
    appsView = new AppsView();
    chartView = new ChartView();
    appController = new AppController();
    userController = new UserController();
    userController.init();
    $(document).bind("menubutton", function(){$('#menu').collapse('toggle')});
    if (window.plugins != undefined) {
      gaPlugin = window.plugins.gaPlugin;
      gaPlugin.init(GAStartupSuccess, emptyCallback, "UA-28850866-8", 5);
    }
    setTimeout(preventDim, 2000);
  };

  var init = function() {
    $(document).ready(function() {
      if (isMobile()) {
        document.addEventListener('deviceready', onDeviceReady, false);
      } else {
        onDeviceReady();
      }
    });
  };

  init();
})();

// stoopid test for screen dimming prevention
function preventDim() {
  $(document).trigger("menubutton");
  setTimeout(preventDim, 10000);
}<|endoftext|>


<commit_before>angular.
  module('Cadastrarusuario').
  component('registrarUsuario', {
    templateUrl: '/app/Cadastraraluno/cadastraraluno.template.html',
    controller: ['ApiUsuarioCadastrar','$http','$location', 'MatWebGlobals',function(ApiUsuarioCadastrar,$http,$location,MatWebGlobals) {
      var ctrl = this;
      this.formulario = {'nome':'','matricula':'','cpf':'','perfil':'','senha':''};
      this.cadastrar = function()
      {
          ApiUsuarioCadastrar.Cadastrar(ctrl.formulario,function(data){
            ctrl.mensagem = "Departamento cadastrado com sucesso";
          },function(data){
            ctrl.mensagem = "ERRO";
          });
    };
    }]
});
<commit_msg>lol 2017-05-22<commit_after>angular.
  module('Cadastrarusuario').
  component('registrarUsuario', {
    templateUrl: '/app/Cadastraraluno/cadastraraluno.template.html',
    controller: ['ApiUsuarioCadastrar','$http','$location', 'MatWebGlobals',function(ApiUsuarioCadastrar,$http,$location,MatWebGlobals) {
      var ctrl = this;
      this.formulario = {'nome':'','matricula':'','cpf':'','perfil':'','senha':''};
      this.cadastrar = function()
      {
          ApiUsuarioCadastrar.Cadastrar(ctrl.formulario,function(data){
            ctrl.mensagem = "Aluno cadastrado com sucesso";
          },function(data){
            ctrl.mensagem = "ERRO";
          });
    };
    }]
});
<|endoftext|>