Remove obsolete files after shared code modularization

This commit is contained in:
Adomas Venčkauskas 2021-07-26 13:16:33 +03:00 committed by Adomas Ven
parent 7814efcfe2
commit 8f90cfbcfd
21 changed files with 0 additions and 14025 deletions

View file

@ -1,962 +0,0 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
Zotero.Date = new function(){
this.isSQLDate = isSQLDate;
this.isSQLDateTime = isSQLDateTime;
this.sqlHasYear = sqlHasYear;
this.sqlHasMonth = sqlHasMonth;
this.sqlHasDay = sqlHasDay;
this.getUnixTimestamp = getUnixTimestamp;
this.toUnixTimestamp = toUnixTimestamp;
this.getFileDateString = getFileDateString;
this.getFileTimeString = getFileTimeString;
this.getLocaleDateOrder = getLocaleDateOrder;
var _localeDateOrder = null;
var _months;
var _monthsWithEnglish;
this.init = function () {
if (!(Zotero.isFx || Zotero.isElectron) || Zotero.isBookmarklet) {
throw new Error("Unimplemented");
}
var json = JSON.parse(Zotero.File.getResource('resource://zotero/schema/dateFormats.json'));
var locale = Zotero.locale;
var english = locale.startsWith('en');
// If no exact match, try first two characters ('de')
if (!json[locale]) {
locale = locale.substr(0, 2);
}
// Try first two characters repeated ('de-DE')
if (!json[locale]) {
locale = locale + "-" + locale.toUpperCase();
}
// Look for another locale with same first two characters
if (!json[locale]) {
let sameLang = Object.keys(json).filter(l => l.startsWith(locale.substr(0, 2)));
if (sameLang.length) {
locale = sameLang[0];
}
}
// If all else fails, use English
if (!json[locale]) {
locale = 'en-US';
english = true;
}
_months = json[locale];
// Add English versions if not already added
if (english) {
_monthsWithEnglish = _months;
}
else {
_monthsWithEnglish = {};
for (let key in _months) {
_monthsWithEnglish[key] = _months[key].concat(json['en-US'][key]);
}
}
};
/**
* @param {Boolean} [withEnglish = false] - Include English months
* @return {Object} - Object with 'short' and 'long' arrays
*/
this.getMonths = function (withEnglish) {
if (withEnglish) {
if (_monthsWithEnglish) return _monthsWithEnglish;
}
else {
if (_months) return _months;
}
if (Zotero.isFx && !Zotero.isBookmarklet) {
throw new Error("Months not cached");
}
// TODO: Use JSON file for connectors
return _months = _monthsWithEnglish = {
short: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
long: ["January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"]};
}
/**
* Convert an SQL date in the form '2006-06-13 11:03:05' into a JS Date object
*
* Can also accept just the date part (e.g. '2006-06-13')
**/
this.sqlToDate = function (sqldate, isUTC) {
try {
if (!this.isSQLDate(sqldate)
&& !this.isSQLDateTime(sqldate)
&& !this.isSQLDateTimeWithoutSeconds(sqldate)) {
throw new Error("Invalid date");
}
var datetime = sqldate.split(' ');
var dateparts = datetime[0].split('-');
if (datetime[1]){
var timeparts = datetime[1].split(':');
}
else {
timeparts = [false, false, false];
}
// Invalid date part
if (dateparts.length==1){
throw new Error("Invalid date part");
}
// Allow missing seconds
if (timeparts.length == 2) {
timeparts[2] = '00';
}
if (isUTC){
return new Date(Date.UTC(dateparts[0], dateparts[1]-1, dateparts[2],
timeparts[0], timeparts[1], timeparts[2]));
}
return new Date(dateparts[0], dateparts[1]-1, dateparts[2],
timeparts[0], timeparts[1], timeparts[2]);
}
catch (e){
Zotero.debug(sqldate + ' is not a valid SQL date', 2)
return false;
}
}
/**
* Convert a JS Date object to an SQL date in the form '2006-06-13 11:03:05'
*
* If _toUTC_ is true, creates a UTC date
**/
this.dateToSQL = function (date, toUTC) {
try {
if (toUTC){
var year = date.getUTCFullYear();
var month = date.getUTCMonth();
var day = date.getUTCDate();
var hours = date.getUTCHours();
var minutes = date.getUTCMinutes();
var seconds = date.getUTCSeconds();
}
else {
var year = date.getFullYear();
var month = date.getMonth();
var day = date.getDate();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
}
year = Zotero.Utilities.lpad(year, '0', 4);
month = Zotero.Utilities.lpad(month + 1, '0', 2);
day = Zotero.Utilities.lpad(day, '0', 2);
hours = Zotero.Utilities.lpad(hours, '0', 2);
minutes = Zotero.Utilities.lpad(minutes, '0', 2);
seconds = Zotero.Utilities.lpad(seconds, '0', 2);
return year + '-' + month + '-' + day + ' '
+ hours + ':' + minutes + ':' + seconds;
}
catch (e){
Zotero.debug(date + ' is not a valid JS date', 2);
return '';
}
}
/**
* Convert a JS Date object to an ISO 8601 UTC date/time
*
* @param {Date} date JS Date object
* @return {String} ISO 8601 UTC date/time
* e.g. 2008-08-15T20:00:00Z
*/
this.dateToISO = function (date) {
var year = date.getUTCFullYear();
var month = date.getUTCMonth();
var day = date.getUTCDate();
var hours = date.getUTCHours();
var minutes = date.getUTCMinutes();
var seconds = date.getUTCSeconds();
year = Zotero.Utilities.lpad(year, '0', 4);
month = Zotero.Utilities.lpad(month + 1, '0', 2);
day = Zotero.Utilities.lpad(day, '0', 2);
hours = Zotero.Utilities.lpad(hours, '0', 2);
minutes = Zotero.Utilities.lpad(minutes, '0', 2);
seconds = Zotero.Utilities.lpad(seconds, '0', 2);
return year + '-' + month + '-' + day + 'T'
+ hours + ':' + minutes + ':' + seconds + 'Z';
}
var _re8601 = /^([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?$/;
/**
* @return {Boolean} - True if string is an ISO 8601 date, false if not
*/
this.isISODate = function (str) {
return _re8601.test(str);
}
/**
* Convert an ISO 8601formatted date/time to a JS Date
*
* @param {String} isoDate ISO 8601 date
* @return {Date|False} - JS Date, or false if not a valid date
*/
this.isoToDate = function (isoDate) {
var d = isoDate.match(_re8601);
if (!d) return false;
return new Date(isoDate);
}
this.isoToSQL = function (isoDate) {
return Zotero.Date.dateToSQL(Zotero.Date.isoToDate(isoDate), true); // no 'this' for translator sandbox
}
/*
* converts a string to an object containing:
* day: integer form of the day
* month: integer form of the month (indexed from 0, not 1)
* year: 4 digit year (or, year + BC/AD/etc.)
* part: anything that does not fall under any of the above categories
* (e.g., "Summer," etc.)
*
* Note: the returned object is *not* a JS Date object
*/
var _slashRe = /^(.*?)\b([0-9]{1,4})(?:([\-\/\.\u5e74])([0-9]{1,2}))?(?:([\-\/\.\u6708])([0-9]{1,4}))?((?:\b|[^0-9]).*?)$/
var _yearRe = /^(.*?)\b((?:circa |around |about |c\.? ?)?[0-9]{1,4}(?: ?B\.? ?C\.?(?: ?E\.?)?| ?C\.? ?E\.?| ?A\.? ?D\.?)|[0-9]{3,4})\b(.*?)$/i;
var _monthRe = null;
var _dayRe = null;
this.strToDate = function (string) {
var date = {
order: ''
};
if (typeof string == 'string' || typeof string == 'number') {
string = Zotero.Utilities.trimInternal(string.toString());
}
// skip empty things
if(!string) {
return date;
}
var parts = [];
// first, directly inspect the string
var m = _slashRe.exec(string);
if(m &&
((!m[5] || !m[3]) || m[3] == m[5] || (m[3] == "\u5e74" && m[5] == "\u6708")) && // require sane separators
((m[2] && m[4] && m[6]) || (!m[1] && !m[7]))) { // require that either all parts are found,
// or else this is the entire date field
// figure out date based on parts
if(m[2].length == 3 || m[2].length == 4 || m[3] == "\u5e74") {
// ISO 8601 style date (big endian)
date.year = m[2];
date.month = m[4];
date.day = m[6];
date.order += m[2] ? 'y' : '';
date.order += m[4] ? 'm' : '';
date.order += m[6] ? 'd' : '';
} else if(m[2] && !m[4] && m[6]) {
date.month = m[2];
date.year = m[6];
date.order += m[2] ? 'm' : '';
date.order += m[6] ? 'y' : '';
} else {
// local style date (middle or little endian)
var country = Zotero.locale ? Zotero.locale.substr(3) : "US";
if(country == "US" || // The United States
country == "FM" || // The Federated States of Micronesia
country == "PW" || // Palau
country == "PH") { // The Philippines
date.month = m[2];
date.day = m[4];
date.order += m[2] ? 'm' : '';
date.order += m[4] ? 'd' : '';
} else {
date.month = m[4];
date.day = m[2];
date.order += m[2] ? 'd' : '';
date.order += m[4] ? 'm' : '';
}
date.year = m[6];
if (m[6] !== undefined) {
date.order += 'y';
}
}
var longYear = date.year && date.year.toString().length > 2;
if(date.year) date.year = parseInt(date.year, 10);
if(date.day) date.day = parseInt(date.day, 10);
if(date.month) {
date.month = parseInt(date.month, 10);
if(date.month > 12) {
// swap day and month
var tmp = date.day;
date.day = date.month
date.month = tmp;
date.order = date.order.replace('m', 'D')
.replace('d', 'M')
.replace('D', 'd')
.replace('M', 'm');
}
}
if((!date.month || date.month <= 12) && (!date.day || date.day <= 31)) {
// Parse pre-100 years with leading zeroes (001, 0001, 012, 0012, 0123, but not 08)
if (date.year && date.year < 100 && !longYear) {
var today = new Date();
var year = today.getFullYear();
var twoDigitYear = year % 100;
var century = year - twoDigitYear;
if(date.year <= twoDigitYear) {
// assume this date is from our century
date.year = century + date.year;
} else {
// assume this date is from the previous century
date.year = century - 100 + date.year;
}
}
if(date.month) date.month--; // subtract one for JS style
else delete date.month;
//Zotero.debug("DATE: retrieved with algorithms: "+JSON.stringify(date));
parts.push(
{ part: m[1], before: true },
{ part: m[7] }
);
} else {
// give up; we failed the sanity check
Zotero.debug("DATE: algorithms failed sanity check");
var date = {
order: ''
};
parts.push({ part: string });
}
} else {
//Zotero.debug("DATE: could not apply algorithms");
parts.push({ part: string });
}
// couldn't find something with the algorithms; use regexp
// YEAR
if(!date.year) {
for (var i in parts) {
var m = _yearRe.exec(parts[i].part);
if (m) {
date.year = m[2];
date.order = _insertDateOrderPart(date.order, 'y', parts[i]);
parts.splice(
i, 1,
{ part: m[1], before: true },
{ part: m[3] }
);
//Zotero.debug("DATE: got year (" + date.year + ", " + JSON.stringify(parts) + ")");
break;
}
}
}
// MONTH
if(date.month === undefined) {
// compile month regular expression
let months = Zotero.Date.getMonths(true); // no 'this' for translator sandbox
months = months.short.map(m => m.toLowerCase())
.concat(months.long.map(m => m.toLowerCase()));
if(!_monthRe) {
_monthRe = new RegExp("^(.*)\\b("+months.join("|")+")[^ ]*(?: (.*)$|$)", "i");
}
for (var i in parts) {
var m = _monthRe.exec(parts[i].part);
if (m) {
// Modulo 12 in case we have multiple languages
date.month = months.indexOf(m[2].toLowerCase()) % 12;
date.order = _insertDateOrderPart(date.order, 'm', parts[i]);
parts.splice(
i, 1,
{ part: m[1], before: "m" },
{ part: m[3], after: "m" }
);
//Zotero.debug("DATE: got month (" + date.month + ", " + JSON.stringify(parts) + ")");
break;
}
}
}
// DAY
if(!date.day) {
// compile day regular expression
if(!_dayRe) {
var daySuffixes = Zotero.isClient ? Zotero.getString("date.daySuffixes").replace(/, ?/g, "|") : "";
_dayRe = new RegExp("\\b([0-9]{1,2})(?:"+daySuffixes+")?\\b(.*)", "i");
}
for (var i in parts) {
var m = _dayRe.exec(parts[i].part);
if (m) {
var day = parseInt(m[1], 10);
// Sanity check
if (day <= 31) {
date.day = day;
date.order = _insertDateOrderPart(date.order, 'd', parts[i]);
if(m.index > 0) {
var part = parts[i].part.substr(0, m.index);
if(m[2]) {
part += " " + m[2];;
}
} else {
var part = m[2];
}
parts.splice(
i, 1,
{ part: part }
);
//Zotero.debug("DATE: got day (" + date.day + ", " + JSON.stringify(parts) + ")");
break;
}
}
}
}
// Concatenate date parts
date.part = '';
for (var i in parts) {
date.part += parts[i].part + ' ';
}
// clean up date part
if(date.part) {
date.part = date.part.replace(/^[^A-Za-z0-9]+|[^A-Za-z0-9]+$/g, "");
}
if(date.part === "" || date.part == undefined) {
delete date.part;
}
//make sure year is always a string
if(date.year || date.year === 0) date.year += '';
return date;
}
this.isHTTPDate = function(str) {
var dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"];
str = str.trim();
var temp = str.split(',');
if (temp.length > 1) {
var dayOfWeek = temp[0];
if(dayNames.indexOf(dayOfWeek) == -1) {
return false;
}
str = temp[1].trim();
}
temp = str.split(' ');
temp = temp.filter((t) => ! t.match(/^\s*$/));
if (temp.length < 5) {
return false;
}
if (!temp[0].trim().match(/[0-3]\d/)) {
return false;
}
if (monthNames.indexOf(temp[1].trim()) == -1) {
return false;
}
if (!temp[2].trim().match(/\d\d\d\d/)) {
return false;
}
temp.splice(0, 3);
var time = temp[0].trim().split(':');
if (time.length < 2) {
return false;
}
for (let t of time) {
if (!t.match(/\d\d/)) {
return false;
}
}
temp.splice(0, 1);
var zone = temp.join(' ').trim();
return !!zone.match(/([+-]\d\d\d\d|UTC?|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT)/)
};
function _insertDateOrderPart(dateOrder, part, partOrder) {
if (!dateOrder) {
return part;
}
if (partOrder.before === true) {
return part + dateOrder;
}
if (partOrder.after === true) {
return dateOrder + part;
}
if (partOrder.before) {
var pos = dateOrder.indexOf(partOrder.before);
if (pos == -1) {
return dateOrder;
}
return dateOrder.replace(new RegExp("(" + partOrder.before + ")"), part + '$1');
}
if (partOrder.after) {
var pos = dateOrder.indexOf(partOrder.after);
if (pos == -1) {
return dateOrder + part;
}
return dateOrder.replace(new RegExp("(" + partOrder.after + ")"), '$1' + part);
}
return dateOrder + part;
}
/**
* does pretty formatting of a date object returned by strToDate()
*
* @param {Object} date A date object, as returned from strToDate()
* @param {Boolean} shortFormat Whether to return a short (12/1/95) date
* @return A formatted date string
* @type String
**/
this.formatDate = function (date, shortFormat) {
if(shortFormat) {
var localeDateOrder = getLocaleDateOrder();
var string = localeDateOrder[0]+"/"+localeDateOrder[1]+"/"+localeDateOrder[2];
return string.replace("y", (date.year !== undefined ? date.year : "00"))
.replace("m", (date.month !== undefined ? 1+date.month : "0"))
.replace("d", (date.day !== undefined ? date.day : "0"));
} else {
var string = "";
if(date.part) {
string += date.part+" ";
}
var months = Zotero.Date.getMonths().long; // no 'this' for translator sandbox
if(date.month != undefined && months[date.month]) {
// get short month strings from CSL interpreter
string += months[date.month];
if(date.day) {
string += " "+date.day+", ";
} else {
string += " ";
}
}
if(date.year) {
string += date.year;
}
}
return string;
}
this.strToISO = function (str) {
var date = this.strToDate(str);
if(date.year) {
var dateString = Zotero.Utilities.lpad(date.year, "0", 4);
if (parseInt(date.month) == date.month) {
dateString += "-"+Zotero.Utilities.lpad(date.month+1, "0", 2);
if(date.day) {
dateString += "-"+Zotero.Utilities.lpad(date.day, "0", 2);
}
}
return dateString;
}
return false;
}
this.sqlToISO8601 = function (sqlDate) {
var date = sqlDate.substr(0, 10);
var matches = date.match(/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})/);
if (!matches) {
return false;
}
date = matches[1];
// Drop parts for reduced precision
if (matches[2] !== "00") {
date += "-" + matches[2];
if (matches[3] !== "00") {
date += "-" + matches[3];
}
}
var time = sqlDate.substr(11);
// TODO: validate times
if (time) {
date += "T" + time + "Z";
}
return date;
}
this.strToMultipart = function (str) {
if (!str){
return '';
}
var parts = this.strToDate(str);
// FIXME: Until we have a better BCE date solution,
// remove year value if not between 1 and 9999
if (parts.year) {
var year = parts.year + '';
if (!year.match(/^[0-9]{1,4}$/)) {
delete parts.year;
}
}
parts.month = typeof parts.month != "undefined" ? parts.month + 1 : '';
var multi = (parts.year ? Zotero.Utilities.lpad(parts.year, '0', 4) : '0000') + '-'
+ Zotero.Utilities.lpad(parts.month, '0', 2) + '-'
+ (parts.day ? Zotero.Utilities.lpad(parts.day, '0', 2) : '00')
+ ' '
+ str;
return multi;
}
// Regexes for multipart and SQL dates
// Allow zeroes in multipart dates
// TODO: Allow negative multipart in DB and here with \-?
var _multipartRE = /^[0-9]{4}\-(0[0-9]|10|11|12)\-(0[0-9]|[1-2][0-9]|30|31) /;
var _sqldateRE = /^\-?[0-9]{4}\-(0[1-9]|10|11|12)\-(0[1-9]|[1-2][0-9]|30|31)$/;
var _sqldateWithZeroesRE = /^\-?[0-9]{4}\-(0[0-9]|10|11|12)\-(0[0-9]|[1-2][0-9]|30|31)$/;
var _sqldatetimeRE = /^\-?[0-9]{4}\-(0[1-9]|10|11|12)\-(0[1-9]|[1-2][0-9]|30|31) ([0-1][0-9]|[2][0-3]):([0-5][0-9]):([0-5][0-9])$/;
var _sqlDateTimeWithoutSecondsRE = /^\-?[0-9]{4}\-(0[1-9]|10|11|12)\-(0[1-9]|[1-2][0-9]|30|31) ([0-1][0-9]|[2][0-3]):([0-5][0-9])$/;
/**
* Tests if a string is a multipart date string
* e.g. '2006-11-03 November 3rd, 2006'
*/
this.isMultipart = function (str) {
if (this.isSQLDateTime(str) || this.isSQLDateTimeWithoutSeconds(str)) {
return false;
}
return _multipartRE.test(str);
}
/**
* Returns the SQL part of a multipart date string
* (e.g. '2006-11-03 November 3rd, 2006' returns '2006-11-03')
*/
this.multipartToSQL = function (multi) {
if (!multi){
return '';
}
if (!this.isMultipart(multi)) {
return '0000-00-00';
}
return multi.substr(0, 10);
}
/**
* Returns the user part of a multipart date string
* (e.g. '2006-11-03 November 3rd, 2006' returns 'November 3rd, 2006')
*/
this.multipartToStr = function (multi) {
if (!multi){
return '';
}
if (!this.isMultipart(multi)) {
return multi;
}
return multi.substr(11);
}
/**
* Convert 'yesterday'/'today'/'tomorrow' to SQL date, or else return original string
*
* @param {String} str
* @return {String}
*/
this.parseDescriptiveString = function (str) {
// Parse 'yesterday'/'today'/'tomorrow' and convert to dates,
// since it doesn't make sense for those to be actual metadata values
var lc = str.toLowerCase().trim();
if (lc == 'yesterday' || lc == Zotero.getString('date.yesterday')) {
str = Zotero.Date.dateToSQL(new Date(new Date().getTime() - 86400000)).substr(0, 10);
}
else if (lc == 'today' || lc == Zotero.getString('date.today')) {
str = Zotero.Date.dateToSQL(new Date()).substr(0, 10);
}
else if (lc == 'tomorrow' || lc == Zotero.getString('date.tomorrow')) {
str = Zotero.Date.dateToSQL(new Date(new Date().getTime() + 86400000)).substr(0, 10);
}
return str;
};
function isSQLDate(str, allowZeroes) {
if (allowZeroes) {
return _sqldateWithZeroesRE.test(str);
}
return _sqldateRE.test(str);
}
function isSQLDateTime(str){
return _sqldatetimeRE.test(str);
}
this.isSQLDateTimeWithoutSeconds = function (str) {
return _sqlDateTimeWithoutSecondsRE.test(str);
}
function sqlHasYear(sqldate){
return isSQLDate(sqldate, true) && sqldate.substr(0,4)!='0000';
}
function sqlHasMonth(sqldate){
return isSQLDate(sqldate, true) && sqldate.substr(5,2)!='00';
}
function sqlHasDay(sqldate){
return isSQLDate(sqldate, true) && sqldate.substr(8,2)!='00';
}
function getUnixTimestamp() {
return Math.round(Date.now() / 1000);
}
function toUnixTimestamp(date) {
if (date === null || typeof date != 'object' ||
date.constructor.name != 'Date') {
throw new Error(`'${date}' is not a valid date`);
}
return Math.round(date.getTime() / 1000);
}
/**
* Convert a JS Date to a relative date (e.g., "5 minutes ago")
*
* Adapted from http://snipplr.com/view/10290/javascript-parse-relative-date/
*
* @param {Date} date
* @return {String}
*/
this.toRelativeDate = function (date) {
var str;
var now = new Date();
var timeSince = now.getTime() - date;
var inSeconds = timeSince / 1000;
var inMinutes = timeSince / 1000 / 60;
var inHours = timeSince / 1000 / 60 / 60;
var inDays = timeSince / 1000 / 60 / 60 / 24;
var inYears = timeSince / 1000 / 60 / 60 / 24 / 365;
var n;
// in seconds
if (Math.round(inSeconds) == 1) {
var key = "secondsAgo";
}
else if (inMinutes < 1.01) {
var key = "secondsAgo";
n = Math.round(inSeconds);
}
// in minutes
else if (Math.round(inMinutes) == 1) {
var key = "minutesAgo";
}
else if (inHours < 1.01) {
var key = "minutesAgo";
n = Math.round(inMinutes);
}
// in hours
else if (Math.round(inHours) == 1) {
var key = "hoursAgo";
}
else if (inDays < 1.01) {
var key = "hoursAgo";
n = Math.round(inHours);
}
// in days
else if (Math.round(inDays) == 1) {
var key = "daysAgo";
}
else if (inYears < 1.01) {
var key = "daysAgo";
n = Math.round(inDays);
}
// in years
else if (Math.round(inYears) == 1) {
var key = "yearsAgo";
}
else {
var key = "yearsAgo";
var n = Math.round(inYears);
}
return Zotero.getString("date.relative." + key + "." + (n ? "multiple" : "one"), n);
}
// Initializing `toFriendlyDate` formatters, since
// `toLocaleDateString` is extremely slow (4500ms vs 200ms
// for 10k calls)
var _friendlyDateTodayFormatter = new Intl.DateTimeFormat(
false, { hour: 'numeric', minute: 'numeric' });
var _friendlyDateWeekFormatter = new Intl.DateTimeFormat(
false, { weekday: 'long' });
var _friendlyDateRegularFormatter = new Intl.DateTimeFormat(
false, { year: '2-digit', month: 'numeric', day: 'numeric' });
this.toFriendlyDate = function (date) {
// 6:14:36 PM
if (isToday(date)) {
return _friendlyDateTodayFormatter.format(date);
}
// 'Thursday'
if (isThisWeek(date)) {
return _friendlyDateWeekFormatter.format(date);
}
return _friendlyDateRegularFormatter.format(date);
};
function isToday(date) {
var d = new Date();
return d.getDate() == date.getDate()
&& d.getMonth() == d.getMonth()
&& d.getFullYear() == d.getFullYear();
}
function isThisWeek(date) {
var d = new Date();
return d.getFullYear() == date.getFullYear() && getWeekNumber(d) == getWeekNumber(date);
}
// https://stackoverflow.com/a/27125580
function getWeekNumber(date) {
let onejan = new Date(date.getFullYear(), 0, 1);
return Math.ceil((((date.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7);
}
function getFileDateString(file){
var date = new Date();
date.setTime(file.lastModifiedTime);
return date.toLocaleDateString();
}
function getFileTimeString(file){
var date = new Date();
date.setTime(file.lastModifiedTime);
return date.toLocaleTimeString();
}
/**
* Get the order of the date components based on the current locale
*
* Returns a string with y, m, and d (e.g. 'ymd', 'mdy')
*/
function getLocaleDateOrder(){
if (!_localeDateOrder) {
switch (Zotero.locale ? Zotero.locale.substr(3) : "US") {
// middle-endian
case 'US': // The United States
case 'BZ': // Belize
case 'FM': // The Federated States of Micronesia
case 'PA': // Panama
case 'PH': // The Philippines
case 'PW': // Palau
case 'ZW': // Zimbabwe
_localeDateOrder = 'mdy';
break;
// big-endian
case 'fa': // Persian
case 'AL': // Albania
case 'CA': // Canada
case 'CN': // China
case 'HU': // Hungary
case 'JP': // Japan
case 'KE': // Kenya
case 'KR': // Korea
case 'LT': // Lithuania
case 'LV': // Latvia
case 'MN': // Mongolia
case 'SE': // Sweden
case 'TW': // Taiwan
case 'ZA': // South Africa
_localeDateOrder = 'ymd';
break;
// little-endian
default:
_localeDateOrder = 'dmy';
}
}
return _localeDateOrder;
}
}
if (typeof process === 'object' && process + '' === '[object process]'){
module.exports = Zotero.Date;
}

View file

@ -1,511 +0,0 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
Zotero.OpenURL = new function() {
this.resolve = resolve;
this.discoverResolvers = discoverResolvers;
this.createContextObject = createContextObject;
this.parseContextObject = parseContextObject;
/*
* Returns a URL to look up an item in the OpenURL resolver
*/
function resolve(itemObject) {
var co = createContextObject(itemObject, Zotero.Prefs.get("openURL.version"));
if(co) {
var base = Zotero.Prefs.get("openURL.resolver");
// Add & if there's already a ?
var splice = base.indexOf("?") == -1 ? "?" : "&";
return base + splice + co;
}
return false;
}
/*
* Queries OCLC's OpenURL resolver registry and returns an address and version
*/
function discoverResolvers() {
var req = new XMLHttpRequest();
req.open("GET", "http://worldcatlibraries.org/registry/lookup?IP=requestor", false);
req.send(null);
if(!req.responseXML) {
throw new Error("Could not access resolver registry");
}
var resolverArray = new Array();
var resolvers = req.responseXML.getElementsByTagName("resolver");
for(var i=0; i<resolvers.length; i++) {
var resolver = resolvers[i];
var name = resolver.parentNode.getElementsByTagName("institutionName");
if(!name.length) {
continue;
}
name = name[0].textContent;
var url = resolver.getElementsByTagName("baseURL");
if(!url.length) {
continue;
}
url = url[0].textContent;
if(resolver.getElementsByTagName("Z39.88-2004").length > 0) {
var version = "1.0";
} else if(resolver.getElementsByTagName("OpenURL_0.1").length > 0) {
var version = "0.1";
} else {
continue;
}
resolverArray.push({name:name, url:url, version:version});
}
return resolverArray;
}
/*
* Generates an OpenURL ContextObject from an item
*/
function createContextObject(item, version, asObj) {
var entries = (asObj ? {} : []);
function _mapTag(data, tag, dontAddPrefix) {
if(!data) return;
if(version === "1.0" && !dontAddPrefix) tag = "rft."+tag;
if(asObj) {
if(!entries[tag]) entries[tag] = [];
entries[tag].push(data);
} else {
entries.push(tag+"="+encodeURIComponent(data));
}
}
if (item.toJSON) {
item = item.toJSON();
}
// find pmid
const pmidRe = /(?:\n|^)PMID:\s*(\d+)/g;
var pmid = pmidRe.exec(item.extra);
if(pmid) pmid = pmid[1];
// encode ctx_ver (if available) and encode identifiers
if(version == "0.1") {
_mapTag("Zotero:2", "sid", true);
if(item.DOI) _mapTag("doi:"+item.DOI, "id", true);
if(item.ISBN) _mapTag(item.ISBN, "isbn", true);
if(pmid) _mapTag("pmid:"+pmid, "id", true);
} else {
_mapTag("Z39.88-2004", "url_ver", true);
_mapTag("Z39.88-2004", "ctx_ver", true);
_mapTag("info:sid/zotero.org:2", "rfr_id", true);
if(item.DOI) _mapTag("info:doi/"+item.DOI, "rft_id", true);
if(item.ISBN) _mapTag("urn:isbn:"+item.ISBN, "rft_id", true);
if(pmid) _mapTag("info:pmid/"+pmid, "rft_id", true);
}
// encode genre and item-specific data
if(item.itemType == "journalArticle") {
if(version === "1.0") {
_mapTag("info:ofi/fmt:kev:mtx:journal", "rft_val_fmt", true);
}
_mapTag("article", "genre");
_mapTag(item.title, "atitle");
_mapTag(item.publicationTitle, (version == "0.1" ? "title" : "jtitle"));
_mapTag(item.journalAbbreviation, "stitle");
_mapTag(item.volume, "volume");
_mapTag(item.issue, "issue");
} else if(item.itemType == "book" || item.itemType == "bookSection" || item.itemType == "conferencePaper" || item.itemType == "report") {
if(version === "1.0") {
_mapTag("info:ofi/fmt:kev:mtx:book", "rft_val_fmt", true);
}
if(item.itemType == "book") {
_mapTag("book", "genre");
_mapTag(item.title, (version == "0.1" ? "title" : "btitle"));
} else if (item.itemType == "conferencePaper") {
_mapTag("proceeding", "genre");
_mapTag(item.title, "atitle");
_mapTag(item.proceedingsTitle, (version == "0.1" ? "title" : "btitle"));
} else if (item.itemType == "report") {
_mapTag("report", "genre");
_mapTag(item.seriesTitle, "series");
_mapTag(item.title, (version == "0.1" ? "title" : "btitle"));
} else {
_mapTag("bookitem", "genre");
_mapTag(item.title, "atitle");
_mapTag(item.publicationTitle, (version == "0.1" ? "title" : "btitle"));
}
_mapTag(item.place, "place");
_mapTag(item.publisher, "publisher");
_mapTag(item.edition, "edition");
_mapTag(item.series, "series");
} else if(item.itemType == "thesis" && version == "1.0") {
_mapTag("info:ofi/fmt:kev:mtx:dissertation", "rft_val_fmt", true);
_mapTag(item.title, "title");
_mapTag(item.publisher, "inst");
_mapTag(item.type, "degree");
} else if(item.itemType == "patent" && version == "1.0") {
_mapTag("info:ofi/fmt:kev:mtx:patent", "rft_val_fmt", true);
_mapTag(item.title, "title");
_mapTag(item.assignee, "assignee");
_mapTag(item.patentNumber, "number");
if(item.issueDate) {
_mapTag(Zotero.Date.strToISO(item.issueDate), "date");
}
} else {
//we map as much as possible to DC for all other types. This will export some info
//and work very nicely on roundtrip. All of these fields legal for mtx:dc according to
//http://alcme.oclc.org/openurl/servlet/OAIHandler/extension?verb=GetMetadata&metadataPrefix=mtx&identifier=info:ofi/fmt:kev:mtx:dc
_mapTag("info:ofi/fmt:kev:mtx:dc", "rft_val_fmt", true);
//lacking something better we use Zotero item types here; no clear alternative and this works for roundtrip
_mapTag(item.itemType, "type");
_mapTag(item.title, "title");
_mapTag(item.publicationTitle, "source");
_mapTag(item.rights, "rights");
_mapTag(item.publisher, "publisher");
_mapTag(item.abstractNote, "description");
if(item.DOI){
_mapTag("urn:doi:" + item.DOI, "identifier");
}
else if(item.url){
_mapTag(item.url, "identifier");
}
}
if(item.creators && item.creators.length) {
// encode first author as first and last
let firstCreator = Zotero.Utilities.Internal.getFirstCreatorFromItemJSON(item);
if(item.itemType == "patent") {
_mapTag(firstCreator.firstName, "invfirst");
_mapTag(firstCreator.lastName, "invlast");
} else {
if (firstCreator.name) {
_mapTag(firstCreator.name, "aucorp");
} else {
_mapTag(firstCreator.firstName, "aufirst");
_mapTag(firstCreator.lastName, "aulast");
}
}
// encode subsequent creators as au
for(var i=0; i<item.creators.length; i++) {
_mapTag((item.creators[i].firstName ? item.creators[i].firstName+" " : "")+
item.creators[i].lastName, (item.itemType == "patent" ? "inventor" : "au"));
}
}
if(item.date) {
_mapTag(Zotero.Date.strToISO(item.date), (item.itemType == "patent" ? "appldate" : "date"));
}
if(item.pages) {
_mapTag(item.pages, "pages");
var pages = item.pages.split(/[-]/);
if(pages.length > 1) {
_mapTag(pages[0], "spage");
if(pages.length >= 2) _mapTag(pages[1], "epage");
}
}
_mapTag(item.numPages, "tpages");
_mapTag(item.ISBN, "isbn");
_mapTag(item.ISSN, "issn");
_mapTag(item.language, "language");
if(asObj) return entries;
return entries.join("&");
}
function _cloneIfNecessary(obj1, obj2) {
if (Zotero.isFx && !Zotero.isBookmarklet) {
return Components.utils.cloneInto(obj1, obj2);
}
return obj1;
}
/*
* Generates an item in the format returned by item.fromArray() given an
* OpenURL version 1.0 contextObject
*
* accepts an item array to fill, or creates and returns a new item array
*/
function parseContextObject(co, item) {
if(!item) {
var item = new Array();
item.creators = new Array();
}
var coParts = co.split("&");
// get type
for(var i=0; i<coParts.length; i++) {
if(coParts[i].substr(0, 12) == "rft_val_fmt=") {
var format = decodeURIComponent(coParts[i].substr(12));
if(format == "info:ofi/fmt:kev:mtx:journal") {
item.itemType = "journalArticle";
break;
} else if(format == "info:ofi/fmt:kev:mtx:book") {
if(coParts.indexOf("rft.genre=bookitem") !== -1) {
item.itemType = "bookSection";
} else if(coParts.indexOf("rft.genre=conference") !== -1 || coParts.indexOf("rft.genre=proceeding") !== -1) {
item.itemType = "conferencePaper";
} else if(coParts.indexOf("rft.genre=report") !== -1) {
item.itemType = "report";
} else if(coParts.indexOf("rft.genre=document") !== -1) {
item.itemType = "document";
} else {
item.itemType = "book";
}
break;
} else if(format == "info:ofi/fmt:kev:mtx:dissertation") {
item.itemType = "thesis";
break;
} else if(format == "info:ofi/fmt:kev:mtx:patent") {
item.itemType = "patent";
break;
} else if(format == "info:ofi/fmt:kev:mtx:dc") {
item.itemType = "webpage";
break;
}
}
}
if(!item.itemType) {
return false;
}
var pagesKey = "";
// keep track of "aucorp," "aufirst," "aulast"
var complexAu = new Array();
for(var i=0; i<coParts.length; i++) {
var keyVal = coParts[i].split("=");
var key = keyVal[0];
var value = decodeURIComponent(keyVal[1].replace(/\+|%2[bB]/g, " "));
if(!value) {
continue;
}
if(key == "rft_id") {
var firstEight = value.substr(0, 8).toLowerCase();
if(firstEight == "info:doi") {
item.DOI = value.substr(9);
} else if(firstEight == "urn:isbn") {
item.ISBN = value.substr(9);
} else if(value.match(/^https?:\/\//)) {
item.url = value;
item.accessDate = "";
}
} else if(key == "rft.btitle") {
if(item.itemType == "book" || item.itemType == "report") {
item.title = value;
} else if(item.itemType == "bookSection" || item.itemType == "conferencePaper") {
item.publicationTitle = value;
}
} else if(key == "rft.atitle"
&& ["journalArticle", "bookSection", "conferencePaper"].indexOf(item.itemType) !== -1) {
item.title = value;
} else if(key == "rft.jtitle" && item.itemType == "journalArticle") {
item.publicationTitle = value;
} else if(key == "rft.stitle" && item.itemType == "journalArticle") {
item.journalAbbreviation = value;
} else if(key == "rft.title") {
if(["journalArticle", "bookSection", "conferencePaper"].indexOf(item.itemType) !== -1) {
item.publicationTitle = value;
} else {
item.title = value;
}
} else if(key == "rft.date") {
if(item.itemType == "patent") {
item.issueDate = value;
} else {
item.date = value;
}
} else if(key == "rft.volume") {
item.volume = value;
} else if(key == "rft.issue") {
item.issue = value;
} else if(key == "rft.pages") {
pagesKey = key;
item.pages = value;
} else if(key == "rft.spage") {
if(pagesKey != "rft.pages") {
// make pages look like start-end
if(pagesKey == "rft.epage") {
if(value != item.pages) {
item.pages = value+"-"+item.pages;
}
} else {
item.pages = value;
}
pagesKey = key;
}
} else if(key == "rft.epage") {
if(pagesKey != "rft.pages") {
// make pages look like start-end
if(pagesKey == "rft.spage") {
if(value != item.pages) {
item.pages = item.pages+"-"+value;
}
} else {
item.pages = value;
}
pagesKey = key;
}
} else if(key == "rft.issn" || (key == "rft.eissn" && !item.ISSN)) {
item.ISSN = value;
} else if(key == "rft.aulast" || key == "rft.invlast") {
var lastCreator = complexAu[complexAu.length-1];
if(complexAu.length && !lastCreator.lastName && !lastCreator.institutional) {
lastCreator.lastName = value;
} else {
complexAu.push(_cloneIfNecessary({lastName:value, creatorType:(key == "rft.aulast" ? "author" : "inventor"), offset:item.creators.length}, item));
}
} else if(key == "rft.aufirst" || key == "rft.invfirst") {
var lastCreator = complexAu[complexAu.length-1];
if(complexAu.length && !lastCreator.firstName && !lastCreator.institutional) {
lastCreator.firstName = value;
} else {
complexAu.push(_cloneIfNecessary({firstName:value, creatorType:(key == "rft.aufirst" ? "author" : "inventor"), offset:item.creators.length}, item));
}
} else if(key == "rft.au" || key == "rft.creator" || key == "rft.contributor" || key == "rft.inventor") {
if(key == "rft.contributor") {
var type = "contributor";
} else if(key == "rft.inventor") {
var type = "inventor";
} else {
var type = "author";
}
item.creators.push(_cloneIfNecessary(Zotero.Utilities.cleanAuthor(value, type, value.indexOf(",") !== -1), item));
} else if(key == "rft.aucorp") {
complexAu.push(_cloneIfNecessary({lastName:value, fieldMode:1}, item));
} else if(key == "rft.isbn" && !item.ISBN) {
item.ISBN = value;
} else if(key == "rft.pub" || key == "rft.publisher") {
item.publisher = value;
} else if(key == "rft.place") {
item.place = value;
} else if(key == "rft.tpages") {
item.numPages = value;
} else if(key == "rft.edition") {
item.edition = value;
} else if(key == "rft.series") {
if(item.itemType == "report") {
item.seriesTitle = value;
} else {
item.series = value;
}
} else if(item.itemType == "thesis") {
if(key == "rft.inst") {
item.publisher = value;
} else if(key == "rft.degree") {
item.type = value;
}
} else if(item.itemType == "patent") {
if(key == "rft.assignee") {
item.assignee = value;
} else if(key == "rft.number") {
item.patentNumber = value;
} else if(key == "rft.appldate") {
item.date = value;
}
} else {
// The following keys are technically only valid in Dublin Core
// (i.e., format == "info:ofi/fmt:kev:mtx:dc") but in practice
// 'format' is not always set
if(key == "rft.identifier") {
if(value.length > 8) { // we could check length separately for
// each type, but all of these identifiers
// must be > 8 characters
if(value.substr(0, 5) == "ISBN ") {
item.ISBN = value.substr(5);
} else if(value.substr(0, 5) == "ISSN ") {
item.ISSN = value.substr(5);
} else if(value.substr(0, 8) == "urn:doi:") {
item.DOI = value.substr(4);
} else if(value.substr(0, 7) == "http://" || value.substr(0, 8) == "https://") {
item.url = value;
}
}
} else if(key == "rft.description") {
item.abstractNote = value;
} else if(key == "rft.rights") {
item.rights = value;
} else if(key == "rft.language") {
item.language = value;
} else if(key == "rft.subject") {
item.tags.push(value);
} else if(key == "rft.type") {
if(Zotero.Utilities.itemTypeExists(value)) item.itemType = value;
} else if(key == "rft.source") {
item.publicationTitle = value;
}
}
}
// To maintain author ordering when complex and simple authors are combined,
// we remember where they were and the correct offsets
var inserted = 0;
// combine two lists of authors, eliminating duplicates
for(var i=0; i<complexAu.length; i++) {
var pushMe = true;
var offset = complexAu[i].offset;
delete complexAu[i].offset;
for (var j = 0; j < item.creators.length; j++) {
// if there's a plain author that is close to this author (the
// same last name, and the same first name up to a point), keep
// the plain author, since it might have a middle initial
if (item.creators[j].lastName == complexAu[i].lastName &&
item.creators[j].firstName &&
((item.creators[j].firstName == "" && complexAu[i].firstName == "") ||
(item.creators[j].firstName.length >= complexAu[i].firstName.length &&
item.creators[j].firstName.substr(0, complexAu[i].firstName.length) == complexAu[i].firstName))) {
pushMe = false;
break;
}
}
// Splice in the complex creator at the correct location,
// accounting for previous insertions
if(pushMe) {
item.creators.splice(offset + inserted, 0, complexAu[i]);
inserted++;
}
}
return item;
}
}
if (typeof process === 'object' && process + '' === '[object process]'){
module.exports = Zotero.OpenURL;
}

View file

@ -1,495 +0,0 @@
// Identity management and indexing for RDF
//
// This file provides IndexedFormula a formula (set of triples) which
// indexed by predicate, subject and object.
//
// It "smushes" (merges into a single node) things which are identical
// according to owl:sameAs or an owl:InverseFunctionalProperty
// or an owl:FunctionalProperty
//
//
// 2005-10 Written Tim Berners-Lee
// 2007 Changed so as not to munge statements from documents when smushing
//
//
/*jsl:option explicit*/
// Turn on JavaScriptLint variable declaration checking
$rdf.IndexedFormula = function () {
var owl_ns = "http://www.w3.org/2002/07/owl#";
// var link_ns = "http://www.w3.org/2007/ont/link#";
/* hashString functions are used as array indeces. This is done to avoid
** conflict with existing properties of arrays such as length and map.
** See issue 139.
*/
$rdf.Literal.prototype.hashString = $rdf.Literal.prototype.toNT;
$rdf.Symbol.prototype.hashString = $rdf.Symbol.prototype.toNT;
$rdf.BlankNode.prototype.hashString = $rdf.BlankNode.prototype.toNT;
$rdf.Collection.prototype.hashString = $rdf.Collection.prototype.toNT;
//Stores an associative array that maps URIs to functions
$rdf.IndexedFormula = function (features) {
this.statements = []; // As in Formula
this.optional = [];
this.propertyActions = []; // Array of functions to call when getting statement with {s X o}
//maps <uri> to [f(F,s,p,o),...]
this.classActions = []; // Array of functions to call when adding { s type X }
this.redirections = []; // redirect to lexically smaller equivalent symbol
this.aliases = []; // reverse mapping to redirection: aliases for this
this.HTTPRedirects = []; // redirections we got from HTTP
this.subjectIndex = []; // Array of statements with this X as subject
this.predicateIndex = []; // Array of statements with this X as subject
this.objectIndex = []; // Array of statements with this X as object
this.whyIndex = []; // Array of statements with X as provenance
this.index = [this.subjectIndex, this.predicateIndex, this.objectIndex, this.whyIndex];
this.namespaces = {} // Dictionary of namespace prefixes
if(features === undefined) features = ["sameAs",
"InverseFunctionalProperty", "FunctionalProperty"];
// this.features = features
// Callbackify?
function handleRDFType(formula, subj, pred, obj, why) {
if(formula.typeCallback != undefined)
formula.typeCallback(formula, obj, why);
var x = formula.classActions[obj.hashString()];
var done = false;
if(x) {
for(var i = 0; i < x.length; i++) {
done = done || x[i](formula, subj, pred, obj, why);
}
}
return done; // statement given is not needed if true
} //handleRDFType
//If the predicate is #type, use handleRDFType to create a typeCallback on the object
this.propertyActions['<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>'] = [handleRDFType];
// Assumption: these terms are not redirected @@fixme
if($rdf.Util.ArrayIndexOf(features, "sameAs") >= 0)
this.propertyActions['<http://www.w3.org/2002/07/owl#sameAs>'] = [
function (formula, subj, pred, obj, why) {
// tabulator.log.warn("Equating "+subj.uri+" sameAs "+obj.uri); //@@
formula.equate(subj, obj);
return true; // true if statement given is NOT needed in the store
}]; //sameAs -> equate & don't add to index
if($rdf.Util.ArrayIndexOf(features, "InverseFunctionalProperty") >= 0)
this.classActions["<" + owl_ns + "InverseFunctionalProperty>"] = [
function (formula, subj, pred, obj, addFn) {
return formula.newPropertyAction(subj, handle_IFP); // yes subj not pred!
}]; //IFP -> handle_IFP, do add to index
if($rdf.Util.ArrayIndexOf(features, "FunctionalProperty") >= 0)
this.classActions["<" + owl_ns + "FunctionalProperty>"] = [
function (formula, subj, proj, obj, addFn) {
return formula.newPropertyAction(subj, handle_FP);
}
]; //FP => handleFP, do add to index
function handle_IFP(formula, subj, pred, obj) {
var s1 = formula.any(undefined, pred, obj);
if(s1 == undefined) return false; // First time with this value
// tabulator.log.warn("Equating "+s1.uri+" and "+subj.uri + " because IFP "+pred.uri); //@@
formula.equate(s1, subj);
return true;
} //handle_IFP
function handle_FP(formula, subj, pred, obj) {
var o1 = formula.any(subj, pred, undefined);
if(o1 == undefined) return false; // First time with this value
// tabulator.log.warn("Equating "+o1.uri+" and "+obj.uri + " because FP "+pred.uri); //@@
formula.equate(o1, obj);
return true;
} //handle_FP
} /* end IndexedFormula */
$rdf.IndexedFormula.prototype = new $rdf.Formula();
$rdf.IndexedFormula.prototype.constructor = $rdf.IndexedFormula;
$rdf.IndexedFormula.SuperClass = $rdf.Formula;
$rdf.IndexedFormula.prototype.newPropertyAction = function newPropertyAction(pred, action) {
//$rdf.log.debug("newPropertyAction: "+pred);
var hash = pred.hashString();
if(this.propertyActions[hash] == undefined)
this.propertyActions[hash] = [];
this.propertyActions[hash].push(action);
// Now apply the function to to statements already in the store
var toBeFixed = this.statementsMatching(undefined, pred, undefined);
var done = false;
for(var i = 0; i < toBeFixed.length; i++) { // NOT optimized - sort toBeFixed etc
done = done || action(this, toBeFixed[i].subject, pred, toBeFixed[i].object);
}
return done;
}
$rdf.IndexedFormula.prototype.setPrefixForURI = function (prefix, nsuri) {
//TODO:This is a hack for our own issues, which ought to be fixed post-release
//See http://dig.csail.mit.edu/cgi-bin/roundup.cgi/$rdf/issue227
if(prefix == "tab" && this.namespaces["tab"]) {
return;
}
this.namespaces[prefix] = nsuri
}
// Deprocated ... name too generic
$rdf.IndexedFormula.prototype.register = function (prefix, nsuri) {
this.namespaces[prefix] = nsuri
}
/** simplify graph in store when we realize two identifiers are equivalent
We replace the bigger with the smaller.
*/
$rdf.IndexedFormula.prototype.equate = function (u1, u2) {
// tabulator.log.warn("Equating "+u1+" and "+u2); // @@
//@@JAMBO Must canonicalize the uris to prevent errors from a=b=c
//03-21-2010
u1 = this.canon(u1);
u2 = this.canon(u2);
var d = u1.compareTerm(u2);
if(!d) return true; // No information in {a = a}
var big, small;
if(d < 0) { // u1 less than u2
return this.replaceWith(u2, u1);
} else {
return this.replaceWith(u1, u2);
}
}
// Replace big with small, obsoleted with obsoleting.
//
$rdf.IndexedFormula.prototype.replaceWith = function (big, small) {
//$rdf.log.debug("Replacing "+big+" with "+small) // @@
var oldhash = big.hashString();
var newhash = small.hashString();
var moveIndex = function (ix) {
var oldlist = ix[oldhash];
if(oldlist == undefined) return; // none to move
var newlist = ix[newhash];
if(newlist == undefined) {
ix[newhash] = oldlist;
} else {
ix[newhash] = oldlist.concat(newlist);
}
delete ix[oldhash];
}
// the canonical one carries all the indexes
for(var i = 0; i < 4; i++) {
moveIndex(this.index[i]);
}
this.redirections[oldhash] = small;
if(big.uri) {
//@@JAMBO: must update redirections,aliases from sub-items, too.
if(this.aliases[newhash] == undefined)
this.aliases[newhash] = [];
this.aliases[newhash].push(big); // Back link
if(this.aliases[oldhash]) {
for(var i = 0; i < this.aliases[oldhash].length; i++) {
this.redirections[this.aliases[oldhash][i].hashString()] = small;
this.aliases[newhash].push(this.aliases[oldhash][i]);
}
}
//this.add(small, this.sym('http://www.w3.org/2007/ont/link#uri'), big.uri)
// If two things are equal, and one is requested, we should request the other.
if(this.sf) {
this.sf.nowKnownAs(big, small)
}
}
moveIndex(this.classActions);
moveIndex(this.propertyActions);
$rdf.log.debug("Equate done. "+big+" now links to "+small)
return true; // true means the statement does not need to be put in
};
// Return the symbol with canonical URI as smushed
$rdf.IndexedFormula.prototype.canon = function (term) {
if(term == undefined) return term;
var y = this.redirections[term.hashString()];
if(y == undefined) return term;
return y;
}
// Compare by canonical URI as smushed
$rdf.IndexedFormula.prototype.sameThings = function (x, y) {
if(x.sameTerm(y)) return true;
var x1 = this.canon(x);
// alert('x1='+x1);
if(x1 == undefined) return false;
var y1 = this.canon(y);
// alert('y1='+y1); //@@
if(y1 == undefined) return false;
return(x1.uri == y1.uri);
}
// A list of all the URIs by which this thing is known
$rdf.IndexedFormula.prototype.uris = function (term) {
var cterm = this.canon(term)
var terms = this.aliases[cterm.hashString()];
if(!cterm.uri) return []
var res = [cterm.uri]
if(terms != undefined) {
for(var i = 0; i < terms.length; i++) {
res.push(terms[i].uri)
}
}
return res
}
// On input parameters, convert constants to terms
//
function RDFMakeTerm(formula, val, canonicalize) {
if(typeof val != 'object') {
if(typeof val == 'string')
return new $rdf.Literal(val);
if(typeof val == 'number')
return new $rdf.Literal(val); // @@ differet types
if(typeof val == 'boolean')
return new $rdf.Literal(val ? "1" : "0", undefined, $rdf.Symbol.prototype.XSDboolean);
if(typeof val == 'undefined')
return undefined;
else // @@ add converting of dates and numbers
throw new Error("Can't make Term from " + val + " of type " + typeof val);
}
return val;
}
// Add a triple to the store
//
// Returns the statement added
// (would it be better to return the original formula for chaining?)
//
$rdf.IndexedFormula.prototype.add = function (subj, pred, obj, why) {
var actions, st;
if(why == undefined) why = this.fetcher ? this.fetcher.appNode : this.sym("chrome:theSession"); //system generated
//defined in source.js, is this OK with identity.js only user?
subj = RDFMakeTerm(this, subj);
pred = RDFMakeTerm(this, pred);
obj = RDFMakeTerm(this, obj);
why = RDFMakeTerm(this, why);
if(this.predicateCallback != undefined)
this.predicateCallback(this, pred, why);
// Action return true if the statement does not need to be added
var actions = this.propertyActions[this.canon(pred).hashString()];
var done = false;
if(actions) {
// alert('type: '+typeof actions +' @@ actions='+actions);
for(var i = 0; i < actions.length; i++) {
done = done || actions[i](this, subj, pred, obj, why);
}
}
//If we are tracking provenanance, every thing should be loaded into the store
//if (done) return new Statement(subj, pred, obj, why); // Don't put it in the store
// still return this statement for owl:sameAs input
var hash = [this.canon(subj).hashString(), this.canon(pred).hashString(),
this.canon(obj).hashString(), this.canon(why).hashString()];
var st = new $rdf.Statement(subj, pred, obj, why);
for(var i = 0; i < 4; i++) {
var ix = this.index[i];
var h = hash[i];
if(ix[h] == undefined) ix[h] = [];
ix[h].push(st); // Set of things with this as subject, etc
}
//tabulator.log.debug("ADDING {"+subj+" "+pred+" "+obj+"} "+why);
this.statements.push(st);
return st;
}; //add
// Find out whether a given URI is used as symbol in the formula
$rdf.IndexedFormula.prototype.mentionsURI = function (uri) {
var hash = '<' + uri + '>';
return (!!this.subjectIndex[hash]
|| !!this.objectIndex[hash]
|| !!this.predicateIndex[hash]);
}
// Find an unused id for a file being edited: return a symbol
// (Note: Slow iff a lot of them -- could be O(log(k)) )
$rdf.IndexedFormula.prototype.nextSymbol = function (doc) {
for(var i = 0;; i++) {
var uri = doc.uri + '#n' + i;
if(!this.mentionsURI(uri)) return this.sym(uri);
}
}
$rdf.IndexedFormula.prototype.anyStatementMatching = function (subj, pred, obj, why) {
var x = this.statementsMatching(subj, pred, obj, why, true);
if(!x || x == []) return undefined;
return x[0];
};
// Return statements matching a pattern
// ALL CONVENIENCE LOOKUP FUNCTIONS RELY ON THIS!
$rdf.IndexedFormula.prototype.statementsMatching = function (subj, pred, obj, why, justOne) {
//$rdf.log.debug("Matching {"+subj+" "+pred+" "+obj+"}");
var pat = [subj, pred, obj, why];
var pattern = [];
var hash = [];
var wild = []; // wildcards
var given = []; // Not wild
for(var p = 0; p < 4; p++) {
pattern[p] = this.canon(RDFMakeTerm(this, pat[p]));
if(pattern[p] == undefined) {
wild.push(p);
} else {
given.push(p);
hash[p] = pattern[p].hashString();
}
}
if(given.length == 0) {
return this.statements;
}
if(given.length == 1) { // Easy too, we have an index for that
var p = given[0];
var list = this.index[p][hash[p]];
if(list && justOne) {
if(list.length > 1)
list = list.slice(0, 1);
}
return list == undefined ? [] : list;
}
// Now given.length is 2, 3 or 4.
// We hope that the scale-free nature of the data will mean we tend to get
// a short index in there somewhere!
var best = 1e10; // really bad
var best_i;
for(var i = 0; i < given.length; i++) {
var p = given[i]; // Which part we are dealing with
var list = this.index[p][hash[p]];
if(list == undefined) return []; // No occurrences
if(list.length < best) {
best = list.length;
best_i = i; // (not p!)
}
}
// Ok, we have picked the shortest index but now we have to filter it
var best_p = given[best_i];
var possibles = this.index[best_p][hash[best_p]];
var check = given.slice(0, best_i).concat(given.slice(best_i + 1)) // remove best_i
var results = [];
var parts = ['subject', 'predicate', 'object', 'why'];
for(var j = 0; j < possibles.length; j++) {
var st = possibles[j];
for(var i = 0; i < check.length; i++) { // for each position to be checked
var p = check[i];
if(!this.canon(st[parts[p]]).sameTerm(pattern[p])) {
st = null;
break;
}
}
if(st != null) {
results.push(st);
if(justOne)
break;
}
}
return results;
}; // statementsMatching
/** remove a particular statement from the bank **/
$rdf.IndexedFormula.prototype.remove = function (st) {
//$rdf.log.debug("entering remove w/ st=" + st);
var term = [st.subject, st.predicate, st.object, st.why];
for(var p = 0; p < 4; p++) {
var c = this.canon(term[p]);
var h = c.hashString();
if(this.index[p][h] == undefined) {
//$rdf.log.warn ("Statement removal: no index '+p+': "+st);
} else {
$rdf.Util.RDFArrayRemove(this.index[p][h], st);
}
}
$rdf.Util.RDFArrayRemove(this.statements, st);
}; //remove
/** remove all statements matching args (within limit) **/
$rdf.IndexedFormula.prototype.removeMany = function (subj, pred, obj, why, limit) {
//$rdf.log.debug("entering removeMany w/ subj,pred,obj,why,limit = " + subj +", "+ pred+", " + obj+", " + why+", " + limit);
var sts = this.statementsMatching(subj, pred, obj, why, false);
//This is a subtle bug that occcured in updateCenter.js too.
//The fact is, this.statementsMatching returns this.whyIndex instead of a copy of it
//but for perfromance consideration, it's better to just do that
//so make a copy here.
var statements = [];
for(var i = 0; i < sts.length; i++) statements.push(sts[i]);
if(limit) statements = statements.slice(0, limit);
for(var i = 0; i < statements.length; i++) this.remove(statements[i]);
}; //removeMany
/** Utility**/
/* @method: copyTo
@description: replace @template with @target and add appropriate triples (no triple removed)
one-direction replication
*/
$rdf.IndexedFormula.prototype.copyTo = function (template, target, flags) {
if(!flags) flags = [];
var statList = this.statementsMatching(template);
if($rdf.Util.ArrayIndexOf(flags, 'two-direction') != -1)
statList.concat(this.statementsMatching(undefined, undefined, template));
for(var i = 0; i < statList.length; i++) {
var st = statList[i];
switch(st.object.termType) {
case 'symbol':
this.add(target, st.predicate, st.object);
break;
case 'literal':
case 'bnode':
case 'collection':
this.add(target, st.predicate, st.object.copy(this));
}
if($rdf.Util.ArrayIndexOf(flags, 'delete') != -1) this.remove(st);
}
};
//for the case when you alter this.value (text modified in userinput.js)
$rdf.Literal.prototype.copy = function () {
return new $rdf.Literal(this.value, this.lang, this.datatype);
};
$rdf.BlankNode.prototype.copy = function (formula) { //depends on the formula
var bnodeNew = new $rdf.BlankNode();
formula.copyTo(this, bnodeNew);
return bnodeNew;
}
/** Full N3 bits -- placeholders only to allow parsing, no functionality! **/
$rdf.IndexedFormula.prototype.newUniversal = function (uri) {
var x = this.sym(uri);
if(!this._universalVariables) this._universalVariables = [];
this._universalVariables.push(x);
return x;
}
$rdf.IndexedFormula.prototype.newExistential = function (uri) {
if(!uri) return this.bnode();
var x = this.sym(uri);
return this.declareExistential(x);
}
$rdf.IndexedFormula.prototype.declareExistential = function (x) {
if(!this._existentialVariables) this._existentialVariables = [];
this._existentialVariables.push(x);
return x;
}
$rdf.IndexedFormula.prototype.formula = function (features) {
return new $rdf.IndexedFormula(features);
}
$rdf.IndexedFormula.prototype.close = function () {
return this;
}
$rdf.IndexedFormula.prototype.hashString = $rdf.IndexedFormula.prototype.toNT;
return $rdf.IndexedFormula;
}();
// ends

View file

@ -1,34 +0,0 @@
/* Set up the environment before loading the rest of the files into Zotero */
var $rdf = {
Util: {
ArrayIndexOf: function (arr, item, i) {
//supported in all browsers except IE<9
return arr.indexOf(item, i);
},
RDFArrayRemove: function (a, x) { //removes all statements equal to x from a
for (var i = 0; i < a.length; i++) {
//TODO: This used to be the following, which didnt always work..why
//if(a[i] == x)
if (a[i].subject.sameTerm(x.subject) && a[i].predicate.sameTerm(x.predicate) && a[i].object.sameTerm(x.object) && a[i].why.sameTerm(x.why)) {
a.splice(i, 1);
return;
}
}
throw new Error("RDFArrayRemove: Array did not contain " + x);
}
},
log: {
debug: Zotero.debug,
warn: Zotero.debug,
error: Zotero.debug
}
};
if(Zotero.RDF) {
Zotero.RDF.AJAW = $rdf;
} else {
Zotero.RDF = {AJAW:$rdf};
}
var tabulator = {log: $rdf.log};
var alert = $rdf.log.warn;

View file

@ -1,144 +0,0 @@
// Matching a statement against a formula
//
//
// W3C open source licence 2005.
//
// We retpresent a set as an associative array whose value for
// each member is set to true.
$rdf.Symbol.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.uri == other.uri))
}
$rdf.BlankNode.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.id == other.id))
}
$rdf.Literal.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType)
&& (this.value == other.value)
&& (this.lang == other.lang)
&& ((!this.datatype && !other.datatype)
|| (this.datatype && this.datatype.sameTerm(other.datatype))))
}
$rdf.Variable.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.uri == other.uri))
}
$rdf.Collection.prototype.sameTerm = $rdf.BlankNode.prototype.sameTerm
$rdf.Formula.prototype.sameTerm = function (other) {
return this.hashString() == other.hashString();
}
// Comparison for ordering
//
// These compare with ANY term
//
//
// When we smush nodes we take the lowest value. This is not
// arbitrary: we want the value actually used to be the literal
// (or list or formula).
$rdf.Literal.prototype.classOrder = 1
$rdf.Collection.prototype.classOrder = 3
$rdf.Formula.prototype.classOrder = 4
$rdf.Symbol.prototype.classOrder = 5
$rdf.BlankNode.prototype.classOrder = 6
// Compaisons return sign(self - other)
// Literals must come out before terms for smushing
$rdf.Literal.prototype.compareTerm = function (other) {
if(this.classOrder < other.classOrder) return -1
if(this.classOrder > other.classOrder) return +1
if(this.value < other.value) return -1
if(this.value > other.value) return +1
return 0
}
$rdf.Symbol.prototype.compareTerm = function (other) {
if(this.classOrder < other.classOrder) return -1
if(this.classOrder > other.classOrder) return +1
if(this.uri < other.uri) return -1
if(this.uri > other.uri) return +1
return 0
}
$rdf.BlankNode.prototype.compareTerm = function (other) {
if(this.classOrder < other.classOrder) return -1
if(this.classOrder > other.classOrder) return +1
if(this.id < other.id) return -1
if(this.id > other.id) return +1
return 0
}
$rdf.Collection.prototype.compareTerm = $rdf.BlankNode.prototype.compareTerm
// Convenience routines
// Only one of s p o can be undefined, and w is optional.
$rdf.Formula.prototype.each = function (s, p, o, w) {
var results = []
var st, sts = this.statementsMatching(s, p, o, w, false)
var i, n = sts.length
if(typeof s == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.subject)
}
} else if(typeof p == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.predicate)
}
} else if(typeof o == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.object)
}
} else if(typeof w == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.why)
}
}
return results
}
$rdf.Formula.prototype.any = function (s, p, o, w) {
var st = this.anyStatementMatching(s, p, o, w)
if(typeof st == 'undefined') return undefined;
if(typeof s == 'undefined') return st.subject;
if(typeof p == 'undefined') return st.predicate;
if(typeof o == 'undefined') return st.object;
return undefined
}
$rdf.Formula.prototype.holds = function (s, p, o, w) {
var st = this.anyStatementMatching(s, p, o, w)
if(typeof st == 'undefined') return false;
return true;
}
$rdf.Formula.prototype.the = function (s, p, o, w) {
// the() should contain a check there is only one
var x = this.any(s, p, o, w)
if(typeof x == 'undefined')
$rdf.log.error("No value found for the(){" + s + " " + p + " " + o + "}.")
return x
}
$rdf.Formula.prototype.whether = function (s, p, o, w) {
return this.statementsMatching(s, p, o, w, false).length;
}

File diff suppressed because it is too large Load diff

View file

@ -1,569 +0,0 @@
/**
* @fileoverview
* TABULATOR RDF PARSER
*
* Version 0.1
* Parser believed to be in full positive RDF/XML parsing compliance
* with the possible exception of handling deprecated RDF attributes
* appropriately. Parser is believed to comply fully with other W3C
* and industry standards where appropriate (DOM, ECMAScript, &c.)
*
* Author: David Sheets <dsheets@mit.edu>
* SVN ID: $Id$
*
* W3C® SOFTWARE NOTICE AND LICENSE
* http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
* This work (and included software, documentation such as READMEs, or
* other related items) is being provided by the copyright holders under
* the following license. By obtaining, using and/or copying this work,
* you (the licensee) agree that you have read, understood, and will
* comply with the following terms and conditions.
*
* Permission to copy, modify, and distribute this software and its
* documentation, with or without modification, for any purpose and
* without fee or royalty is hereby granted, provided that you include
* the following on ALL copies of the software and documentation or
* portions thereof, including modifications:
*
* 1. The full text of this NOTICE in a location viewable to users of
* the redistributed or derivative work.
* 2. Any pre-existing intellectual property disclaimers, notices, or terms and
* conditions. If none exist, the W3C Software Short Notice should be
* included (hypertext is preferred, text is permitted) within the body
* of any redistributed or derivative code.
* 3. Notice of any changes or modifications to the files, including the
* date changes were made. (We recommend you provide URIs to the location
* from which the code is derived.)
*
* THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
* HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
* FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
* DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
* TRADEMARKS OR OTHER RIGHTS.
*
* COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL
* OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
* DOCUMENTATION.
*
* The name and trademarks of copyright holders may NOT be used in
* advertising or publicity pertaining to the software without specific,
* written prior permission. Title to copyright in this software and any
* associated documentation will at all times remain with copyright
* holders.
*/
/**
* @class Class defining an RDFParser resource object tied to an RDFStore
*
* @author David Sheets <dsheets@mit.edu>
* @version 0.1
*
* @constructor
* @param {RDFStore} store An RDFStore object
*/
$rdf.RDFParser = function (store) {
var RDFParser = {};
/** Standard namespaces that we know how to handle @final
* @member RDFParser
*/
RDFParser['ns'] = {
'RDF': "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
'RDFS': "http://www.w3.org/2000/01/rdf-schema#"
}
/** DOM Level 2 node type magic numbers @final
* @member RDFParser
*/
RDFParser['nodeType'] = {
'ELEMENT': 1,
'ATTRIBUTE': 2,
'TEXT': 3,
'CDATA_SECTION': 4,
'ENTITY_REFERENCE': 5,
'ENTITY': 6,
'PROCESSING_INSTRUCTION': 7,
'COMMENT': 8,
'DOCUMENT': 9,
'DOCUMENT_TYPE': 10,
'DOCUMENT_FRAGMENT': 11,
'NOTATION': 12
}
/**
* Frame class for namespace and base URI lookups
* Base lookups will always resolve because the parser knows
* the default base.
*
* @private
*/
this['frameFactory'] = function (parser, parent, element) {
return {
'NODE': 1,
'ARC': 2,
'parent': parent,
'parser': parser,
'store': parser['store'],
'element': element,
'lastChild': 0,
'base': null,
'lang': null,
'node': null,
'nodeType': null,
'listIndex': 1,
'rdfid': null,
'datatype': null,
'collection': false,
/** Terminate the frame and notify the store that we're done */
'terminateFrame': function () {
if(this['collection']) {
this['node']['close']()
}
},
/** Add a symbol of a certain type to the this frame */
'addSymbol': function (type, uri) {
uri = $rdf.Util.uri.join(uri, this['base'])
this['node'] = this['store']['sym'](uri)
this['nodeType'] = type
},
/** Load any constructed triples into the store */
'loadTriple': function () {
if(this['parent']['parent']['collection']) {
this['parent']['parent']['node']['append'](this['node'])
} else {
this['store']['add'](this['parent']['parent']['node'],
this['parent']['node'],
this['node'],
this['parser']['why'])
}
if(this['parent']['rdfid'] != null) { // reify
var triple = this['store']['sym'](
$rdf.Util.uri.join("#" + this['parent']['rdfid'], this['base']))
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "type"),
this['store']['sym'](RDFParser['ns']['RDF'] + "Statement"),
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "subject"),
this['parent']['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "predicate"),
this['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "object"),
this['node'],
this['parser']['why'])
}
},
/** Check if it's OK to load a triple */
'isTripleToLoad': function () {
return (this['parent'] != null
&& this['parent']['parent'] != null
&& this['nodeType'] == this['NODE']
&& this['parent']['nodeType'] == this['ARC']
&& this['parent']['parent']['nodeType'] == this['NODE'])
},
/** Add a symbolic node to this frame */
'addNode': function (uri) {
this['addSymbol'](this['NODE'], uri)
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add a collection node to this frame */
'addCollection': function () {
this['nodeType'] = this['NODE']
this['node'] = this['store']['collection']()
this['collection'] = true
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add a collection arc to this frame */
'addCollectionArc': function () {
this['nodeType'] = this['ARC']
},
/** Add a bnode to this frame */
'addBNode': function (id) {
if(id != null) {
if(this['parser']['bnodes'][id] != null) {
this['node'] = this['parser']['bnodes'][id]
} else {
this['node'] = this['parser']['bnodes'][id] = this['store']['bnode']()
}
} else {
this['node'] = this['store']['bnode']()
}
this['nodeType'] = this['NODE']
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add an arc or property to this frame */
'addArc': function (uri) {
if(uri == RDFParser['ns']['RDF'] + "li") {
uri = RDFParser['ns']['RDF'] + "_" + this['parent']['listIndex']++
}
this['addSymbol'](this['ARC'], uri)
},
/** Add a literal to this frame */
'addLiteral': function (value) {
if(this['parent']['datatype']) {
this['node'] = this['store']['literal'](
value, "", this['store']['sym'](
this['parent']['datatype']))
} else {
this['node'] = this['store']['literal'](
value, this['lang'])
}
this['nodeType'] = this['NODE']
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
}
}
}
//from the OpenLayers source .. needed to get around IE problems.
this['getAttributeNodeNS'] = function (node, uri, name) {
var attributeNode = null;
if(node.getAttributeNodeNS) {
attributeNode = node.getAttributeNodeNS(uri, name);
} else {
var attributes = node.attributes;
var potentialNode, fullName;
for(var i = 0; i < attributes.length; ++i) {
potentialNode = attributes[i];
if(potentialNode.namespaceURI == uri) {
fullName = (potentialNode.prefix) ? (potentialNode.prefix + ":" + name) : name;
if(fullName == potentialNode.nodeName) {
attributeNode = potentialNode;
break;
}
}
}
}
return attributeNode;
}
/** Our triple store reference @private */
this['store'] = store
/** Our identified blank nodes @private */
this['bnodes'] = {}
/** A context for context-aware stores @private */
this['why'] = null
/** Reification flag */
this['reify'] = false
/**
* Build our initial scope frame and parse the DOM into triples
* @param {DOMTree} document The DOM to parse
* @param {String} base The base URL to use
* @param {Object} why The context to which this resource belongs
*/
this['parse'] = function (document, base, why) {
// alert('parse base:'+base);
var children = document['childNodes']
// clean up for the next run
this['cleanParser']()
// figure out the root element
//var root = document.documentElement; //this is faster, I think, cross-browser issue? well, DOM 2
if(document['nodeType'] == RDFParser['nodeType']['DOCUMENT']) {
for(var c = 0; c < children['length']; c++) {
if(children[c]['nodeType'] == RDFParser['nodeType']['ELEMENT']) {
var root = children[c]
break
}
}
} else if(document['nodeType'] == RDFParser['nodeType']['ELEMENT']) {
var root = document
} else {
throw new Error("RDFParser: can't find root in " + base + ". Halting. ")
return false
}
this['why'] = why
// our topmost frame
var f = this['frameFactory'](this)
this['base'] = base
f['base'] = base
f['lang'] = ''
this['parseDOM'](this['buildFrame'](f, root))
return true
}
this['parseDOM'] = function (frame) {
// a DOM utility function used in parsing
var elementURI = function (el) {
var result = "";
if(el['namespaceURI'] == null) {
throw new Error("RDF/XML syntax error: No namespace for "
+ el['localName'] + " in " + this.base)
}
if(el['namespaceURI']) {
result = result + el['namespaceURI'];
}
if(el['localName']) {
result = result + el['localName'];
} else if(el['nodeName']) {
if(el['nodeName'].indexOf(":") >= 0)
result = result + el['nodeName'].split(":")[1];
else
result = result + el['nodeName'];
}
return result;
}
var dig = true // if we'll dig down in the tree on the next iter
while(frame['parent']) {
var dom = frame['element']
var attrs = dom['attributes']
if(dom['nodeType'] == RDFParser['nodeType']['TEXT']
|| dom['nodeType'] == RDFParser['nodeType']['CDATA_SECTION']) {
//we have a literal
if(frame['parent']['nodeType'] == frame['NODE']) {
//must have had attributes, store as rdf:value
frame['addArc'](RDFParser['ns']['RDF'] + 'value');
frame = this['buildFrame'](frame);
}
frame['addLiteral'](dom['nodeValue'])
} else if(elementURI(dom) != RDFParser['ns']['RDF'] + "RDF") {
// not root
if(frame['parent'] && frame['parent']['collection']) {
// we're a collection element
frame['addCollectionArc']()
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
}
if(!frame['parent'] || !frame['parent']['nodeType']
|| frame['parent']['nodeType'] == frame['ARC']) {
// we need a node
var about = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "about")
var rdfid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "ID")
if(about && rdfid) {
throw new Error("RDFParser: " + dom['nodeName']
+ " has both rdf:id and rdf:about." + " Halting. Only one of these"
+ " properties may be specified on a" + " node.");
}
if(about == null && rdfid) {
frame['addNode']("#" + rdfid['nodeValue'])
dom['removeAttributeNode'](rdfid)
} else if(about == null && rdfid == null) {
var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "nodeID")
if(bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else {
frame['addBNode']()
}
} else {
frame['addNode'](about['nodeValue'])
dom['removeAttributeNode'](about)
}
// Typed nodes
var rdftype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "type")
if(RDFParser['ns']['RDF'] + "Description" != elementURI(dom)) {
rdftype = {
'nodeValue': elementURI(dom)
}
}
if(rdftype != null) {
this['store']['add'](frame['node'],
this['store']['sym'](RDFParser['ns']['RDF'] + "type"),
this['store']['sym'](
$rdf.Util.uri.join(
rdftype['nodeValue'],
frame['base'])),
this['why'])
if(rdftype['nodeName']) {
dom['removeAttributeNode'](rdftype)
}
}
// Property Attributes
for(var x = attrs['length'] - 1; x >= 0; x--) {
this['store']['add'](frame['node'],
this['store']['sym'](elementURI(attrs[x])),
this['store']['literal'](
attrs[x]['nodeValue'],
frame['lang']),
this['why'])
}
} else {
// we should add an arc (or implicit bnode+arc)
frame['addArc'](elementURI(dom))
// save the arc's rdf:ID if it has one
if(this['reify']) {
var rdfid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "ID")
if(rdfid) {
frame['rdfid'] = rdfid['nodeValue']
dom['removeAttributeNode'](rdfid)
}
}
var parsetype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "parseType")
var datatype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "datatype")
if(datatype) {
frame['datatype'] = datatype['nodeValue']
dom['removeAttributeNode'](datatype)
}
if(parsetype) {
var nv = parsetype['nodeValue']
if(nv == "Literal") {
frame['datatype'] = RDFParser['ns']['RDF'] + "XMLLiteral"
// (this.buildFrame(frame)).addLiteral(dom)
// should work but doesn't
frame = this['buildFrame'](frame)
frame['addLiteral'](dom)
dig = false
} else if(nv == "Resource") {
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
frame['addBNode']()
} else if(nv == "Collection") {
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
frame['addCollection']()
}
dom['removeAttributeNode'](parsetype)
}
if(attrs['length'] != 0) {
var resource = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "resource")
var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "nodeID")
frame = this['buildFrame'](frame)
if(resource) {
frame['addNode'](resource['nodeValue'])
dom['removeAttributeNode'](resource)
} else {
if(bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else {
frame['addBNode']()
}
}
for(var x = attrs['length'] - 1; x >= 0; x--) {
var f = this['buildFrame'](frame)
f['addArc'](elementURI(attrs[x]))
if(elementURI(attrs[x]) == RDFParser['ns']['RDF'] + "type") {
(this['buildFrame'](f))['addNode'](
attrs[x]['nodeValue'])
} else {
(this['buildFrame'](f))['addLiteral'](
attrs[x]['nodeValue'])
}
}
} else if(dom['childNodes']['length'] == 0) {
(this['buildFrame'](frame))['addLiteral']("")
}
}
} // rdf:RDF
// dig dug
dom = frame['element']
while(frame['parent']) {
var pframe = frame
while(dom == null) {
frame = frame['parent']
dom = frame['element']
}
var candidate = dom['childNodes'][frame['lastChild']]
if(candidate == null || !dig) {
frame['terminateFrame']()
if(!(frame = frame['parent'])) {
break
} // done
dom = frame['element']
dig = true
} else if((candidate['nodeType'] != RDFParser['nodeType']['ELEMENT']
&& candidate['nodeType'] != RDFParser['nodeType']['TEXT']
&& candidate['nodeType'] != RDFParser['nodeType']['CDATA_SECTION'])
|| ((candidate['nodeType'] == RDFParser['nodeType']['TEXT']
|| candidate['nodeType'] == RDFParser['nodeType']['CDATA_SECTION'])
&& dom['childNodes']['length'] != 1)) {
frame['lastChild']++
} else {
// not a leaf
frame['lastChild']++;
frame = this['buildFrame'](pframe, dom['childNodes'][frame['lastChild'] - 1])
break
}
}
} // while
}
/**
* Cleans out state from a previous parse run
* @private
*/
this['cleanParser'] = function () {
this['bnodes'] = {}
this['why'] = null
}
/**
* Builds scope frame
* @private
*/
this['buildFrame'] = function (parent, element) {
var frame = this['frameFactory'](this, parent, element)
if(parent) {
frame['base'] = parent['base']
frame['lang'] = parent['lang']
}
if(element == null
|| element['nodeType'] == RDFParser['nodeType']['TEXT']
|| element['nodeType'] == RDFParser['nodeType']['CDATA_SECTION']) {
return frame
}
var attrs = element['attributes']
var base = element['getAttributeNode']("xml:base")
if(base != null) {
frame['base'] = base['nodeValue']
element['removeAttribute']("xml:base")
}
var lang = element['getAttributeNode']("xml:lang")
if(lang != null) {
frame['lang'] = lang['nodeValue']
element['removeAttribute']("xml:lang")
}
// remove all extraneous xml and xmlns attributes
for(var x = attrs['length'] - 1; x >= 0; x--) {
if(attrs[x]['nodeName']['substr'](0, 3) == "xml") {
if(attrs[x].name.slice(0, 6) == 'xmlns:') {
var uri = attrs[x].nodeValue;
// alert('base for namespac attr:'+this.base);
if(this.base) uri = $rdf.Util.uri.join(uri, this.base);
this.store.setPrefixForURI(attrs[x].name.slice(6), uri);
}
// alert('rdfparser: xml atribute: '+attrs[x].name) //@@
element['removeAttributeNode'](attrs[x])
}
}
return frame
}
}

View file

@ -1,877 +0,0 @@
/* Serialization of RDF Graphs
**
** Tim Berners-Lee 2006
** This is or was http://dig.csail.mit.edu/2005/ajar/ajaw/js/rdf/serialize.js
**
** Bug: can't serialize http://data.semanticweb.org/person/abraham-bernstein/rdf
** in XML (from mhausenblas)
*/
// @@@ Check the whole toStr thing tosee whetehr it still makes sense -- tbl
//
$rdf.Serializer = function () {
var __Serializer = function (store) {
this.flags = "";
this.base = null;
this.prefixes = [];
this.keywords = ['a']; // The only one we generate at the moment
this.prefixchars = "abcdefghijklmnopqustuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
this.incoming = null; // Array not calculated yet
this.formulas = []; // remebering original formulae from hashes
this.store = store;
/* pass */
}
var Serializer = function (store) {
return new __Serializer(store)
};
__Serializer.prototype.setBase = function (base) {
this.base = base
};
__Serializer.prototype.setFlags = function (flags) {
this.flags = flags ? flags : ''
};
__Serializer.prototype.toStr = function (x) {
var s = x.toNT();
if(x.termType == 'formula') {
this.formulas[s] = x; // remember as reverse does not work
}
return s;
};
__Serializer.prototype.fromStr = function (s) {
if(s[0] == '{') {
var x = this.formulas[s];
if(!x) alert('No formula object for ' + s)
return x;
}
return this.store.fromNT(s);
};
/* Accumulate Namespaces
**
** These are only hints. If two overlap, only one gets used
** There is therefore no guarantee in general.
*/
__Serializer.prototype.suggestPrefix = function (prefix, uri) {
this.prefixes[uri] = prefix;
}
// Takes a namespace -> prefix map
__Serializer.prototype.suggestNamespaces = function (namespaces) {
for(var px in namespaces) {
this.prefixes[namespaces[px]] = px;
}
}
// Make up an unused prefix for a random namespace
__Serializer.prototype.makeUpPrefix = function (uri) {
var p = uri;
var namespaces = [];
var pok;
var sz = this;
function canUse(pp) {
if(namespaces[pp]) return false; // already used
sz.prefixes[uri] = pp;
pok = pp;
return true
}
for(var ns in sz.prefixes) {
namespaces[sz.prefixes[ns]] = ns; // reverse index
}
// trim off illegal characters from the end
var i;
for(i = p.length - 1; i>=0; i--) {
if(sz._notNameChars.indexOf(p.charAt(i)) == -1) break;
}
p = p.substring(0, i+1);
if(p) {
// find shortest possible NCName to use as namespace name
for(i = p.length - 1; i>=0; i--) {
if(sz._notNameChars.indexOf(p.charAt(i)) != -1) break;
}
i++;
p = p.substr(i);
if(p.length < 6 && canUse(p)) return pok; // exact is best
if(canUse(p.slice(0, 3))) return pok;
if(canUse(p.slice(0, 2))) return pok;
if(canUse(p.slice(0, 4))) return pok;
if(canUse(p.slice(0, 1))) return pok;
if(canUse(p.slice(0, 5))) return pok;
p = p.slice(0, 3);
} else {
// no suitable characters (weird), fall back to 'ns'
p = 'ns';
if(canUse(p)) return pok;
}
for(var i = 0;; i++) if(canUse(p + i)) return pok;
}
// Todo:
// - Sort the statements by subject, pred, object
// - do stuff about the docu first and then (or first) about its primary topic.
__Serializer.prototype.rootSubjects = function (sts) {
var incoming = {};
var subjects = {};
var sz = this;
var allBnodes = {};
/* This scan is to find out which nodes will have to be the roots of trees
** in the serialized form. This will be any symbols, and any bnodes
** which hve more or less than one incoming arc, and any bnodes which have
** one incoming arc but it is an uninterrupted loop of such nodes back to itself.
** This should be kept linear time with repect to the number of statements.
** Note it does not use any indexing of the store.
*/
tabulator.log.debug('serialize.js Find bnodes with only one incoming arc\n')
for(var i = 0; i < sts.length; i++) {
var st = sts[i];
[st.subject, st.predicate, st.object].map(function (y) {
if(y.termType == 'bnode') {
allBnodes[y.toNT()] = true
}
});
var x = sts[i].object;
if(!incoming[x]) incoming[x] = [];
incoming[x].push(st.subject) // List of things which will cause this to be printed
var ss = subjects[sz.toStr(st.subject)]; // Statements with this as subject
if(!ss) ss = [];
ss.push(st);
subjects[this.toStr(st.subject)] = ss; // Make hash. @@ too slow for formula?
//$rdf.log.debug(' sz potential subject: '+sts[i].subject)
}
var roots = [];
for(var xNT in subjects) {
var x = sz.fromStr(xNT);
if((x.termType != 'bnode') || !incoming[x] || (incoming[x].length != 1)) {
roots.push(x);
//$rdf.log.debug(' sz actual subject -: ' + x)
continue;
}
}
this.incoming = incoming; // Keep for serializing @@ Bug for nested formulas
//////////// New bit for CONNECTED bnode loops:frootshash
// This scans to see whether the serialization is gpoing to lead to a bnode loop
// and at the same time accumulates a list of all bnodes mentioned.
// This is in fact a cut down N3 serialization
/*
tabulator.log.debug('serialize.js Looking for connected bnode loops\n')
for (var i=0; i<sts.length; i++) { // @@TBL
// dump('\t'+sts[i]+'\n');
}
var doneBnodesNT = {};
function dummyPropertyTree(subject, subjects, rootsHash) {
// dump('dummyPropertyTree('+subject+'...)\n');
var sts = subjects[sz.toStr(subject)]; // relevant statements
for (var i=0; i<sts.length; i++) {
dummyObjectTree(sts[i].object, subjects, rootsHash);
}
}
// Convert a set of statements into a nested tree of lists and strings
// @param force, "we know this is a root, do it anyway. It isn't a loop."
function dummyObjectTree(obj, subjects, rootsHash, force) {
// dump('dummyObjectTree('+obj+'...)\n');
if (obj.termType == 'bnode' && (subjects[sz.toStr(obj)] &&
(force || (rootsHash[obj.toNT()] == undefined )))) {// and there are statements
if (doneBnodesNT[obj.toNT()]) { // Ah-ha! a loop
throw new Error("Serializer: Should be no loops "+obj);
}
doneBnodesNT[obj.toNT()] = true;
return dummyPropertyTree(obj, subjects, rootsHash);
}
return dummyTermToN3(obj, subjects, rootsHash);
}
// Scan for bnodes nested inside lists too
function dummyTermToN3(expr, subjects, rootsHash) {
if (expr.termType == 'bnode') doneBnodesNT[expr.toNT()] = true;
tabulator.log.debug('serialize: seen '+expr);
if (expr.termType == 'collection') {
for (i=0; i<expr.elements.length; i++) {
if (expr.elements[i].termType == 'bnode')
dummyObjectTree(expr.elements[i], subjects, rootsHash);
}
return;
}
}
// The tree for a subject
function dummySubjectTree(subject, subjects, rootsHash) {
// dump('dummySubjectTree('+subject+'...)\n');
if (subject.termType == 'bnode' && !incoming[subject])
return dummyObjectTree(subject, subjects, rootsHash, true); // Anonymous bnode subject
dummyTermToN3(subject, subjects, rootsHash);
dummyPropertyTree(subject, subjects, rootsHash);
}
*/
// Now do the scan using existing roots
tabulator.log.debug('serialize.js Dummy serialize to check for missing nodes')
var rootsHash = {};
for(var i = 0; i < roots.length; i++) rootsHash[roots[i].toNT()] = true;
/*
for (var i=0; i<roots.length; i++) {
var root = roots[i];
dummySubjectTree(root, subjects, rootsHash);
}
// dump('Looking for mising bnodes...\n')
// Now in new roots for anythig not acccounted for
// Now we check for any bndoes which have not been covered.
// Such bnodes must be in isolated rings of pure bnodes.
// They each have incoming link of 1.
tabulator.log.debug('serialize.js Looking for connected bnode loops\n')
for (;;) {
var bnt;
var found = null;
for (bnt in allBnodes) { // @@ Note: not repeatable. No canonicalisation
if (doneBnodesNT[bnt]) continue;
found = bnt; // Ah-ha! not covered
break;
}
if (found == null) break; // All done - no bnodes left out/
// dump('Found isolated bnode:'+found+'\n');
doneBnodesNT[bnt] = true;
var root = this.store.fromNT(found);
roots.push(root); // Add a new root
rootsHash[found] = true;
tabulator.log.debug('isolated bnode:'+found+', subjects[found]:'+subjects[found]+'\n');
if (subjects[found] == undefined) {
for (var i=0; i<sts.length; i++) {
// dump('\t'+sts[i]+'\n');
}
throw new Error("Isolated node should be a subject" +found);
}
dummySubjectTree(root, subjects, rootsHash); // trace out the ring
}
// dump('Done bnode adjustments.\n')
*/
return {
'roots': roots,
'subjects': subjects,
'rootsHash': rootsHash,
'incoming': incoming
};
}
////////////////////////////////////////////////////////
__Serializer.prototype.toN3 = function (f) {
return this.statementsToN3(f.statements);
}
__Serializer.prototype._notQNameChars = "\t\r\n !\"#$%&'()*,+/;<=>?@[\\]^`{|}~";
__Serializer.prototype._notNameChars = (__Serializer.prototype._notQNameChars + ":");
__Serializer.prototype._NCNameRegExp = (function() {
// escape characters that are unsafe inside RegExp character set
var reSafeChars = __Serializer.prototype._notNameChars.replace(/[-\]\\]/g, '\\$&');
return new RegExp('[^0-9\\-.' + reSafeChars + '][^' + reSafeChars + ']*$');
})();
__Serializer.prototype.statementsToN3 = function (sts) {
var indent = 4;
var width = 80;
var sz = this;
var namespaceCounts = []; // which have been used
var predMap = {
'http://www.w3.org/2002/07/owl#sameAs': '=',
'http://www.w3.org/2000/10/swap/log#implies': '=>',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': 'a'
}
////////////////////////// Arrange the bits of text
var spaces = function (n) {
var s = '';
for(var i = 0; i < n; i++) s += ' ';
return s
}
var treeToLine = function (tree) {
var str = '';
for(var i = 0; i < tree.length; i++) {
var branch = tree[i];
var s2 = (typeof branch == 'string') ? branch : treeToLine(branch);
if(i != 0 && s2 != ',' && s2 != ';' && s2 != '.') str += ' ';
str += s2;
}
return str;
}
// Convert a nested tree of lists and strings to a string
var treeToString = function (tree, level) {
var str = '';
var lastLength = 100000;
if(!level) level = 0;
for(var i = 0; i < tree.length; i++) {
var branch = tree[i];
if(typeof branch != 'string') {
var substr = treeToString(branch, level + 1);
if(substr.length < 10 * (width - indent * level)
&& substr.indexOf('"""') < 0) {
// Don't mess up multiline strings
var line = treeToLine(branch);
if(line.length < (width - indent * level)) {
branch = ' ' + line; // @@ Hack: treat as string below
substr = ''
}
}
if(substr) lastLength = 10000;
str += substr;
}
if(typeof branch == 'string') {
if(branch.length == '1' && str.slice(-1) == '\n') {
if(",.;".indexOf(branch) >= 0) {
str = str.slice(0, -1) + branch + '\n'; // slip punct'n on end
lastLength += 1;
continue;
} else if("])}".indexOf(branch) >= 0) {
str = str.slice(0, -1) + ' ' + branch + '\n';
lastLength += 2;
continue;
}
}
if(lastLength < (indent * level + 4)) { // continue
str = str.slice(0, -1) + ' ' + branch + '\n';
lastLength += branch.length + 1;
} else {
var line = spaces(indent * level) + branch;
str += line + '\n';
lastLength = line.length;
}
} else { // not string
}
}
return str;
};
////////////////////////////////////////////// Structure for N3
// Convert a set of statements into a nested tree of lists and strings
function statementListToTree(statements) {
// print('Statement tree for '+statements.length);
var res = [];
var stats = sz.rootSubjects(statements);
var roots = stats.roots;
var results = []
for(var i = 0; i < roots.length; i++) {
var root = roots[i];
results.push(subjectTree(root, stats))
}
return results;
}
// The tree for a subject
function subjectTree(subject, stats) {
if(subject.termType == 'bnode' && !stats.incoming[subject])
return objectTree(subject, stats, true).concat(["."]); // Anonymous bnode subject
return [termToN3(subject, stats)].concat([propertyTree(subject, stats)]).concat(["."]);
}
// The property tree for a single subject or anonymous node
function propertyTree(subject, stats) {
// print('Proprty tree for '+subject);
var results = []
var lastPred = null;
var sts = stats.subjects[sz.toStr(subject)]; // relevant statements
if(typeof sts == 'undefined') {
throw('Cant find statements for ' + subject);
}
sts.sort();
var objects = [];
for(var i = 0; i < sts.length; i++) {
var st = sts[i];
if(st.predicate.uri == lastPred) {
objects.push(',');
} else {
if(lastPred) {
results = results.concat([objects]).concat([';']);
objects = [];
}
results.push(predMap[st.predicate.uri] ?
predMap[st.predicate.uri] :
termToN3(st.predicate, stats));
}
lastPred = st.predicate.uri;
objects.push(objectTree(st.object, stats));
}
results = results.concat([objects]);
return results;
}
function objectTree(obj, stats, force) {
if(obj.termType == 'bnode'
&& stats.subjects[sz.toStr(obj)]
// and there are statements
&& (force || stats.rootsHash[obj.toNT()] == undefined)) // and not a root
return ['['].concat(propertyTree(obj, stats)).concat([']']);
return termToN3(obj, stats);
}
function termToN3(expr, stats) {
switch(expr.termType) {
case 'bnode':
case 'variable':
return expr.toNT();
case 'literal':
var str = stringToN3(expr.value);
if(expr.lang) str += '@' + expr.lang;
if(expr.datatype) str += '^^' + termToN3(expr.datatype, stats);
return str;
case 'symbol':
return symbolToN3(expr.uri);
case 'formula':
var res = ['{'];
res = res.concat(statementListToTree(expr.statements));
return res.concat(['}']);
case 'collection':
var res = ['('];
for(i = 0; i < expr.elements.length; i++) {
res.push([objectTree(expr.elements[i], stats)]);
}
res.push(')');
return res;
default:
throw new Error("Internal: termToN3 cannot handle " + expr + " of termType+" + expr.termType);
return '' + expr;
}
}
////////////////////////////////////////////// Atomic Terms
// Deal with term level things and nesting with no bnode structure
function symbolToN3(uri) { // c.f. symbolString() in notation3.py
var j = uri.indexOf('#');
if(j < 0 && sz.flags.indexOf('/') < 0) {
j = uri.lastIndexOf('/');
}
if(j >= 0 && sz.flags.indexOf('p') < 0) { // Can split at namespace
var canSplit = true;
for(var k = j + 1; k < uri.length; k++) {
if(__Serializer.prototype._notNameChars.indexOf(uri[k]) >= 0) {
canSplit = false;
break;
}
}
if(canSplit) {
var localid = uri.slice(j + 1);
var namesp = uri.slice(0, j + 1);
if(sz.defaultNamespace
&& sz.defaultNamespace == namesp
&& sz.flags.indexOf('d') < 0) { // d -> suppress default
if(sz.flags.indexOf('k') >= 0
&& sz.keyords.indexOf(localid) < 0)
return localid;
return ':' + localid;
}
var prefix = sz.prefixes[namesp];
if(prefix) {
namespaceCounts[namesp] = true;
return prefix + ':' + localid;
}
if(uri.slice(0, j) == sz.base)
return '<#' + localid + '>';
// Fall though if can't do qname
}
}
if(sz.flags.indexOf('r') < 0 && sz.base)
uri = $rdf.Util.uri.refTo(sz.base, uri);
else if(sz.flags.indexOf('u') >= 0)
uri = backslashUify(uri);
else uri = hexify(uri);
return '<' + uri + '>';
}
function prefixDirectives() {
var str = '';
if(sz.defaultNamespace)
str += '@prefix : <' + sz.defaultNamespace + '>.\n';
for(var ns in namespaceCounts) {
str += '@prefix ' + sz.prefixes[ns] + ': <' + ns + '>.\n';
}
return str + '\n';
}
// stringToN3: String escaping for N3
//
var forbidden1 = new RegExp(/[\\"\b\f\r\v\t\n\u0080-\uffff]/gm);
var forbidden3 = new RegExp(/[\\"\b\f\r\v\u0080-\uffff]/gm);
function stringToN3(str, flags) {
if(!flags) flags = "e";
var res = '', i = 0, j = 0;
var delim;
var forbidden;
if(str.length > 20 // Long enough to make sense
&& str.slice(-1) != '"' // corner case'
&& flags.indexOf('n') < 0 // Force single line
&& (str.indexOf('\n') > 0 || str.indexOf('"') > 0)) {
delim = '"""';
forbidden = forbidden3;
} else {
delim = '"';
forbidden = forbidden1;
}
for(i = 0; i < str.length;) {
forbidden.lastIndex = 0;
var m = forbidden.exec(str.slice(i));
if(m == null) break;
j = i + forbidden.lastIndex - 1;
res += str.slice(i, j);
var ch = str[j];
if(ch == '"' && delim == '"""' && str.slice(j, j + 3) != '"""') {
res += ch;
} else {
var k = '\b\f\r\t\v\n\\"'.indexOf(ch); // No escaping of bell (7)?
if(k >= 0) {
res += "\\" + 'bfrtvn\\"' [k];
} else {
if(flags.indexOf('e') >= 0) {
res += '\\u' + ('000' + ch.charCodeAt(0).toString(16).toLowerCase()).slice(-4)
} else { // no 'e' flag
res += ch;
}
}
}
i = j + 1;
}
return delim + res + str.slice(i) + delim
}
// Body of toN3:
var tree = statementListToTree(sts);
return prefixDirectives() + treeToString(tree, -1);
}
// String ecaping utilities
function hexify(str) { // also used in parser
// var res = '';
// for (var i=0; i<str.length; i++) {
// k = str.charCodeAt(i);
// if (k>126 || k<33)
// res += '%' + ('0'+n.toString(16)).slice(-2); // convert to upper?
// else
// res += str[i];
// }
// return res;
return encodeURI(str);
}
function backslashUify(str) {
var res = '', k;
for(var i = 0; i < str.length; i++) {
k = str.charCodeAt(i);
if(k > 65535)
res += '\\U' + ('00000000' + n.toString(16)).slice(-8); // convert to upper?
else if(k > 126)
res += '\\u' + ('0000' + n.toString(16)).slice(-4);
else
res += str[i];
}
return res;
}
//////////////////////////////////////////////// XML serialization
__Serializer.prototype.statementsToXML = function (sts) {
var indent = 4;
var width = 80;
var sz = this;
var namespaceCounts = []; // which have been used
namespaceCounts['http://www.w3.org/1999/02/22-rdf-syntax-ns#'] = true;
////////////////////////// Arrange the bits of XML text
var spaces = function (n) {
var s = '';
for(var i = 0; i < n; i++) s += ' ';
return s
}
var XMLtreeToLine = function (tree) {
var str = '';
for(var i = 0; i < tree.length; i++) {
var branch = tree[i];
var s2 = (typeof branch == 'string') ? branch : XMLtreeToLine(branch);
str += s2;
}
return str;
}
// Convert a nested tree of lists and strings to a string
var XMLtreeToString = function (tree, level) {
var str = '';
var lastLength = 100000;
if(!level) level = 0;
for(var i = 0; i < tree.length; i++) {
var branch = tree[i];
if(typeof branch != 'string') {
var substr = XMLtreeToString(branch, level + 1);
if(substr.length < 10 * (width - indent * level)
&& substr.indexOf('"""') < 0) {
// Don't mess up multiline strings
var line = XMLtreeToLine(branch);
if(line.length < (width - indent * level)) {
branch = ' ' + line; // @@ Hack: treat as string below
substr = ''
}
}
if(substr) lastLength = 10000;
str += substr;
}
if(typeof branch == 'string') {
if(lastLength < (indent * level + 4)) { // continue
str = str.slice(0, -1) + ' ' + branch + '\n';
lastLength += branch.length + 1;
} else {
var line = spaces(indent * level) + branch;
str += line + '\n';
lastLength = line.length;
}
} else { // not string
}
}
return str;
};
function statementListToXMLTree(statements) {
sz.suggestPrefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
var stats = sz.rootSubjects(statements);
var roots = stats.roots;
var results = [], root;
for(var i = 0; i < roots.length; i++) {
root = roots[i];
results.push(subjectXMLTree(root, stats))
}
return results;
}
function escapeForXML(str) {
if(typeof str == 'undefined') return '@@@undefined@@@@';
return str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function relURI(term) {
return escapeForXML((sz.base) ? $rdf.Util.uri.refTo(this.base, term.uri) : term.uri);
}
// The tree for a subject
function subjectXMLTree(subject, stats) {
const liPrefix = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_';
var results = [];
var type = null, t, st;
var sts = stats.subjects[sz.toStr(subject)]; // relevant statements
// Sort only on the predicate, leave the order at object
// level undisturbed. This leaves multilingual content in
// the order of entry (for partner literals), which helps
// readability.
//
// For the predicate sort, we attempt to split the uri
// as a hint to the sequence, as sequenced items seems
// to be of the form http://example.com#_1, http://example.com#_2,
// et cetera. Probably not the most optimal of fixes, but
// it does work.
sts.sort(function (a, b) {
var aa = a.predicate.uri.split('#_');
var bb = a.predicate.uri.split('#_');
if(aa[0] > bb[0]) {
return 1;
} else if(aa[0] < bb[0]) {
return -1;
} else if("undefined" !== typeof aa[1] && "undefined" !== typeof bb[1]) {
if(parseInt(aa[1], 10) > parseInt(bb[1], 10)) {
return 1;
} else if(parseInt(aa[1], 10) < parseInt(bb[1], 10)) {
return -1;
}
}
return 0;
});
for(var i = 0; i < sts.length; i++) {
st = sts[i];
if(st.predicate.uri == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && !type && st.object.termType == "symbol") {
// look for a type
type = st.object;
} else {
// see whether predicate can be replaced with "li"
if(st.predicate.uri.substr(0, liPrefix.length) == liPrefix) {
var number = st.predicate.uri.substr(liPrefix.length);
// make sure these are actually numeric list items
var intNumber = parseInt(number);
if(number == intNumber.toString()) {
// was numeric; don't need to worry about ordering since we've already
// sorted the statements
st.predicate = $rdf.Symbol('http://www.w3.org/1999/02/22-rdf-syntax-ns#li');
}
}
t = qname(st.predicate);
switch(st.object.termType) {
case 'bnode':
if(sz.incoming[st.object].length == 1) {
results = results.concat(['<' + t + '>',
subjectXMLTree(st.object, stats),
'</' + t + '>']);
} else {
results = results.concat(['<' + t + ' rdf:nodeID="'
+ st.object.toNT().slice(2) + '"/>']);
}
break;
case 'symbol':
results = results.concat(['<' + t + ' rdf:resource="'
+ relURI(st.object) + '"/>']);
break;
case 'literal':
results = results.concat(['<' + t
+ (st.object.dt ? ' rdf:datatype="' + escapeForXML(st.object.dt.uri) + '"' : '')
+ (st.object.lang ? ' xml:lang="' + st.object.lang + '"' : '')
+ '>' + escapeForXML(st.object.value)
+ '</' + t + '>']);
break;
case 'collection':
results = results.concat(['<' + t + ' rdf:parseType="Collection">',
collectionXMLTree(st.object, stats),
'</' + t + '>']);
break;
default:
throw new Error("Can't serialize object of type " + st.object.termType + " into XML");
} // switch
}
}
var tag = type ? qname(type) : 'rdf:Description';
var attrs = '';
if(subject.termType == 'bnode') {
if(!sz.incoming[subject] || sz.incoming[subject].length != 1) { // not an anonymous bnode
attrs = ' rdf:nodeID="' + subject.toNT().slice(2) + '"';
}
} else {
attrs = ' rdf:about="' + relURI(subject) + '"';
}
return ['<' + tag + attrs + '>'].concat([results]).concat(["</" + tag + ">"]);
}
function collectionXMLTree(subject, stats) {
var res = []
for(var i = 0; i < subject.elements.length; i++) {
res.push(subjectXMLTree(subject.elements[i], stats));
}
return res;
}
// The property tree for a single subject or anonymos node
function propertyXMLTree(subject, stats) {
var results = []
var sts = stats.subjects[sz.toStr(subject)]; // relevant statements
if(sts == undefined) return results; // No relevant statements
sts.sort();
for(var i = 0; i < sts.length; i++) {
var st = sts[i];
switch(st.object.termType) {
case 'bnode':
if(stats.rootsHash[st.object.toNT()]) { // This bnode has been done as a root -- no content here @@ what bout first time
results = results.concat(['<' + qname(st.predicate) + ' rdf:nodeID="' + st.object.toNT().slice(2) + '">',
'</' + qname(st.predicate) + '>']);
} else {
results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Resource">',
propertyXMLTree(st.object, stats),
'</' + qname(st.predicate) + '>']);
}
break;
case 'symbol':
results = results.concat(['<' + qname(st.predicate) + ' rdf:resource="'
+ relURI(st.object) + '"/>']);
break;
case 'literal':
results = results.concat(['<' + qname(st.predicate)
+ (st.object.datatype ? ' rdf:datatype="' + escapeForXML(st.object.datatype.uri) + '"' : '')
+ (st.object.lang ? ' xml:lang="' + st.object.lang + '"' : '')
+ '>' + escapeForXML(st.object.value)
+ '</' + qname(st.predicate) + '>']);
break;
case 'collection':
results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Collection">',
collectionXMLTree(st.object, stats),
'</' + qname(st.predicate) + '>']);
break;
default:
throw new Error("Can't serialize object of type " + st.object.termType + " into XML");
} // switch
}
return results;
}
function qname(term) {
var uri = term.uri;
var j = uri.search(sz._NCNameRegExp);
if(j < 0) throw("Cannot make qname out of <" + uri + ">")
var localid = uri.substr(j);
var namesp = uri.substr(0, j);
if(sz.defaultNamespace
&& sz.defaultNamespace == namesp
&& sz.flags.indexOf('d') < 0) { // d -> suppress default
return localid;
}
var prefix = sz.prefixes[namesp];
if(!prefix) prefix = sz.makeUpPrefix(namesp);
namespaceCounts[namesp] = true;
return prefix + ':' + localid;
// throw ('No prefix for namespace "'+namesp +'" for XML qname for '+uri+', namespaces: '+sz.prefixes+' sz='+sz);
}
// Body of toXML:
var tree = statementListToXMLTree(sts);
var str = '<rdf:RDF';
if(sz.defaultNamespace)
str += ' xmlns="' + escapeForXML(sz.defaultNamespace) + '"';
for(var ns in namespaceCounts) {
str += '\n xmlns:' + sz.prefixes[ns] + '="' + escapeForXML(ns) + '"';
}
str += '>';
var tree2 = [str, tree, '</rdf:RDF>']; //@@ namespace declrations
return XMLtreeToString(tree2, -1);
} // End @@ body
return Serializer;
}();

View file

@ -1,346 +0,0 @@
// These are the classes corresponding to the RDF and N3 data models
//
// Designed to look like rdflib and cwm designs.
//
// Issues: Should the names start with RDF to make them
// unique as program-wide symbols?
//
// W3C open source licence 2005.
//
// Symbol
$rdf.Empty = function () {
return this;
};
$rdf.Empty.prototype.termType = 'empty';
$rdf.Empty.prototype.toString = function () {
return "()"
};
$rdf.Empty.prototype.toNT = $rdf.Empty.prototype.toString;
$rdf.Symbol = function (uri) {
this.uri = uri;
this.value = uri; // -- why? -tim
return this;
}
$rdf.Symbol.prototype.termType = 'symbol';
$rdf.Symbol.prototype.toString = function () {
return("<" + this.uri + ">");
};
$rdf.Symbol.prototype.toNT = $rdf.Symbol.prototype.toString;
// Some precalculated symbols
$rdf.Symbol.prototype.XSDboolean = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#boolean');
$rdf.Symbol.prototype.XSDdecimal = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#decimal');
$rdf.Symbol.prototype.XSDfloat = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#float');
$rdf.Symbol.prototype.XSDinteger = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#integer');
$rdf.Symbol.prototype.XSDdateTime = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#dateTime');
$rdf.Symbol.prototype.integer = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#integer'); // Used?
// Blank Node
if(typeof $rdf.NextId != 'undefined') {
$rdf.log.error('Attempt to re-zero existing blank node id counter at ' + $rdf.NextId);
} else {
$rdf.NextId = 0; // Global genid
}
$rdf.NTAnonymousNodePrefix = "_:n";
$rdf.BlankNode = function (id) {
/*if (id)
this.id = id;
else*/
this.id = $rdf.NextId++;
this.value = id ? id : this.id.toString();
return this
};
$rdf.BlankNode.prototype.termType = 'bnode';
$rdf.BlankNode.prototype.toNT = function () {
return $rdf.NTAnonymousNodePrefix + this.id
};
$rdf.BlankNode.prototype.toString = $rdf.BlankNode.prototype.toNT;
// Literal
$rdf.Literal = function (value, lang, datatype) {
this.value = value
if(lang == "" || lang == null) this.lang = undefined;
else this.lang = lang; // string
if(datatype == null) this.datatype = undefined;
else this.datatype = datatype; // term
return this;
}
$rdf.Literal.prototype.termType = 'literal'
$rdf.Literal.prototype.toString = function () {
return '' + this.value;
};
$rdf.Literal.prototype.toNT = function () {
var str = this.value
if(typeof str != 'string') {
if(typeof str == 'number') return '' + str;
throw Error("Value of RDF literal is not string: " + str)
}
str = str.replace(/\\/g, '\\\\'); // escape backslashes
str = str.replace(/\"/g, '\\"'); // escape quotes
str = str.replace(/\n/g, '\\n'); // escape newlines
str = '"' + str + '"' //';
if(this.datatype) {
str = str + '^^' + this.datatype.toNT()
}
if(this.lang) {
str = str + "@" + this.lang;
}
return str;
};
$rdf.Collection = function () {
this.id = $rdf.NextId++; // Why need an id? For hashstring.
this.elements = [];
this.closed = false;
};
$rdf.Collection.prototype.termType = 'collection';
$rdf.Collection.prototype.toNT = function () {
return $rdf.NTAnonymousNodePrefix + this.id
};
$rdf.Collection.prototype.toString = function () {
var str = '(';
for(var i = 0; i < this.elements.length; i++)
str += this.elements[i] + ' ';
return str + ')';
};
$rdf.Collection.prototype.append = function (el) {
this.elements.push(el)
}
$rdf.Collection.prototype.unshift = function (el) {
this.elements.unshift(el);
}
$rdf.Collection.prototype.shift = function () {
return this.elements.shift();
}
$rdf.Collection.prototype.close = function () {
this.closed = true
}
// Convert Javascript representation to RDF term object
//
$rdf.term = function (val) {
if(typeof val == 'object')
if(val instanceof Date) {
var d2 = function (x) {
return('' + (100 + x)).slice(1, 3)
}; // format as just two digits
return new $rdf.Literal('' + val.getUTCFullYear() + '-' + d2(val.getUTCMonth() + 1)
+ '-' + d2(val.getUTCDate()) + 'T' + d2(val.getUTCHours()) + ':'
+ d2(val.getUTCMinutes()) + ':' + d2(val.getUTCSeconds()) + 'Z',
undefined,
$rdf.Symbol.prototype.XSDdateTime);
} else if(val instanceof Array) {
var x = new $rdf.Collection();
for(var i = 0; i < val.length; i++)
x.append($rdf.term(val[i]));
return x;
} else
return val;
if(typeof val == 'string')
return new $rdf.Literal(val);
if(typeof val == 'number') {
var dt;
if(('' + val).indexOf('e') >= 0) dt = $rdf.Symbol.prototype.XSDfloat;
else if(('' + val).indexOf('.') >= 0) dt = $rdf.Symbol.prototype.XSDdecimal;
else dt = $rdf.Symbol.prototype.XSDinteger;
return new $rdf.Literal(val, undefined, dt);
}
if(typeof val == 'boolean')
return new $rdf.Literal(val ? "1" : "0", undefined, $rdf.Symbol.prototype.XSDboolean);
if(typeof val == 'undefined')
return undefined;
throw("Can't make term from " + val + " of type " + typeof val);
}
// Statement
//
// This is a triple with an optional reason.
//
// The reason can point to provenece or inference
//
$rdf.Statement = function (subject, predicate, object, why) {
this.subject = $rdf.term(subject)
this.predicate = $rdf.term(predicate)
this.object = $rdf.term(object)
if(typeof why != 'undefined') {
this.why = why;
}
return this;
}
$rdf.st = function (subject, predicate, object, why) {
return new $rdf.Statement(subject, predicate, object, why);
};
$rdf.Statement.prototype.toNT = function () {
return (this.subject.toNT() + " " + this.predicate.toNT() + " " + this.object.toNT() + " .");
};
$rdf.Statement.prototype.toString = $rdf.Statement.prototype.toNT;
// Formula
//
// Set of statements.
$rdf.Formula = function () {
this.statements = []
this.constraints = []
this.initBindings = []
this.optional = []
return this;
};
$rdf.Formula.prototype.termType = 'formula';
$rdf.Formula.prototype.toNT = function () {
return "{" + this.statements.join('\n') + "}"
};
$rdf.Formula.prototype.toString = $rdf.Formula.prototype.toNT;
$rdf.Formula.prototype.add = function (subj, pred, obj, why) {
this.statements.push(new $rdf.Statement(subj, pred, obj, why))
}
// Convenience methods on a formula allow the creation of new RDF terms:
$rdf.Formula.prototype.sym = function (uri, name) {
if(name != null) {
throw new Error("This feature (kb.sym with 2 args) is removed. Do not assume prefix mappings.");
if(!$rdf.ns[uri]) throw 'The prefix "' + uri + '" is not set in the API';
uri = $rdf.ns[uri] + name
}
return new $rdf.Symbol(uri)
}
$rdf.sym = function (uri) {
return new $rdf.Symbol(uri);
};
$rdf.Formula.prototype.literal = function (val, lang, dt) {
return new $rdf.Literal(val.toString(), lang, dt)
}
$rdf.lit = $rdf.Formula.prototype.literal;
$rdf.Formula.prototype.bnode = function (id) {
return new $rdf.BlankNode(id)
}
$rdf.Formula.prototype.formula = function () {
return new $rdf.Formula()
}
$rdf.Formula.prototype.collection = function () { // obsolete
return new $rdf.Collection()
}
$rdf.Formula.prototype.list = function (values) {
var li = new $rdf.Collection();
if(values) {
for(var i = 0; i < values.length; i++) {
li.append(values[i]);
}
}
return li;
}
/* Variable
**
** Variables are placeholders used in patterns to be matched.
** In cwm they are symbols which are the formula's list of quantified variables.
** In sparl they are not visibily URIs. Here we compromise, by having
** a common special base URI for variables. Their names are uris,
** but the ? nottaion has an implicit base uri of 'varid:'
*/
$rdf.Variable = function (rel) {
this.base = "varid:"; // We deem variabe x to be the symbol varid:x
this.uri = $rdf.Util.uri.join(rel, this.base);
return this;
}
$rdf.Variable.prototype.termType = 'variable';
$rdf.Variable.prototype.toNT = function () {
if(this.uri.slice(0, this.base.length) == this.base) {
return '?' + this.uri.slice(this.base.length);
} // @@ poor man's refTo
return '?' + this.uri;
};
$rdf.Variable.prototype.toString = $rdf.Variable.prototype.toNT;
$rdf.Variable.prototype.classOrder = 7;
$rdf.variable = $rdf.Formula.prototype.variable = function (name) {
return new $rdf.Variable(name);
};
$rdf.Variable.prototype.hashString = $rdf.Variable.prototype.toNT;
// The namespace function generator
$rdf.Namespace = function (nsuri) {
return function (ln) {
return new $rdf.Symbol(nsuri + (ln === undefined ? '' : ln))
}
}
$rdf.Formula.prototype.ns = function (nsuri) {
return function (ln) {
return new $rdf.Symbol(nsuri + (ln === undefined ? '' : ln))
}
}
// Parse a single token
//
// The bnode bit should not be used on program-external values; designed
// for internal work such as storing a bnode id in an HTML attribute.
// This will only parse the strings generated by the vaious toNT() methods.
$rdf.Formula.prototype.fromNT = function (str) {
var len = str.length
var ch = str.slice(0, 1)
if(ch == '<') return $rdf.sym(str.slice(1, len - 1))
if(ch == '"') {
var lang = undefined;
var dt = undefined;
var k = str.lastIndexOf('"');
if(k < len - 1) {
if(str[k + 1] == '@') lang = str.slice(k + 2, len);
else if(str.slice(k + 1, k + 3) == '^^') dt = $rdf.fromNT(str.slice(k + 3, len));
else throw new Error("Can't convert string from NT: " + str);
}
var str = (str.slice(1, k));
str = str.replace(/\\"/g, '"'); // unescape quotes '
str = str.replace(/\\n/g, '\n'); // unescape newlines
str = str.replace(/\\\\/g, '\\'); // unescape backslashes
return $rdf.lit(str, lang, dt);
}
if(ch == '_') {
var x = new $rdf.BlankNode();
x.id = parseInt(str.slice(3));
$rdf.NextId--
return x
}
if(ch == '?') {
var x = new $rdf.Variable(str.slice(1));
return x;
}
throw new Error("Can't convert from NT: " + str);
}
$rdf.fromNT = $rdf.Formula.prototype.fromNT; // Not for inexpert user
// Convenience - and more conventional name:
$rdf.graph = function () {
return new $rdf.IndexedFormula();
};
// ends

View file

@ -1,149 +0,0 @@
// Implementing URI-specific functions
//
// See RFC 2386
//
// This is or was http://www.w3.org/2005/10/ajaw/uri.js
// 2005 W3C open source licence
//
//
// Take a URI given in relative or absolute form and a base
// URI, and return an absolute URI
//
// See also http://www.w3.org/2000/10/swap/uripath.py
//
if(typeof $rdf.Util.uri == "undefined") {
$rdf.Util.uri = {};
};
$rdf.Util.uri.join = function (given, base) {
// if (typeof $rdf.log.debug != 'undefined') $rdf.log.debug(" URI given="+given+" base="+base)
var baseHash = base.indexOf('#')
if(baseHash > 0) base = base.slice(0, baseHash)
if(given.length == 0) return base // before chopping its filename off
if(given.indexOf('#') == 0) return base + given
var colon = given.indexOf(':')
if(colon >= 0) return given // Absolute URI form overrides base URI
var baseColon = base.indexOf(':')
if(base == "") return given;
if(baseColon < 0) {
alert("Invalid base: " + base + ' in join with ' + given);
return given
}
var baseScheme = base.slice(0, baseColon + 1) // eg http:
if(given.indexOf("//") == 0) // Starts with //
return baseScheme + given;
if(base.indexOf('//', baseColon) == baseColon + 1) { // Any hostpart?
var baseSingle = base.indexOf("/", baseColon + 3)
if(baseSingle < 0) {
if(base.length - baseColon - 3 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
} else {
var baseSingle = base.indexOf("/", baseColon + 1)
if(baseSingle < 0) {
if(base.length - baseColon - 1 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
}
if(given.indexOf('/') == 0) // starts with / but not //
return base.slice(0, baseSingle) + given
var path = base.slice(baseSingle)
var lastSlash = path.lastIndexOf("/")
if(lastSlash < 0) return baseScheme + given
if((lastSlash >= 0)
&& (lastSlash < (path.length - 1)))
path = path.slice(0, lastSlash + 1) // Chop trailing filename from base
path = path + given
while(path.match(/[^\/]*\/\.\.\//)) // must apply to result of prev
path = path.replace(/[^\/]*\/\.\.\//, '') // ECMAscript spec 7.8.5
path = path.replace(/\.\//g, '') // spec vague on escaping
path = path.replace(/\/\.$/, '/')
return base.slice(0, baseSingle) + path
}
if(typeof tabulator != 'undefined' && tabulator.isExtension) {
$rdf.Util.uri.join2 = function (given, base) {
var tIOService = Components.classes['@mozilla.org/network/io-service;1']
.getService(Components.interfaces.nsIIOService);
var baseURI = tIOService.newURI(base, null, null);
return tIOService.newURI(baseURI.resolve(given), null, null).spec;
}
} else
$rdf.Util.uri.join2 = $rdf.Util.uri.join;
// refTo: Make a URI relative to a given base
//
// based on code in http://www.w3.org/2000/10/swap/uripath.py
//
$rdf.Util.uri.commonHost = new RegExp("^[-_a-zA-Z0-9.]+:(//[^/]*)?/[^/]*$");
$rdf.Util.uri.hostpart = function (u) {
var m = /[^\/]*\/\/([^\/]*)\//.exec(u);
return m ? m[1] : ''
};
$rdf.Util.uri.refTo = function (base, uri) {
if(!base) return uri;
if(base == uri) return "";
var i = 0; // How much are they identical?
while(i < uri.length && i < base.length)
if(uri[i] == base[i]) i++;
else break;
if(base.slice(0, i).match($rdf.Util.uri.commonHost)) {
var k = uri.indexOf('//');
if(k < 0) k = -2; // no host
var l = uri.indexOf('/', k + 2); // First *single* slash
if(uri.slice(l + 1, l + 2) != '/'
&& base.slice(l + 1, l + 2) != '/'
&& uri.slice(0, l) == base.slice(0, l))
// common path to single slash
return uri.slice(l); // but no other common path segments
}
// fragment of base?
if(uri.slice(i, i + 1) == '#' && base.length == i) return uri.slice(i);
while(i > 0 && uri[i - 1] != '/') i--;
if(i < 3) return uri; // No way
if((base.indexOf('//', i - 2) > 0)
|| uri.indexOf('//', i - 2) > 0)
return uri; // an unshared '//'
if(base.indexOf(':', i) > 0) return uri; // unshared ':'
var n = 0;
for(var j = i; j < base.length; j++) if(base[j] == '/') n++;
if(n == 0 && i < uri.length && uri[i] == '#') return './' + uri.slice(i);
if(n == 0 && i == uri.length) return './';
var str = '';
for(var j = 0; j < n; j++) str += '../';
return str + uri.slice(i);
}
/** returns URI without the frag **/
$rdf.Util.uri.docpart = function (uri) {
var i = uri.indexOf("#")
if(i < 0) return uri
return uri.slice(0, i)
}
/** The document in which something a thing defined **/
$rdf.Util.uri.document = function (x) {
return $rdf.sym($rdf.Util.uri.docpart(x.uri));
}
/** return the protocol of a uri **/
/** return null if there isn't one **/
$rdf.Util.uri.protocol = function (uri) {
var index = uri.indexOf(':');
if(index >= 0) return uri.slice(0, index);
else return null;
} //protocol
//ends

View file

@ -1,274 +0,0 @@
const TLDS = {
"ac":true,
"ad":true,
"ae":true,
"aero":true,
"af":true,
"ag":true,
"ai":true,
"al":true,
"am":true,
"an":true,
"ao":true,
"aq":true,
"ar":true,
"arpa":true,
"as":true,
"asia":true,
"at":true,
"au":true,
"aw":true,
"ax":true,
"az":true,
"ba":true,
"bb":true,
"bd":true,
"be":true,
"bf":true,
"bg":true,
"bh":true,
"bi":true,
"biz":true,
"bj":true,
"bm":true,
"bn":true,
"bo":true,
"br":true,
"bs":true,
"bt":true,
"bv":true,
"bw":true,
"by":true,
"bz":true,
"ca":true,
"cat":true,
"cc":true,
"cd":true,
"cf":true,
"cg":true,
"ch":true,
"ci":true,
"ck":true,
"cl":true,
"cm":true,
"cn":true,
"co":true,
"com":true,
"coop":true,
"cr":true,
"cu":true,
"cv":true,
"cx":true,
"cy":true,
"cz":true,
"de":true,
"dj":true,
"dk":true,
"dm":true,
"do":true,
"dz":true,
"ec":true,
"edu":true,
"ee":true,
"eg":true,
"er":true,
"es":true,
"et":true,
"eu":true,
"fi":true,
"fj":true,
"fk":true,
"fm":true,
"fo":true,
"fr":true,
"ga":true,
"gb":true,
"gd":true,
"ge":true,
"gf":true,
"gg":true,
"gh":true,
"gi":true,
"gl":true,
"gm":true,
"gn":true,
"gov":true,
"gp":true,
"gq":true,
"gr":true,
"gs":true,
"gt":true,
"gu":true,
"gw":true,
"gy":true,
"hk":true,
"hm":true,
"hn":true,
"hr":true,
"ht":true,
"hu":true,
"id":true,
"ie":true,
"il":true,
"im":true,
"in":true,
"info":true,
"int":true,
"io":true,
"iq":true,
"ir":true,
"is":true,
"it":true,
"je":true,
"jm":true,
"jo":true,
"jobs":true,
"jp":true,
"ke":true,
"kg":true,
"kh":true,
"ki":true,
"km":true,
"kn":true,
"kp":true,
"kr":true,
"kw":true,
"ky":true,
"kz":true,
"la":true,
"lb":true,
"lc":true,
"li":true,
"lk":true,
"lr":true,
"ls":true,
"lt":true,
"lu":true,
"lv":true,
"ly":true,
"ma":true,
"mc":true,
"md":true,
"me":true,
"mg":true,
"mh":true,
"mil":true,
"mk":true,
"ml":true,
"mm":true,
"mn":true,
"mo":true,
"mobi":true,
"mp":true,
"mq":true,
"mr":true,
"ms":true,
"mt":true,
"mu":true,
"museum":true,
"mv":true,
"mw":true,
"mx":true,
"my":true,
"mz":true,
"na":true,
"name":true,
"nc":true,
"ne":true,
"net":true,
"nf":true,
"ng":true,
"ni":true,
"nl":true,
"no":true,
"np":true,
"nr":true,
"nu":true,
"nz":true,
"om":true,
"org":true,
"pa":true,
"pe":true,
"pf":true,
"pg":true,
"ph":true,
"pk":true,
"pl":true,
"pm":true,
"pn":true,
"pr":true,
"pro":true,
"ps":true,
"pt":true,
"pw":true,
"py":true,
"qa":true,
"re":true,
"ro":true,
"rs":true,
"ru":true,
"rw":true,
"sa":true,
"sb":true,
"sc":true,
"sd":true,
"se":true,
"sg":true,
"sh":true,
"si":true,
"sj":true,
"sk":true,
"sl":true,
"sm":true,
"sn":true,
"so":true,
"sr":true,
"st":true,
"su":true,
"sv":true,
"sy":true,
"sz":true,
"tc":true,
"td":true,
"tel":true,
"tf":true,
"tg":true,
"th":true,
"tj":true,
"tk":true,
"tl":true,
"tm":true,
"tn":true,
"to":true,
"tp":true,
"tr":true,
"travel":true,
"tt":true,
"tv":true,
"tw":true,
"tz":true,
"ua":true,
"ug":true,
"uk":true,
"us":true,
"uy":true,
"uz":true,
"va":true,
"vc":true,
"ve":true,
"vg":true,
"vi":true,
"vn":true,
"vu":true,
"wf":true,
"ws":true,
"xxx":true,
"ye":true,
"yt":true,
"za":true,
"zm":true,
"zw":true
};
if (typeof process === 'object' && process + '' === '[object process]'){
module.exports = TLDS;
}

File diff suppressed because it is too large Load diff

View file

@ -1,221 +0,0 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2013 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
// Enumeration of types of translators
var TRANSLATOR_TYPES = {"import":1, "export":2, "web":4, "search":8};
// Properties required for every translator
var TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator",
"target", "priority", "lastUpdated"];
// Properties that are preserved if present
var TRANSLATOR_OPTIONAL_PROPERTIES = ["targetAll", "browserSupport", "minVersion", "maxVersion",
"inRepository", "configOptions", "displayOptions",
"hiddenPrefs", "itemType"];
// Properties that are passed from background to inject page in connector
var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.
concat(["targetAll", "browserSupport", "code", "runMode", "itemType", "inRepository"]);
/**
* @class Represents an individual translator
* @constructor
* @property {String} translatorID Unique GUID of the translator
* @property {Integer} translatorType Type of the translator (use bitwise & with TRANSLATOR_TYPES to read)
* @property {String} label Human-readable name of the translator
* @property {String} creator Author(s) of the translator
* @property {String} target Location that the translator processes
* @property {String} minVersion Minimum Zotero version
* @property {String} maxVersion Minimum Zotero version
* @property {Integer} priority Lower-priority translators will be selected first
* @property {String} browserSupport String indicating browser supported by the translator
* g = Gecko (Firefox)
* c = Google Chrome (WebKit & V8)
* s = Safari (WebKit & Nitro/Squirrelfish Extreme)
* i = Internet Explorer
* b = Bookmarklet
* v = Server
* @property {Object} configOptions Configuration options for import/export
* @property {Object} displayOptions Display options for export
* @property {Object} hiddenPrefs Hidden preferences configurable through about:config
* @property {Boolean} inRepository Whether the translator may be found in the repository
* @property {String} lastUpdated SQL-style date and time of translator's last update
* @property {Object} metadata - Metadata block as object
* @property {String} code The executable JavaScript for the translator
* @property {Boolean} cacheCode Whether to cache code for this session (non-connector only)
* @property {String} [path] File path corresponding to this translator (non-connector only)
* @property {String} [fileName] File name corresponding to this translator (non-connector only)
*/
Zotero.Translator = function(info) {
this.init(info);
}
/**
* Initializes a translator from a set of info, clearing code if it is set
*/
Zotero.Translator.prototype.init = function(info) {
// make sure we have all the properties
for (let property of TRANSLATOR_REQUIRED_PROPERTIES) {
if (info[property] === undefined) {
this.logError(new Error('Missing property "'+property+'" in translator metadata JSON object in ' + info.label));
break;
} else {
this[property] = info[property];
}
}
for (let property of TRANSLATOR_OPTIONAL_PROPERTIES) {
if(info[property] !== undefined) {
this[property] = info[property];
}
}
this.browserSupport = info["browserSupport"] ? info["browserSupport"] : "g";
var supported = !Zotero.isBookmarklet || this.browserSupport.includes("b") ||
/(?:^|; ?)bookmarklet-debug-mode=1(?:$|; ?)/.test(document.cookie);
if (supported) {
this.runMode = Zotero.Translator.RUN_MODE_IN_BROWSER;
} else {
this.runMode = Zotero.Translator.RUN_MODE_ZOTERO_STANDALONE;
}
if (this.translatorType & TRANSLATOR_TYPES["import"]) {
// compile import regexp to match only file extension
this.importRegexp = this.target ? new RegExp("\\."+this.target+"$", "i") : null;
} else if (this.hasOwnProperty("importRegexp")) {
delete this.importRegexp;
}
this.cacheCode = Zotero.isConnector || info.cacheCode;
if (this.translatorType & TRANSLATOR_TYPES["web"]) {
// compile web regexp
this.cacheCode |= !this.target;
this.webRegexp = {
root: this.target ? new RegExp(this.target, "i") : null,
all: this.targetAll ? new RegExp(this.targetAll, "i") : null
};
} else if (this.hasOwnProperty("webRegexp")) {
delete this.webRegexp;
}
if (info.path) {
this.path = info.path;
this.fileName = OS.Path.basename(info.path);
}
if (info.code && this.cacheCode) {
this.code = Zotero.Translator.replaceDeprecatedStatements(info.code);
} else if (this.hasOwnProperty("code")) {
delete this.code;
}
// Save a copy of the metadata block
delete info.path;
delete info.code;
this.metadata = info;
}
/**
* Load code for a translator
*/
Zotero.Translator.prototype.getCode = Zotero.Promise.method(function () {
if (this.code) return this.code;
if (Zotero.isConnector) {
return Zotero.Repo.getTranslatorCode(this.translatorID)
.then(function (args) {
var code = args[0];
var source = args[1];
if(!code) {
throw new Error("Code for " + this.label + " could not be retrieved");
}
// Cache any translators for session, since retrieving via
// HTTP may be expensive
this.code = code;
this.codeSource = source;
return code;
}.bind(this));
} else {
var promise = Zotero.File.getContentsAsync(this.path);
if(this.cacheCode) {
// Cache target-less web translators for session, since we
// will use them a lot
return promise.then(function(code) {
this.code = code;
return code;
}.bind(this));
}
return promise;
}
});
/**
* Get metadata block for a translator
*/
Zotero.Translator.prototype.serialize = function(properties) {
var info = {};
for(var i in properties) {
var property = properties[i];
info[property] = this[property];
}
return info;
}
/**
* Log a translator-related error
* @param {String} message The error message
* @param {String} [type] The error type ("error", "warning", "exception", or "strict")
* @param {String} [line] The text of the line on which the error occurred
* @param {Integer} lineNumber
* @param {Integer} colNumber
*/
Zotero.Translator.prototype.logError = function(message, type, line, lineNumber, colNumber) {
if (Zotero.isFx && this.path) {
Components.utils.import("resource://gre/modules/FileUtils.jsm");
var file = new FileUtils.File(this.path);
var ios = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
Zotero.log(message, type ? type : "error", ios.newFileURI(file).spec);
Zotero.debug(message, 1);
} else {
Zotero.logError(message);
}
}
/**
* Replace deprecated ES5 statements
*/
Zotero.Translator.replaceDeprecatedStatements = function(code) {
const foreach = /^(\s*)for each\s*\((var )?([^ ]+) in (.*?)\)(\s*){/gm;
code = code.replace(foreach, "$1var $3_zForEachSubject = $4; "+
"for(var $3_zForEachIndex in $3_zForEachSubject)$5{ "+
"$2$3 = $3_zForEachSubject[$3_zForEachIndex];");
return code;
}
Zotero.Translator.RUN_MODE_IN_BROWSER = 1;
Zotero.Translator.RUN_MODE_ZOTERO_STANDALONE = 2;
Zotero.Translator.RUN_MODE_ZOTERO_SERVER = 4;
Zotero.Translator.TRANSLATOR_TYPES = TRANSLATOR_TYPES;
Zotero.Translator.TRANSLATOR_OPTIONAL_PROPERTIES = TRANSLATOR_OPTIONAL_PROPERTIES;
Zotero.Translator.TRANSLATOR_REQUIRED_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES;

File diff suppressed because it is too large Load diff

View file

@ -1,402 +0,0 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
Utilities based in part on code taken from Piggy Bank 2.1.1 (BSD-licensed)
***** END LICENSE BLOCK *****
*/
/**
* @class All functions accessible from within Zotero.Utilities namespace inside sandboxed
* translators
*
* @constructor
* @augments Zotero.Utilities
* @borrows Zotero.Date.formatDate as this.formatDate
* @borrows Zotero.Date.strToDate as this.strToDate
* @borrows Zotero.Date.strToISO as this.strToISO
* @borrows Zotero.OpenURL.createContextObject as this.createContextObject
* @borrows Zotero.OpenURL.parseContextObject as this.parseContextObject
* @borrows Zotero.HTTP.processDocuments as this.processDocuments
* @borrows Zotero.HTTP.doPost as this.doPost
* @param {Zotero.Translate} translate
*/
Zotero.Utilities.Translate = function(translate) {
this._translate = translate;
}
var tmp = function() {};
tmp.prototype = Zotero.Utilities;
Zotero.Utilities.Translate.prototype = new tmp();
Zotero.Utilities.Translate.prototype.formatDate = Zotero.Date.formatDate;
Zotero.Utilities.Translate.prototype.strToDate = Zotero.Date.strToDate;
Zotero.Utilities.Translate.prototype.strToISO = Zotero.Date.strToISO;
Zotero.Utilities.Translate.prototype.createContextObject = Zotero.OpenURL.createContextObject;
Zotero.Utilities.Translate.prototype.parseContextObject = Zotero.OpenURL.parseContextObject;
/**
* Hack to overloads {@link Zotero.Utilities.capitalizeTitle} to allow overriding capitalizeTitles
* pref on a per-translate instance basis (for translator testing only)
*/
Zotero.Utilities.Translate.prototype.capitalizeTitle = function(string, force) {
if(force === undefined) {
var translate = this._translate;
do {
if(translate.capitalizeTitles !== undefined) {
force = translate.capitalizeTitles;
break;
}
} while(translate = translate._parentTranslator);
}
return Zotero.Utilities.capitalizeTitle(string, force);
}
/**
* Gets the current Zotero version
*
* @type String
*/
Zotero.Utilities.Translate.prototype.getVersion = function() {
return Zotero.version;
}
/**
* Takes an XPath query and returns the results
*
* @deprecated Use {@link Zotero.Utilities.xpath} or doc.evaluate() directly
* @type Node[]
*/
Zotero.Utilities.Translate.prototype.gatherElementsOnXPath = function(doc, parentNode, xpath, nsResolver) {
var elmts = [];
var iterator = doc.evaluate(xpath, parentNode, nsResolver, XPathResult.ANY_TYPE, null);
var elmt = iterator.iterateNext();
var i = 0;
while (elmt) {
elmts[i++] = elmt;
elmt = iterator.iterateNext();
}
return elmts;
}
/**
* Gets a given node as a string containing all child nodes
*
* @deprecated Use doc.evaluate and the "nodeValue" or "textContent" property
* @type String
*/
Zotero.Utilities.Translate.prototype.getNodeString = function(doc, contextNode, xpath, nsResolver) {
var elmts = this.gatherElementsOnXPath(doc, contextNode, xpath, nsResolver);
var returnVar = "";
for(var i=0; i<elmts.length; i++) {
returnVar += elmts[i].nodeValue;
}
return returnVar;
}
/**
* Grabs items based on URLs
*
* @param {Document} doc DOM document object
* @param {Element|Element[]} inHere DOM element(s) to process
* @param {RegExp} [urlRe] Regexp of URLs to add to list
* @param {RegExp} [urlRe] Regexp of URLs to reject
* @return {Object} Associative array of link => textContent pairs, suitable for passing to
* Zotero.selectItems from within a translator
*/
Zotero.Utilities.Translate.prototype.getItemArray = function(doc, inHere, urlRe, rejectRe) {
var availableItems = new Object(); // Technically, associative arrays are objects
// Require link to match this
if(urlRe) {
if(urlRe.exec) {
var urlRegexp = urlRe;
} else {
var urlRegexp = new RegExp();
urlRegexp.compile(urlRe, "i");
}
}
// Do not allow text to match this
if(rejectRe) {
if(rejectRe.exec) {
var rejectRegexp = rejectRe;
} else {
var rejectRegexp = new RegExp();
rejectRegexp.compile(rejectRe, "i");
}
}
if(!inHere.length) {
inHere = new Array(inHere);
}
for(var j=0; j<inHere.length; j++) {
var links = inHere[j].getElementsByTagName("a");
for(var i=0; i<links.length; i++) {
if(!urlRe || urlRegexp.test(links[i].href)) {
var text = "textContent" in links[i] ? links[i].textContent : links[i].innerText;
if(text) {
text = this.trimInternal(text);
if(!rejectRe || !rejectRegexp.test(text)) {
if(availableItems[links[i].href]) {
if(text != availableItems[links[i].href]) {
availableItems[links[i].href] += " "+text;
}
} else {
availableItems[links[i].href] = text;
}
}
}
}
}
}
return availableItems;
}
/**
* Load a single document in a hidden browser
*
* @deprecated Use processDocuments with a single URL
* @see Zotero.Utilities.Translate#processDocuments
*/
Zotero.Utilities.Translate.prototype.loadDocument = function(url, succeeded, failed) {
Zotero.debug("Zotero.Utilities.loadDocument is deprecated; please use processDocuments in new code");
this.processDocuments([url], succeeded, null, failed);
}
/**
* Already documented in Zotero.HTTP, except this optionally takes noCompleteOnError, which prevents
* the translation process from being cancelled automatically on error, as it is normally. The promise
* is still rejected on error for handling by the calling function.
* @ignore
*/
Zotero.Utilities.Translate.prototype.processDocuments = async function (urls, processor, noCompleteOnError) {
// Handle old signature: urls, processor, onDone, onError
if (arguments.length > 3 || typeof arguments[2] == 'function') {
Zotero.debug("ZU.processDocuments() now takes only 3 arguments -- update your code");
var onDone = arguments[2];
var onError = arguments[3];
noCompleteOnError = false;
}
var translate = this._translate;
if (typeof urls == "string") {
urls = [translate.resolveURL(urls)];
} else {
for(var i in urls) {
urls[i] = translate.resolveURL(urls[i]);
}
}
var processDoc = function (doc) {
return processor(doc, doc.location.href);
};
var funcs = [];
// If current URL passed, use loaded document instead of reloading
for (var i = 0; i < urls.length; i++) {
if(translate.document && translate.document.location
&& translate.document.location.toString() === urls[i]) {
Zotero.debug("Translate: Attempted to load the current document using processDocuments; using loaded document instead");
funcs.push(() => processDoc(this._translate.document, urls[i]));
urls.splice(i, 1);
i--;
}
}
translate.incrementAsyncProcesses("Zotero.Utilities.Translate#processDocuments");
if (urls.length) {
funcs.push(
() => Zotero.HTTP.processDocuments(
urls,
function (doc) {
if (!processor) return;
return processDoc(doc);
},
{
cookieSandbox: translate.cookieSandbox
}
)
);
}
var f;
while (f = funcs.shift()) {
try {
let maybePromise = f();
// The processor may or may not return a promise
if (maybePromise) {
await maybePromise;
}
}
catch (e) {
if (onError) {
try {
onError(e);
}
catch (e) {
translate.complete(false, e);
}
}
// Unless instructed otherwise, end the translation on error
else if (!noCompleteOnError) {
translate.complete(false, e);
}
throw e;
}
}
// Deprecated
if (onDone) {
onDone();
}
translate.decrementAsyncProcesses("Zotero.Utilities.Translate#processDocuments");
}
/**
* Send an HTTP GET request via XMLHTTPRequest
*
* @param {String|String[]} urls URL(s) to request
* @param {Function} processor Callback to be executed for each document loaded
* @param {Function} done Callback to be executed after all documents have been loaded
* @param {String} responseCharset Character set to force on the response
* @param {Object} requestHeaders HTTP headers to include with request
* @param {Number[]} successCodes - HTTP status codes that are considered
* successful, or FALSE to allow all
* @return {Boolean} True if the request was sent, or false if the browser is offline
*/
Zotero.Utilities.Translate.prototype.doGet = function(urls, processor, done, responseCharset, requestHeaders, successCodes) {
var callAgain = false,
me = this,
translate = this._translate;
if(typeof(urls) == "string") {
var url = urls;
} else {
if(urls.length > 1) callAgain = true;
var url = urls.shift();
}
url = translate.resolveURL(url);
translate.incrementAsyncProcesses("Zotero.Utilities.Translate#doGet");
var xmlhttp = Zotero.HTTP.doGet(url, function(xmlhttp) {
if (successCodes) {
var success = successCodes.includes(xmlhttp.status);
}
else if (successCodes === false) {
var success = true;
}
else {
var success = xmlhttp.status >= 200 && xmlhttp.status < 400;
}
if (!success) {
translate.complete(false, `HTTP GET ${url} failed with status code ${xmlhttp.status}`);
return;
}
try {
if(processor) {
processor(xmlhttp.responseText, xmlhttp, url);
}
if(callAgain) {
me.doGet(urls, processor, done, responseCharset);
} else {
if(done) {
done();
}
}
translate.decrementAsyncProcesses("Zotero.Utilities.Translate#doGet");
} catch(e) {
translate.complete(false, e);
}
}, responseCharset, this._translate.cookieSandbox, Object.assign({}, this._translate.requestHeaders, requestHeaders));
}
/**
* Already documented in Zotero.HTTP
* @ignore
*/
Zotero.Utilities.Translate.prototype.doPost = function(url, body, onDone, headers, responseCharset, successCodes) {
var translate = this._translate;
url = translate.resolveURL(url);
translate.incrementAsyncProcesses("Zotero.Utilities.Translate#doPost");
var xmlhttp = Zotero.HTTP.doPost(url, body, function(xmlhttp) {
if (successCodes) {
var success = successCodes.includes(xmlhttp.status);
}
else if (successCodes === false) {
var success = true;
}
else {
var success = xmlhttp.status >= 200 && xmlhttp.status < 400;
}
if (!success) {
translate.complete(false, `HTTP POST ${url} failed with status code ${xmlhttp.status}`);
return;
}
try {
onDone(xmlhttp.responseText, xmlhttp);
translate.decrementAsyncProcesses("Zotero.Utilities.Translate#doPost");
} catch(e) {
translate.complete(false, e);
}
}, Object.assign({}, translate.requestHeaders, headers), responseCharset, translate.cookieSandbox ? translate.cookieSandbox : undefined);
}
Zotero.Utilities.Translate.prototype.urlToProxy = function(url) {
var proxy = this._translate._proxy;
if (proxy) return proxy.toProxy(url);
return url;
};
Zotero.Utilities.Translate.prototype.urlToProper = function(url) {
var proxy = this._translate._proxy;
if (proxy) return proxy.toProper(url);
return url;
};
Zotero.Utilities.Translate.prototype.resolveURL = function (url, dontUseProxy) {
return this._translate.resolveURL(url, dontUseProxy);
};
Zotero.Utilities.Translate.prototype.__exposedProps__ = {"HTTP":"r"};
for(var j in Zotero.Utilities.Translate.prototype) {
if(typeof Zotero.Utilities.Translate.prototype[j] === "function" && j[0] !== "_" && j != "Translate") {
Zotero.Utilities.Translate.prototype.__exposedProps__[j] = "r";
}
}
if (typeof process === 'object' && process + '' === '[object process]'){
module.exports = Zotero.Utilities.Translate;
}

View file

@ -1,169 +0,0 @@
/*!
* XRegExp.build 3.0.0-pre
* <http://xregexp.com/>
* Steven Levithan © 2012 MIT License
* Inspired by Lea Verou's RegExp.create <http://lea.verou.me/>
*/
(function(XRegExp) {
'use strict';
var REGEX_DATA = 'xregexp',
subParts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*]/g,
parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subParts], 'g');
/**
* Strips a leading `^` and trailing unescaped `$`, if both are present.
* @private
* @param {String} pattern Pattern to process.
* @returns {String} Pattern with edge anchors removed.
*/
function deanchor(pattern) {
var leadingAnchor = /^\^/,
trailingAnchor = /\$$/;
// Ensure that the trailing `$` isn't escaped
if (leadingAnchor.test(pattern) && trailingAnchor.test(pattern.replace(/\\[\s\S]/g, ''))) {
return pattern.replace(leadingAnchor, '').replace(trailingAnchor, '');
}
return pattern;
}
/**
* Converts the provided value to an XRegExp. Native RegExp flags are not preserved.
* @private
* @param {String|RegExp} value Value to convert.
* @returns {RegExp} XRegExp object with XRegExp syntax applied.
*/
function asXRegExp(value) {
return XRegExp.isRegExp(value) ?
(value[REGEX_DATA] && value[REGEX_DATA].captureNames ?
// Don't recompile, to preserve capture names
value :
// Recompile as XRegExp
XRegExp(value.source)
) :
// Compile string as XRegExp
XRegExp(value);
}
/**
* Builds regexes using named subpatterns, for readability and pattern reuse. Backreferences in the
* outer pattern and provided subpatterns are automatically renumbered to work correctly. Native
* flags used by provided subpatterns are ignored in favor of the `flags` argument.
* @memberOf XRegExp
* @param {String} pattern XRegExp pattern using `{{name}}` for embedded subpatterns. Allows
* `({{name}})` as shorthand for `(?<name>{{name}})`. Patterns cannot be embedded within
* character classes.
* @param {Object} subs Lookup object for named subpatterns. Values can be strings or regexes. A
* leading `^` and trailing unescaped `$` are stripped from subpatterns, if both are present.
* @param {String} [flags] Any combination of XRegExp flags.
* @returns {RegExp} Regex with interpolated subpatterns.
* @example
*
* var time = XRegExp.build('(?x)^ {{hours}} ({{minutes}}) $', {
* hours: XRegExp.build('{{h12}} : | {{h24}}', {
* h12: /1[0-2]|0?[1-9]/,
* h24: /2[0-3]|[01][0-9]/
* }, 'x'),
* minutes: /^[0-5][0-9]$/
* });
* time.test('10:59'); // -> true
* XRegExp.exec('10:59', time).minutes; // -> '59'
*/
XRegExp.build = function(pattern, subs, flags) {
var inlineFlags = /^\(\?([\w$]+)\)/.exec(pattern),
data = {},
numCaps = 0, // 'Caps' is short for captures
numPriorCaps,
numOuterCaps = 0,
outerCapsMap = [0],
outerCapNames,
sub,
p;
// Add flags within a leading mode modifier to the overall pattern's flags
if (inlineFlags) {
flags = flags || '';
inlineFlags[1].replace(/./g, function(flag) {
// Don't add duplicates
flags += (flags.indexOf(flag) > -1 ? '' : flag);
});
}
for (p in subs) {
if (subs.hasOwnProperty(p)) {
// Passing to XRegExp enables extended syntax and ensures independent validity,
// lest an unescaped `(`, `)`, `[`, or trailing `\` breaks the `(?:)` wrapper. For
// subpatterns provided as native regexes, it dies on octals and adds the property
// used to hold extended regex instance data, for simplicity
sub = asXRegExp(subs[p]);
data[p] = {
// Deanchoring allows embedding independently useful anchored regexes. If you
// really need to keep your anchors, double them (i.e., `^^...$$`)
pattern: deanchor(sub.source),
names: sub[REGEX_DATA].captureNames || []
};
}
}
// Passing to XRegExp dies on octals and ensures the outer pattern is independently valid;
// helps keep this simple. Named captures will be put back
pattern = asXRegExp(pattern);
outerCapNames = pattern[REGEX_DATA].captureNames || [];
pattern = pattern.source.replace(parts, function($0, $1, $2, $3, $4) {
var subName = $1 || $2, capName, intro;
// Named subpattern
if (subName) {
if (!data.hasOwnProperty(subName)) {
throw new ReferenceError('Undefined property ' + $0);
}
// Named subpattern was wrapped in a capturing group
if ($1) {
capName = outerCapNames[numOuterCaps];
outerCapsMap[++numOuterCaps] = ++numCaps;
// If it's a named group, preserve the name. Otherwise, use the subpattern name
// as the capture name
intro = '(?<' + (capName || subName) + '>';
} else {
intro = '(?:';
}
numPriorCaps = numCaps;
return intro + data[subName].pattern.replace(subParts, function(match, paren, backref) {
// Capturing group
if (paren) {
capName = data[subName].names[numCaps - numPriorCaps];
++numCaps;
// If the current capture has a name, preserve the name
if (capName) {
return '(?<' + capName + '>';
}
// Backreference
} else if (backref) {
// Rewrite the backreference
return '\\' + (+backref + numPriorCaps);
}
return match;
}) + ')';
}
// Capturing group
if ($3) {
capName = outerCapNames[numOuterCaps];
outerCapsMap[++numOuterCaps] = ++numCaps;
// If the current capture has a name, preserve the name
if (capName) {
return '(?<' + capName + '>';
}
// Backreference
} else if ($4) {
// Rewrite the backreference
return '\\' + outerCapsMap[+$4];
}
return $0;
});
return XRegExp(pattern, flags);
};
}(XRegExp));

View file

@ -1,190 +0,0 @@
/*!
* XRegExp.matchRecursive 3.0.0-pre
* <http://xregexp.com/>
* Steven Levithan © 2009-2012 MIT License
*/
(function(XRegExp) {
'use strict';
/**
* Returns a match detail object composed of the provided values.
* @private
*/
function row(name, value, start, end) {
return {
name: name,
value: value,
start: start,
end: end
};
}
/**
* Returns an array of match strings between outermost left and right delimiters, or an array of
* objects with detailed match parts and position data. An error is thrown if delimiters are
* unbalanced within the data.
* @memberOf XRegExp
* @param {String} str String to search.
* @param {String} left Left delimiter as an XRegExp pattern.
* @param {String} right Right delimiter as an XRegExp pattern.
* @param {String} [flags] Any native or XRegExp flags, used for the left and right delimiters.
* @param {Object} [options] Lets you specify `valueNames` and `escapeChar` options.
* @returns {Array} Array of matches, or an empty array.
* @example
*
* // Basic usage
* var str = '(t((e))s)t()(ing)';
* XRegExp.matchRecursive(str, '\\(', '\\)', 'g');
* // -> ['t((e))s', '', 'ing']
*
* // Extended information mode with valueNames
* str = 'Here is <div> <div>an</div></div> example';
* XRegExp.matchRecursive(str, '<div\\s*>', '</div>', 'gi', {
* valueNames: ['between', 'left', 'match', 'right']
* });
* // -> [
* // {name: 'between', value: 'Here is ', start: 0, end: 8},
* // {name: 'left', value: '<div>', start: 8, end: 13},
* // {name: 'match', value: ' <div>an</div>', start: 13, end: 27},
* // {name: 'right', value: '</div>', start: 27, end: 33},
* // {name: 'between', value: ' example', start: 33, end: 41}
* // ]
*
* // Omitting unneeded parts with null valueNames, and using escapeChar
* str = '...{1}\\{{function(x,y){return y+x;}}';
* XRegExp.matchRecursive(str, '{', '}', 'g', {
* valueNames: ['literal', null, 'value', null],
* escapeChar: '\\'
* });
* // -> [
* // {name: 'literal', value: '...', start: 0, end: 3},
* // {name: 'value', value: '1', start: 4, end: 5},
* // {name: 'literal', value: '\\{', start: 6, end: 8},
* // {name: 'value', value: 'function(x,y){return y+x;}', start: 9, end: 35}
* // ]
*
* // Sticky mode via flag y
* str = '<1><<<2>>><3>4<5>';
* XRegExp.matchRecursive(str, '<', '>', 'gy');
* // -> ['1', '<<2>>', '3']
*/
XRegExp.matchRecursive = function(str, left, right, flags, options) {
flags = flags || '';
options = options || {};
var global = flags.indexOf('g') > -1,
sticky = flags.indexOf('y') > -1,
// Flag `y` is controlled internally
basicFlags = flags.replace(/y/g, ''),
escapeChar = options.escapeChar,
vN = options.valueNames,
output = [],
openTokens = 0,
delimStart = 0,
delimEnd = 0,
lastOuterEnd = 0,
outerStart,
innerStart,
leftMatch,
rightMatch,
esc;
left = XRegExp(left, basicFlags);
right = XRegExp(right, basicFlags);
if (escapeChar) {
if (escapeChar.length > 1) {
throw new Error('Cannot use more than one escape character');
}
escapeChar = XRegExp.escape(escapeChar);
// Using `XRegExp.union` safely rewrites backreferences in `left` and `right`
esc = new RegExp(
'(?:' + escapeChar + '[\\S\\s]|(?:(?!' +
XRegExp.union([left, right]).source +
')[^' + escapeChar + '])+)+',
// Flags `gy` not needed here
flags.replace(/[^im]+/g, '')
);
}
while (true) {
// If using an escape character, advance to the delimiter's next starting position,
// skipping any escaped characters in between
if (escapeChar) {
delimEnd += (XRegExp.exec(str, esc, delimEnd, 'sticky') || [''])[0].length;
}
leftMatch = XRegExp.exec(str, left, delimEnd);
rightMatch = XRegExp.exec(str, right, delimEnd);
// Keep the leftmost match only
if (leftMatch && rightMatch) {
if (leftMatch.index <= rightMatch.index) {
rightMatch = null;
} else {
leftMatch = null;
}
}
/* Paths (LM: leftMatch, RM: rightMatch, OT: openTokens):
* LM | RM | OT | Result
* 1 | 0 | 1 | loop
* 1 | 0 | 0 | loop
* 0 | 1 | 1 | loop
* 0 | 1 | 0 | throw
* 0 | 0 | 1 | throw
* 0 | 0 | 0 | break
* Doesn't include the sticky mode special case. The loop ends after the first
* completed match if not `global`.
*/
if (leftMatch || rightMatch) {
delimStart = (leftMatch || rightMatch).index;
delimEnd = delimStart + (leftMatch || rightMatch)[0].length;
} else if (!openTokens) {
break;
}
if (sticky && !openTokens && delimStart > lastOuterEnd) {
break;
}
if (leftMatch) {
if (!openTokens) {
outerStart = delimStart;
innerStart = delimEnd;
}
++openTokens;
} else if (rightMatch && openTokens) {
if (!--openTokens) {
if (vN) {
if (vN[0] && outerStart > lastOuterEnd) {
output.push(row(vN[0], str.slice(lastOuterEnd, outerStart), lastOuterEnd, outerStart));
}
if (vN[1]) {
output.push(row(vN[1], str.slice(outerStart, innerStart), outerStart, innerStart));
}
if (vN[2]) {
output.push(row(vN[2], str.slice(innerStart, delimStart), innerStart, delimStart));
}
if (vN[3]) {
output.push(row(vN[3], str.slice(delimStart, delimEnd), delimStart, delimEnd));
}
} else {
output.push(str.slice(innerStart, delimStart));
}
lastOuterEnd = delimEnd;
if (!global) {
break;
}
}
} else {
throw new Error('Unbalanced delimiter found in string');
}
// If the delimiter matched an empty string, avoid an infinite loop
if (delimStart === delimEnd) {
++delimEnd;
}
}
if (global && !sticky && vN && vN[0] && str.length > lastOuterEnd) {
output.push(row(vN[0], str.slice(lastOuterEnd), lastOuterEnd, str.length));
}
return output;
};
}(XRegExp));

View file

@ -1,239 +0,0 @@
/*!
* XRegExp Unicode Base 3.0.0-pre
* <http://xregexp.com/>
* Steven Levithan © 2008-2012 MIT License
* Uses Unicode 6.2.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
/**
* Adds support for the `\p{L}` or `\p{Letter}` Unicode category. Addon packages for other Unicode
* categories, scripts, blocks, and properties are available separately. Also adds flag A (astral),
* which enables 21-bit Unicode support. All Unicode tokens can be inverted using `\P{..}` or
* `\p{^..}`. Token names ignore case, spaces, hyphens, and underscores.
* @requires XRegExp
*/
(function(XRegExp) {
'use strict';
// Storage for Unicode data
var unicode = {};
/* ==============================
* Private functions
* ============================== */
// Generates a token lookup name: lowercase, with hyphens, spaces, and underscores removed
function normalize(name) {
return name.replace(/[- _]+/g, '').toLowerCase();
}
// Adds leading zeros if shorter than four characters
function pad4(str) {
while (str.length < 4) {
str = '0' + str;
}
return str;
}
// Converts a hexadecimal number to decimal
function dec(hex) {
return parseInt(hex, 16);
}
// Converts a decimal number to hexadecimal
function hex(dec) {
return parseInt(dec, 10).toString(16);
}
// Gets the decimal code of a literal code unit, \xHH, \uHHHH, or a backslash-escaped literal
function charCode(chr) {
var esc = /^\\[xu](.+)/.exec(chr);
return esc ?
dec(esc[1]) :
chr.charCodeAt(chr.charAt(0) === '\\' ? 1 : 0);
}
// Inverts a list of ordered BMP characters and ranges
function invertBmp(range) {
var output = '',
lastEnd = -1,
start;
XRegExp.forEach(range, /(\\x..|\\u....|\\?[\s\S])(?:-(\\x..|\\u....|\\?[\s\S]))?/, function(m) {
start = charCode(m[1]);
if (start > (lastEnd + 1)) {
output += '\\u' + pad4(hex(lastEnd + 1));
if (start > (lastEnd + 2)) {
output += '-\\u' + pad4(hex(start - 1));
}
}
lastEnd = charCode(m[2] || m[1]);
});
if (lastEnd < 0xFFFF) {
output += '\\u' + pad4(hex(lastEnd + 1));
if (lastEnd < 0xFFFE) {
output += '-\\uFFFF';
}
}
return output;
}
// Generates an inverted BMP range on first use
function cacheInvertedBmp(slug) {
var prop = 'b!';
return unicode[slug][prop] || (
unicode[slug][prop] = invertBmp(unicode[slug].bmp)
);
}
// Combines and optionally negates BMP and astral data
function buildAstral(slug, isNegated) {
var item = unicode[slug],
combined = '';
if (item.bmp && !item.isBmpLast) {
combined = '[' + item.bmp + ']' + (item.astral ? '|' : '');
}
if (item.astral) {
combined += item.astral;
}
if (item.isBmpLast && item.bmp) {
combined += (item.astral ? '|' : '') + '[' + item.bmp + ']';
}
// Astral Unicode tokens always match a code point, never a code unit
return isNegated ?
'(?:(?!' + combined + ')(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))' :
'(?:' + combined + ')';
}
// Builds a complete astral pattern on first use
function cacheAstral(slug, isNegated) {
var prop = isNegated ? 'a!' : 'a=';
return unicode[slug][prop] || (
unicode[slug][prop] = buildAstral(slug, isNegated)
);
}
/* ==============================
* Core functionality
* ============================== */
/* Add Unicode token syntax: \p{..}, \P{..}, \p{^..}. Also add astral mode (flag A).
*/
XRegExp.addToken(
// Use `*` instead of `+` to avoid capturing `^` as the token name in `\p{^}`
/\\([pP])(?:{(\^?)([^}]*)}|([A-Za-z]))/,
function(match, scope, flags) {
var ERR_DOUBLE_NEG = 'Invalid double negation ',
ERR_UNKNOWN_NAME = 'Unknown Unicode token ',
ERR_UNKNOWN_REF = 'Unicode token missing data ',
ERR_ASTRAL_ONLY = 'Astral mode required for Unicode token ',
ERR_ASTRAL_IN_CLASS = 'Astral mode does not support Unicode tokens within character classes',
// Negated via \P{..} or \p{^..}
isNegated = match[1] === 'P' || !!match[2],
// Switch from BMP (U+FFFF) to astral (U+10FFFF) mode via flag A or implicit opt-in
isAstralMode = flags.indexOf('A') > -1 || XRegExp.isInstalled('astral'),
// Token lookup name. Check `[4]` first to avoid passing `undefined` via `\p{}`
slug = normalize(match[4] || match[3]),
// Token data object
item = unicode[slug];
if (match[1] === 'P' && match[2]) {
throw new SyntaxError(ERR_DOUBLE_NEG + match[0]);
}
if (!unicode.hasOwnProperty(slug)) {
throw new SyntaxError(ERR_UNKNOWN_NAME + match[0]);
}
// Switch to the negated form of the referenced Unicode token
if (item.inverseOf) {
slug = normalize(item.inverseOf);
if (!unicode.hasOwnProperty(slug)) {
throw new ReferenceError(ERR_UNKNOWN_REF + match[0] + ' -> ' + item.inverseOf);
}
item = unicode[slug];
isNegated = !isNegated;
}
if (!(item.bmp || isAstralMode)) {
throw new SyntaxError(ERR_ASTRAL_ONLY + match[0]);
}
if (isAstralMode) {
if (scope === 'class') {
throw new SyntaxError(ERR_ASTRAL_IN_CLASS);
}
return cacheAstral(slug, isNegated);
}
return scope === 'class' ?
(isNegated ? cacheInvertedBmp(slug) : item.bmp) :
(isNegated ? '[^' : '[') + item.bmp + ']';
},
{
scope: 'all',
optionalFlags: 'A'
}
);
/**
* Adds to the list of Unicode tokens that XRegExp regexes can match via `\p` or `\P`.
* @memberOf XRegExp
* @param {Array} data Objects with named character ranges. Each object may have properties `name`,
* `alias`, `isBmpLast`, `inverseOf`, `bmp`, and `astral`. All but `name` are optional, although
* one of `bmp` or `astral` is required (unless `inverseOf` is set). If `astral` is absent, the
* `bmp` data is used for BMP and astral modes. If `bmp` is absent, the name errors in BMP mode
* but works in astral mode. If both `bmp` and `astral` are provided, the `bmp` data only is used
* in BMP mode, and the combination of `bmp` and `astral` data is used in astral mode.
* `isBmpLast` is needed when a token matches orphan high surrogates *and* uses surrogate pairs
* to match astral code points. The `bmp` and `astral` data should be a combination of literal
* characters and `\xHH` or `\uHHHH` escape sequences, with hyphens to create ranges. Any regex
* metacharacters in the data should be escaped, apart from range-creating hyphens. The `astral`
* data can additionally use character classes and alternation, and should use surrogate pairs to
* represent astral code points. `inverseOf` can be used to avoid duplicating character data if a
* Unicode token is defined as the exact inverse of another token.
* @example
*
* // Basic use
* XRegExp.addUnicodeData([{
* name: 'XDigit',
* alias: 'Hexadecimal',
* bmp: '0-9A-Fa-f'
* }]);
* XRegExp('\\p{XDigit}:\\p{Hexadecimal}+').test('0:3D'); // -> true
*/
XRegExp.addUnicodeData = function(data) {
var ERR_NO_NAME = 'Unicode token requires name',
ERR_NO_DATA = 'Unicode token has no character data ',
item,
i;
for (i = 0; i < data.length; ++i) {
item = data[i];
if (!item.name) {
throw new Error(ERR_NO_NAME);
}
if (!(item.inverseOf || item.bmp || item.astral)) {
throw new Error(ERR_NO_DATA + item.name);
}
unicode[normalize(item.name)] = item;
if (item.alias) {
unicode[normalize(item.alias)] = item;
}
}
// Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and
// flags might now produce different results
XRegExp.cache.flush('patterns');
};
/* Add data for the Unicode `L` or `Letter` category. Separate addons are available that add other
* categories, scripts, blocks, and properties.
*/
XRegExp.addUnicodeData([{
name: 'L',
alias: 'Letter',
bmp: 'A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC'
//astral: /* Removed to conserve space */
}]);
}(XRegExp));

View file

@ -1,185 +0,0 @@
/*!
* XRegExp Unicode Categories 3.0.0-pre
* <http://xregexp.com/>
* Steven Levithan © 2010-2012 MIT License
* Uses Unicode 6.2.0 <http://unicode.org/>
* Unicode data generated by Mathias Bynens <http://mathiasbynens.be/>
*/
/**
* Adds support for all Unicode categories. E.g., `\p{Lu}` or `\p{Uppercase Letter}`. Token names
* are case insensitive, and any spaces, hyphens, and underscores are ignored.
* @requires XRegExp, Unicode Base
*/
/**
* Control characters and astral planes removed to conserve space
*/
(function(XRegExp) {
'use strict';
if (!XRegExp.addUnicodeData) {
throw new ReferenceError('Unicode Base must be loaded before Unicode Categories');
}
XRegExp.addUnicodeData([
// Included in Unicode Base
/*{
name: 'L',
alias: 'Letter',
bmp: '...',
astral: '...'
},*/
{
name: 'Ll',
alias: 'Lowercase_Letter',
bmp: 'a-z\xB5\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0561-\u0587\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD0-\u1FD3\u1FD6\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u210A\u210E\u210F\u2113\u212F\u2134\u2139\u213C\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7FA\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A'
},
{
name: 'Lm',
alias: 'Modifier_Letter',
bmp: '\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5\u06E6\u07F4\u07F5\u07FA\u081A\u0824\u0828\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA717-\uA71F\uA770\uA788\uA7F8\uA7F9\uA9CF\uAA70\uAADD\uAAF3\uAAF4\uFF70\uFF9E\uFF9F'
},
{
name: 'Lo',
alias: 'Other_Letter',
bmp: '\xAA\xBA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05F0-\u05F2\u0620-\u063F\u0641-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E45\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10D0-\u10FA\u10FD-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A\uA62B\uA66E\uA6A0-\uA6E5\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC'
},
{
name: 'Lt',
alias: 'Titlecase_Letter',
bmp: '\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC'
},
{
name: 'Lu',
alias: 'Uppercase_Letter',
bmp: 'A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u0386\u0388-\u038A\u038C\u038E\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA\uFF21-\uFF3A'
},
{
name: 'M',
alias: 'Mark',
bmp: '\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u08FE\u0900-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C82\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D02\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1DC0-\u1DE6\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE26'
},
{
name: 'Mc',
alias: 'Spacing_Mark',
bmp: '\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E\u094F\u0982\u0983\u09BE-\u09C0\u09C7\u09C8\u09CB\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB\u0ACC\u0B02\u0B03\u0B3E\u0B40\u0B47\u0B48\u0B4B\u0B4C\u0B57\u0BBE\u0BBF\u0BC1\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7\u0CC8\u0CCA\u0CCB\u0CD5\u0CD6\u0D02\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2\u0DF3\u0F3E\u0F3F\u0F7F\u102B\u102C\u1031\u1038\u103B\u103C\u1056\u1057\u1062-\u1064\u1067-\u106D\u1083\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7\u17C8\u1923-\u1926\u1929-\u192B\u1930\u1931\u1933-\u1938\u19B0-\u19C0\u19C8\u19C9\u1A19-\u1A1B\u1A55\u1A57\u1A61\u1A63\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43\u1B44\u1B82\u1BA1\u1BA6\u1BA7\u1BAA\u1BAC\u1BAD\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2\u1BF3\u1C24-\u1C2B\u1C34\u1C35\u1CE1\u1CF2\u1CF3\u302E\u302F\uA823\uA824\uA827\uA880\uA881\uA8B4-\uA8C3\uA952\uA953\uA983\uA9B4\uA9B5\uA9BA\uA9BB\uA9BD-\uA9C0\uAA2F\uAA30\uAA33\uAA34\uAA4D\uAA7B\uAAEB\uAAEE\uAAEF\uAAF5\uABE3\uABE4\uABE6\uABE7\uABE9\uABEA\uABEC'
},
{
name: 'Me',
alias: 'Enclosing_Mark',
bmp: '\u0488\u0489\u20DD-\u20E0\u20E2-\u20E4\uA670-\uA672'
},
{
name: 'Mn',
alias: 'Nonspacing_Mark',
bmp: '\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u08FE\u0900-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2\u09E3\u0A01\u0A02\u0A3C\u0A41\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7\u0AC8\u0ACD\u0AE2\u0AE3\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62\u0B63\u0B82\u0BC0\u0BCD\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0CBC\u0CBF\u0CC6\u0CCC\u0CCD\u0CE2\u0CE3\u0D41-\u0D44\u0D4D\u0D62\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039\u103A\u103D\u103E\u1058\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193B\u1A17\u1A18\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80\u1B81\u1BA2-\u1BA5\u1BA8\u1BA9\u1BAB\u1BE6\u1BE8\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1DC0-\u1DE6\u1DFC-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099\u309A\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA825\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uAA29-\uAA2E\uAA31\uAA32\uAA35\uAA36\uAA43\uAA4C\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEC\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE26'
},
{
name: 'N',
alias: 'Number',
bmp: '0-9\xB2\xB3\xB9\xBC-\xBE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19'
},
{
name: 'Nd',
alias: 'Decimal_Number',
bmp: '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19'
},
{
name: 'Nl',
alias: 'Letter_Number',
bmp: '\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF'
},
{
name: 'No',
alias: 'Other_Number',
bmp: '\xB2\xB3\xB9\xBC-\xBE\u09F4-\u09F9\u0B72-\u0B77\u0BF0-\u0BF2\u0C78-\u0C7E\u0D70-\u0D75\u0F2A-\u0F33\u1369-\u137C\u17F0-\u17F9\u19DA\u2070\u2074-\u2079\u2080-\u2089\u2150-\u215F\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA830-\uA835'
},
{
name: 'P',
alias: 'Punctuation',
bmp: '\x21-\x23\x25-\\x2A\x2C-\x2F\x3A\x3B\\x3F\x40\\x5B-\\x5D\x5F\\x7B\x7D\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E3B\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65'
},
{
name: 'Pc',
alias: 'Connector_Punctuation',
bmp: '\x5F\u203F\u2040\u2054\uFE33\uFE34\uFE4D-\uFE4F\uFF3F'
},
{
name: 'Pd',
alias: 'Dash_Punctuation',
bmp: '\\x2D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D'
},
{
name: 'Pe',
alias: 'Close_Punctuation',
bmp: '\\x29\\x5D\x7D\u0F3B\u0F3D\u169C\u2046\u207E\u208E\u232A\u2769\u276B\u276D\u276F\u2771\u2773\u2775\u27C6\u27E7\u27E9\u27EB\u27ED\u27EF\u2984\u2986\u2988\u298A\u298C\u298E\u2990\u2992\u2994\u2996\u2998\u29D9\u29DB\u29FD\u2E23\u2E25\u2E27\u2E29\u3009\u300B\u300D\u300F\u3011\u3015\u3017\u3019\u301B\u301E\u301F\uFD3F\uFE18\uFE36\uFE38\uFE3A\uFE3C\uFE3E\uFE40\uFE42\uFE44\uFE48\uFE5A\uFE5C\uFE5E\uFF09\uFF3D\uFF5D\uFF60\uFF63'
},
{
name: 'Pf',
alias: 'Final_Punctuation',
bmp: '\xBB\u2019\u201D\u203A\u2E03\u2E05\u2E0A\u2E0D\u2E1D\u2E21'
},
{
name: 'Pi',
alias: 'Initial_Punctuation',
bmp: '\xAB\u2018\u201B\u201C\u201F\u2039\u2E02\u2E04\u2E09\u2E0C\u2E1C\u2E20'
},
{
name: 'Po',
alias: 'Other_Punctuation',
bmp: '\x21-\x23\x25-\x27\\x2A\x2C\\x2E\x2F\x3A\x3B\\x3F\x40\\x5C\xA1\xA7\xB6\xB7\xBF\u037E\u0387\u055A-\u055F\u0589\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u166D\u166E\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u1805\u1807-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2016\u2017\u2020-\u2027\u2030-\u2038\u203B-\u203E\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205E\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00\u2E01\u2E06-\u2E08\u2E0B\u2E0E-\u2E16\u2E18\u2E19\u2E1B\u2E1E\u2E1F\u2E2A-\u2E2E\u2E30-\u2E39\u3001-\u3003\u303D\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFE10-\uFE16\uFE19\uFE30\uFE45\uFE46\uFE49-\uFE4C\uFE50-\uFE52\uFE54-\uFE57\uFE5F-\uFE61\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF07\uFF0A\uFF0C\uFF0E\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3C\uFF61\uFF64\uFF65'
},
{
name: 'Ps',
alias: 'Open_Punctuation',
bmp: '\\x28\\x5B\\x7B\u0F3A\u0F3C\u169B\u201A\u201E\u2045\u207D\u208D\u2329\u2768\u276A\u276C\u276E\u2770\u2772\u2774\u27C5\u27E6\u27E8\u27EA\u27EC\u27EE\u2983\u2985\u2987\u2989\u298B\u298D\u298F\u2991\u2993\u2995\u2997\u29D8\u29DA\u29FC\u2E22\u2E24\u2E26\u2E28\u3008\u300A\u300C\u300E\u3010\u3014\u3016\u3018\u301A\u301D\uFD3E\uFE17\uFE35\uFE37\uFE39\uFE3B\uFE3D\uFE3F\uFE41\uFE43\uFE47\uFE59\uFE5B\uFE5D\uFF08\uFF3B\uFF5B\uFF5F\uFF62'
},
{
name: 'S',
alias: 'Symbol',
bmp: '\\x24\\x2B\x3C-\x3E\\x5E\x60\\x7C\x7E\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20BA\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u2190-\u2328\u232B-\u23F3\u2400-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u26FF\u2701-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B4C\u2B50-\u2B59\u2CE5-\u2CEA\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u32FE\u3300-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uFB29\uFBB2-\uFBC1\uFDFC\uFDFD\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD'
},
{
name: 'Sc',
alias: 'Currency_Symbol',
bmp: '\\x24\xA2-\xA5\u058F\u060B\u09F2\u09F3\u09FB\u0AF1\u0BF9\u0E3F\u17DB\u20A0-\u20BA\uA838\uFDFC\uFE69\uFF04\uFFE0\uFFE1\uFFE5\uFFE6'
},
{
name: 'Sk',
alias: 'Modifier_Symbol',
bmp: '\\x5E\x60\xA8\xAF\xB4\xB8\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u309B\u309C\uA700-\uA716\uA720\uA721\uA789\uA78A\uFBB2-\uFBC1\uFF3E\uFF40\uFFE3'
},
{
name: 'Sm',
alias: 'Math_Symbol',
bmp: '\\x2B\x3C-\x3E\\x7C\x7E\xAC\xB1\xD7\xF7\u03F6\u0606-\u0608\u2044\u2052\u207A-\u207C\u208A-\u208C\u2118\u2140-\u2144\u214B\u2190-\u2194\u219A\u219B\u21A0\u21A3\u21A6\u21AE\u21CE\u21CF\u21D2\u21D4\u21F4-\u22FF\u2308-\u230B\u2320\u2321\u237C\u239B-\u23B3\u23DC-\u23E1\u25B7\u25C1\u25F8-\u25FF\u266F\u27C0-\u27C4\u27C7-\u27E5\u27F0-\u27FF\u2900-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2AFF\u2B30-\u2B44\u2B47-\u2B4C\uFB29\uFE62\uFE64-\uFE66\uFF0B\uFF1C-\uFF1E\uFF5C\uFF5E\uFFE2\uFFE9-\uFFEC'
},
{
name: 'So',
alias: 'Other_Symbol',
bmp: '\xA6\xA9\xAE\xB0\u0482\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09FA\u0B70\u0BF3-\u0BF8\u0BFA\u0C7F\u0D79\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116\u2117\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u214A\u214C\u214D\u214F\u2195-\u2199\u219C-\u219F\u21A1\u21A2\u21A4\u21A5\u21A7-\u21AD\u21AF-\u21CD\u21D0\u21D1\u21D3\u21D5-\u21F3\u2300-\u2307\u230C-\u231F\u2322-\u2328\u232B-\u237B\u237D-\u239A\u23B4-\u23DB\u23E2-\u23F3\u2400-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u25B6\u25B8-\u25C0\u25C2-\u25F7\u2600-\u266E\u2670-\u26FF\u2701-\u2767\u2794-\u27BF\u2800-\u28FF\u2B00-\u2B2F\u2B45\u2B46\u2B50-\u2B59\u2CE5-\u2CEA\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u32FE\u3300-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA828-\uA82B\uA836\uA837\uA839\uAA77-\uAA79\uFDFD\uFFE4\uFFE8\uFFED\uFFEE\uFFFC\uFFFD'
},
{
name: 'Z',
alias: 'Separator',
bmp: '\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000'
},
{
name: 'Zl',
alias: 'Line_Separator',
bmp: '\u2028'
},
{
name: 'Zp',
alias: 'Paragraph_Separator',
bmp: '\u2029'
},
{
name: 'Zs',
alias: 'Space_Separator',
bmp: '\x20\xA0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000'
}
]);
}(XRegExp));

View file

@ -1,44 +0,0 @@
/**
* Adds support for various character categories used by Zotero.
* Token names are case insensitive, and any spaces, hyphens, and underscores are ignored.
* @requires XRegExp, Unicode Base
*/
(function(XRegExp) {
'use strict';
if (!XRegExp.addUnicodeData) {
throw new ReferenceError('Unicode Base must be loaded before Unicode Zotero');
}
XRegExp.addUnicodeData([
{
name: 'WSpace',
alias: 'White_Space',
bmp: '\x09-\x0D\x20\x85\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000'
},
{
name: 'Hex',
alias: 'Hex_Digit',
bmp: '0-9A-Fa-f\uFF10-\uFF19\uFF21-\uFF26\uFF41-\uFF46'
},
{
name: 'Dash',
bmp: '\x2D\u058A\u05BE\u1806\u2010-\u2015\u2053\u207B\u208B\u2212\u2E17\u2E1A\u301C\u3030\u30A0\uFE31-\uFE32\uFE58\uFE63\uFF0D'
},
{
name: 'Hyphen',
bmp: '\x2D\xAD\u058A\u1806\u2010-\u2011\u2E17\u30FB\uFE63\uFF0D\uFF65'
},
{
name: 'QMark',
alias: 'Quotation_Mark',
bmp: '\x22\x27\xAB\xBB\u2018\u2019\u201A\u201B-\u201C\u201D\u201E\u201F\u2039\u203A\u300C\u300D\u300E\u300F\u301D\u301E-\u301F\uFE41\uFE42\uFE43\uFE44\uFF02\uFF07\uFF62\uFF63'
},
{
name: 'Term',
alias: 'Terminal_Punctuation',
bmp: '\x21\x2C\x2E\x3A-\x3B\x3F\u037E\u0387\u0589\u05C3\u060C\u061B\u061F\u06D4\u0700-\u070A\u070C\u07F8-\u07F9\u0964-\u0965\u0E5A-\u0E5B\u0F08\u0F0D-\u0F12\u104A-\u104B\u1361-\u1368\u166D-\u166E\u16EB-\u16ED\u17D4-\u17D6\u17DA\u1802-\u1805\u1808-\u1809\u1944-\u1945\u1B5A-\u1B5B\u1B5D-\u1B5F\u1C3B-\u1C3F\u1C7E-\u1C7F\u203C-\u203D\u2047-\u2049\u2E2E\u3001-\u3002\uA60D-\uA60F\uA876-\uA877\uA8CE-\uA8CF\uA92F\uAA5D-\uAA5F\uFE50-\uFE52\uFE54-\uFE57\uFF01\uFF0C\uFF0E\uFF1A-\uFF1B\uFF1F\uFF61\uFF64\u1039F\u103D0\u1091F\u12470-\u12473'
}
]);
}(XRegExp));

File diff suppressed because it is too large Load diff