@citation-js/core
Version:
Convert different bibliographic metadata sources
193 lines • 6.4 kB
JavaScript
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { type, typeMatcher } from './type.js';
class TypeParser {
constructor(data) {
_defineProperty(this, "validDataTypes", ['String', 'Array', 'SimpleObject', 'ComplexObject', 'Primitive']);
this.data = data;
}
validateDataType() {
const dataType = this.data.dataType;
if (dataType && !this.validDataTypes.includes(dataType)) {
throw new RangeError(`dataType was ${dataType}; expected one of ${this.validDataTypes}`);
}
}
validateParseType() {
const predicate = this.data.predicate;
if (predicate && !(predicate instanceof RegExp || typeof predicate === 'function')) {
throw new TypeError(`predicate was ${typeof predicate}; expected RegExp or function`);
}
}
validateTokenList() {
const tokenList = this.data.tokenList;
if (tokenList && typeof tokenList !== 'object') {
throw new TypeError(`tokenList was ${typeof tokenList}; expected object or RegExp`);
}
}
validatePropertyConstraint() {
const propertyConstraint = this.data.propertyConstraint;
if (propertyConstraint && typeof propertyConstraint !== 'object') {
throw new TypeError(`propertyConstraint was ${typeof propertyConstraint}; expected array or object`);
}
}
validateElementConstraint() {
const elementConstraint = this.data.elementConstraint;
if (elementConstraint && typeof elementConstraint !== 'string') {
throw new TypeError(`elementConstraint was ${typeof elementConstraint}; expected string`);
}
}
validateExtends() {
const extend = this.data.extends;
if (extend && typeof extend !== 'string') {
throw new TypeError(`extends was ${typeof extend}; expected string`);
}
}
validate() {
if (this.data === null || typeof this.data !== 'object') {
throw new TypeError(`typeParser was ${typeof this.data}; expected object`);
}
this.validateDataType();
this.validateParseType();
this.validateTokenList();
this.validatePropertyConstraint();
this.validateElementConstraint();
this.validateExtends();
}
parseTokenList() {
let tokenList = this.data.tokenList;
if (!tokenList) {
return [];
} else if (tokenList instanceof RegExp) {
tokenList = {
token: tokenList
};
}
const {
token,
split = /\s+/,
trim = true,
every = true
} = tokenList;
const trimInput = input => trim ? input.trim() : input;
const testTokens = every ? 'every' : 'some';
const predicate = input => trimInput(input).split(split)[testTokens](part => token.test(part));
return [predicate];
}
parsePropertyConstraint() {
const constraints = [].concat(this.data.propertyConstraint || []);
return constraints.map(({
props,
match,
value
}) => {
props = [].concat(props);
switch (match) {
case 'any':
case 'some':
return input => props.some(prop => prop in input && (!value || value(input[prop])));
case 'none':
return input => !props.some(prop => prop in input && (!value || value(input[prop])));
case 'every':
default:
return input => props.every(prop => prop in input && (!value || value(input[prop])));
}
});
}
parseElementConstraint() {
const constraint = this.data.elementConstraint;
return !constraint ? [] : [input => input.every(entry => type(entry) === constraint)];
}
parsePredicate() {
if (this.data.predicate instanceof RegExp) {
return [this.data.predicate.test.bind(this.data.predicate)];
} else if (this.data.predicate) {
return [this.data.predicate];
} else {
return [];
}
}
getCombinedPredicate() {
const predicates = [...this.parsePredicate(), ...this.parseTokenList(), ...this.parsePropertyConstraint(), ...this.parseElementConstraint()];
if (predicates.length === 0) {
return () => true;
} else if (predicates.length === 1) {
return predicates[0];
} else {
return input => predicates.every(predicate => predicate(input));
}
}
getDataType() {
if (this.data.dataType) {
return this.data.dataType;
} else if (this.data.predicate instanceof RegExp) {
return 'String';
} else if (this.data.tokenList) {
return 'String';
} else if (this.data.elementConstraint) {
return 'Array';
} else {
return 'Primitive';
}
}
get dataType() {
return this.getDataType();
}
get predicate() {
return this.getCombinedPredicate();
}
get extends() {
return this.data.extends;
}
}
class DataParser {
constructor(parser, {
async
} = {}) {
this.parser = parser;
this.async = async;
}
validate() {
const parser = this.parser;
if (typeof parser !== 'function') {
throw new TypeError(`parser was ${typeof parser}; expected function`);
}
}
}
class FormatParser {
constructor(format, parsers = {}) {
this.format = format;
if (parsers.parseType) {
this.typeParser = new TypeParser(parsers.parseType);
}
if (parsers.parse) {
this.dataParser = new DataParser(parsers.parse, {
async: false
});
}
if (parsers.parseAsync) {
this.asyncDataParser = new DataParser(parsers.parseAsync, {
async: true
});
}
}
validateFormat() {
const format = this.format;
if (!typeMatcher.test(format)) {
throw new TypeError(`format name was "${format}"; didn't match expected pattern`);
}
}
validate() {
this.validateFormat();
if (this.typeParser) {
this.typeParser.validate();
}
if (this.dataParser) {
this.dataParser.validate();
}
if (this.asyncDataParser) {
this.asyncDataParser.validate();
}
}
}
export { TypeParser, DataParser, FormatParser };