Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
509101394c |
|
|
@ -25,7 +25,7 @@ main() {
|
|||
deletions+=($(git diff-index --diff-filter=D --name-only --find-renames $MASTER|grep -v '\.ci'|grep 'js$'))
|
||||
if (( ${#deletions[@]} > 0 ));then
|
||||
for f in "${deletions[@]}";do
|
||||
local id=$(git show $MASTER:"$f" | get_translator_id)
|
||||
local id=$(git show $MASTER:"$f" | grep_translator_id)
|
||||
if ! grep -qF "$id" '../deleted.txt';then
|
||||
echo "${color_notok}not ok${color_reset} - $id ($f) should be added to deleted.txt"
|
||||
(( failed += 1))
|
||||
|
|
|
|||
|
|
@ -2,8 +2,110 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const find = require('recursive-readdir-synchronous');
|
||||
const CLIEngine = require("eslint").CLIEngine;
|
||||
const argv = require('commander');
|
||||
|
||||
process.argv = process.argv.map(arg => arg === '--output-json' ? [ '--format', 'json', '--output-file' ] : arg).flat();
|
||||
const translators = require('../lib/translators');
|
||||
|
||||
require('../../../node_modules/.bin/eslint')
|
||||
argv
|
||||
.version(CLIEngine.version)
|
||||
.option('-f, --fix', 'Automatically fix problems')
|
||||
.option('--no-ignore', 'Disable use of ignore files and patterns')
|
||||
.option('--quiet', 'Report errors only - default: false')
|
||||
.option('--dump-decorated [file]', 'Dump decorated translator to file for inspection')
|
||||
.parse(process.argv);
|
||||
|
||||
/* PATCHES */
|
||||
// disable the processor so that fixing works
|
||||
const eslintPluginZoteroTranslator = require('eslint-plugin-zotero-translator');
|
||||
delete eslintPluginZoteroTranslator.processors;
|
||||
|
||||
/* MAIN */
|
||||
// split sources to lint into regular javascript (handled by executeOnFiles) and translators (handled by executeOnText)
|
||||
const sources = {
|
||||
javascripts: [],
|
||||
translators: [],
|
||||
errors: 0,
|
||||
};
|
||||
function findIgnore(file, stats) {
|
||||
if (stats.isDirectory()) return (path.basename(file) == "node_modules");
|
||||
return !file.endsWith('.js');
|
||||
}
|
||||
for (const target of argv.args) {
|
||||
if (!fs.existsSync(target)) continue;
|
||||
const files = fs.lstatSync(target).isDirectory() ? find(target, [findIgnore]) : [target];
|
||||
for (const file of files) {
|
||||
if (path.dirname(path.resolve(file)) === translators.cache.repo) {
|
||||
const translator = translators.cache.get(file);
|
||||
if (translator.header) {
|
||||
translator.filename = file;
|
||||
sources.translators.push(translator);
|
||||
}
|
||||
else {
|
||||
sources.javascripts.push(file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sources.javascripts.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cli = new CLIEngine({
|
||||
cwd: translators.cache.repo,
|
||||
fix: argv.fix,
|
||||
ignore: argv.ignore, // otherwise you can't lint stuff in hidden dirs
|
||||
});
|
||||
const formatter = cli.getFormatter();
|
||||
function showResults(files, results) {
|
||||
if (argv.quiet) results = CLIEngine.getErrorResults(results);
|
||||
for (const res of results) {
|
||||
sources.errors += res.errorCount;
|
||||
}
|
||||
|
||||
if (results.length) {
|
||||
console.log(formatter(results)); // eslint-disable-line no-console
|
||||
}
|
||||
else {
|
||||
if (Array.isArray(files)) files = files.join(', ');
|
||||
if (!argv.quiet) console.log(files, 'OK'); // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
if (sources.javascripts.length) {
|
||||
const report = cli.executeOnFiles(sources.javascripts);
|
||||
if (argv.fix) {
|
||||
for (const result of report.results) {
|
||||
if (result.messages.find(msg => msg.ruleId === 'notice/notice' && msg.fix)) {
|
||||
console.log(`Not safe to apply 'notice/notice' to ${result.filePath}`); // eslint-disable-line no-console
|
||||
process.exit(1); // eslint-disable-line no-process-exit
|
||||
}
|
||||
}
|
||||
CLIEngine.outputFixes(report);
|
||||
}
|
||||
showResults(sources.javascripts, report.results);
|
||||
}
|
||||
|
||||
for (const translator of sources.translators) {
|
||||
if (argv.dumpDecorated) fs.writeFileSync(argv.dumpDecorated, translator.source, 'utf-8');
|
||||
const report = cli.executeOnText(translator.source, translator.filename);
|
||||
if (argv.fix) {
|
||||
for (const result of report.results) {
|
||||
if (result.output) {
|
||||
try {
|
||||
fs.writeFileSync(result.filePath, translators.strip(result.output), 'utf-8');
|
||||
}
|
||||
catch (err) {
|
||||
console.log(`Error writing fixed ${result.filePath}: ${err.message}`); // eslint-disable-line no-console
|
||||
process.exit(1); // eslint-disable-line no-process-exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
showResults(translator.filename, report.results);
|
||||
}
|
||||
|
||||
process.exit(sources.errors); // eslint-disable-line no-process-exit
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ const requireDir = require('require-dir');
|
|||
module.exports = {
|
||||
rules: requireDir('./lib/rules'),
|
||||
processors: {
|
||||
translator: require('./processor'),
|
||||
},
|
||||
'.js': require('./lib/processor'),
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators').cache;
|
||||
|
||||
module.exports = {
|
||||
preprocess: function (text, filename) {
|
||||
const translator = translators.get(filename);
|
||||
|
||||
return [(typeof translator.source === 'string') ? translator.source : text];
|
||||
},
|
||||
|
||||
postprocess: function (messages, _filename) {
|
||||
return messages[0];
|
||||
},
|
||||
};
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed, header } = require('../../processor').support;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'enforce valid lastUpdated in header',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const filename = context.getFilename();
|
||||
const translator = parsed(filename);
|
||||
if (!translator || !translator.header.fields) return; // regular js source, or header is invalid
|
||||
|
||||
const lastUpdated = header(node).properties.find(p => p.key.value === 'lastUpdated');
|
||||
|
||||
if (!lastUpdated) {
|
||||
context.report({
|
||||
loc: { start: { line: 1, column: 1 } },
|
||||
message: 'Header needs lastUpdated field',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const format = date => date.toISOString().replace('T', ' ').replace(/\..*/, '');
|
||||
const now = format(new Date());
|
||||
const fix = fixer => fixer.replaceText(lastUpdated.value, `"${now}"`);
|
||||
|
||||
if (typeof lastUpdated.value.value !== 'string' || !lastUpdated.value.value.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/)) {
|
||||
context.report({
|
||||
node: lastUpdated.value,
|
||||
message: `lastUpdated field must be a string in YYYY-MM-DD HH:MM:SS format`,
|
||||
fix,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (translator.lastUpdated && translator.lastUpdated > lastUpdated.value.value) {
|
||||
context.report({
|
||||
node: lastUpdated.value,
|
||||
message: `lastUpdated field must be updated to be > ${translator.lastUpdated} to push to clients`,
|
||||
fix,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const { repo, parsed, header, IDconflict } = require('../../processor').support;
|
||||
|
||||
const deleted = new Set(
|
||||
fs.readFileSync(path.join(repo, 'deleted.txt'), 'utf-8')
|
||||
.split('\n')
|
||||
.map(line => line.split(' ')[0])
|
||||
.filter(id => id && id.indexOf('-') > 0)
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'disallows translatorID re-use',
|
||||
category: 'Potential Problems',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const filename = context.getFilename();
|
||||
const translator = parsed(filename);
|
||||
if (!translator || !translator.header.fields) return; // regular js source, or header is invalid
|
||||
|
||||
const translatorID = header(node).properties.find(p => p.key.value === 'translatorID');
|
||||
|
||||
if (!translatorID || !translatorID.value.value) {
|
||||
context.report({
|
||||
node: header(node),
|
||||
message: 'Header has no translator ID',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (deleted.has(translatorID.value.value)) {
|
||||
context.report({
|
||||
node: translatorID.value,
|
||||
message: 'Header re-uses translator ID of deleted translator',
|
||||
fix: function (fixer) {
|
||||
return fixer.replaceText(translatorID.value, `"${uuid()}"`);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const conflict = IDconflict(filename);
|
||||
if (conflict) {
|
||||
context.report({
|
||||
node: translatorID.value,
|
||||
message: `re-uses translator ID of ${conflict.label}`,
|
||||
fix: fixer => fixer.replaceText(translatorID.value, `"${uuid()}"`),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed } = require('../../processor').support;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'enforce translatorType against handler functions',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (program) {
|
||||
const translator = parsed(context.getFilename());
|
||||
if (!translator || !translator.header.fields) return; // regular js source, or header is invalid
|
||||
|
||||
const functions = program.body.map((node) => {
|
||||
if (node.type === 'FunctionDeclaration') return node.id && node.id.name;
|
||||
if (node.type === 'VariableDeclaration'
|
||||
&& node.declarations.length === 1
|
||||
&& node.declarations[0].init
|
||||
&& node.declarations[0].init.type === 'FunctionExpression') {
|
||||
return node.declarations[0].id.name;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(name => name);
|
||||
|
||||
const type = {
|
||||
import: 1,
|
||||
export: 2,
|
||||
web: 4,
|
||||
search: 8
|
||||
};
|
||||
|
||||
const translatorType = translator.header.fields.translatorType;
|
||||
const browserSupport = translator.header.fields.browserSupport;
|
||||
|
||||
if (browserSupport && !(translatorType & type.web)) {
|
||||
context.report({
|
||||
loc: { start: { line: 1, column: 1 } },
|
||||
message: `browserSupport set, but translatorType (${translatorType}) does not include web (${type.web})`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for (const name of ['detectWeb', 'doWeb', 'detectImport', 'doImport', 'doExport', 'detectSearch', 'doSearch']) {
|
||||
const handler = functions.includes(name);
|
||||
const mode = name.replace(/^(detect|do)/, '').toLowerCase();
|
||||
const bit = type[mode];
|
||||
if (handler && !(translatorType & bit)) {
|
||||
context.report({
|
||||
loc: { start: { line: 1, column: 1 } },
|
||||
message: `${name} present, but translatorType (${translatorType}) does not specify ${mode} (${bit})`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!handler && (translatorType & bit)) {
|
||||
let message = `translatorType specifies ${mode} (${bit}), but no ${name} present`;
|
||||
if (translatorType & type.web && mode !== 'web') {
|
||||
// Lots of common errors involve web translator developers not understanding
|
||||
// translator type jargon and checking too many boxes - checking "search"
|
||||
// because the translator supports search pages, or "import" because it
|
||||
// imports items from the site.
|
||||
// Be extra explicit when it seems like that might be the situation.
|
||||
message += `. This web translator is probably NOT a${bit <= 2 ? 'n' : ''} ${mode} translator, `
|
||||
+ `even if it supports "${mode}" pages or "${mode}ing". Uncheck "${mode}" in Scaffold.`;
|
||||
}
|
||||
context.report({
|
||||
loc: { start: { line: 1, column: 1 } },
|
||||
message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed, json } = require('../../processor').support;
|
||||
const translators = require('../translators').cache;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -14,15 +14,14 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (_node) {
|
||||
const translator = parsed(context.getFilename());
|
||||
const translator = translators.get(context.getFilename());
|
||||
|
||||
if (!translator || translator.header.fields) return; // regular js source, or header is valid json
|
||||
if (!translator.source) return; // regular js source
|
||||
|
||||
const err = json.try(translator.header.text, { line: 0, position: 1 });
|
||||
if (err) {
|
||||
if (translator.header.error) {
|
||||
context.report({
|
||||
message: `Could not parse header: ${err.message}`,
|
||||
loc: { start: { line: err.line, column: err.column } },
|
||||
message: `Could not parse header: ${translator.header.error.message}`,
|
||||
loc: { start: { line: translator.error.line, column: translator.error.column } },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators').cache;
|
||||
const getHeaderFromAST = require('../translators').getHeaderFromAST;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'enforce valid lastUpdated in header',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const header = getHeaderFromAST(node);
|
||||
if (!header.declaration) return;
|
||||
|
||||
const translator = translators.get(context.getFilename());
|
||||
|
||||
const updated = (new Date)
|
||||
.toISOString()
|
||||
.replace('T', ' ')
|
||||
.replace(/\..*/, '');
|
||||
|
||||
if (!header.properties.lastUpdated) {
|
||||
context.report({
|
||||
node: header.declaration,
|
||||
message: 'Header needs lastUpdated field'
|
||||
});
|
||||
}
|
||||
else if (translator.lastUpdated && translator.lastUpdated >= header.properties.lastUpdated.value) {
|
||||
context.report({
|
||||
node: header.properties.lastUpdated,
|
||||
message: `lastUpdated field must be updated to be > ${translator.lastUpdated} to push to clients`,
|
||||
fix: function (fixer) {
|
||||
return fixer.replaceText(header.properties.lastUpdated, `"${updated}"`);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed } = require('../../processor').support;
|
||||
const translators = require('../translators');
|
||||
const findRoot = require("find-root");
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
|
@ -18,63 +18,69 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const translator = parsed(context.getFilename());
|
||||
|
||||
if (!translator) return; // regular js source
|
||||
|
||||
if (node.body.length < 2) return; // no body?
|
||||
const header = translators.getHeaderFromAST(node);
|
||||
if (!header.body) return; // if there's no file header, assume it's not a translator
|
||||
if (!header.followingStatement) return; // if there's no following statement, there's more significant problems than just the license missing
|
||||
|
||||
const options = context.options[0];
|
||||
if (!options.mustMatch) throw new Error('license/mustMatch not set');
|
||||
if (!options.templateFile) throw new Error('license/templateFile not set');
|
||||
if (!options.mustMatch) throw new Error('mustMatch not set');
|
||||
|
||||
const license = context.getSourceCode().getAllComments().find((comment) => {
|
||||
return comment.type === 'Block' && comment.value.match(/(BEGIN LICENSE BLOCK[\s\S]+END LICENSE BLOCK)|(Copyright)/i);
|
||||
});
|
||||
let firstComment = null;
|
||||
let copyright = null;
|
||||
for (const comment of context.getSourceCode().getAllComments()) {
|
||||
if (comment.loc.start.line <= header.body.loc.end.line) continue; // skip decorator comments
|
||||
|
||||
if (!license) {
|
||||
const properties = translator.header.fields;
|
||||
const copyright = {
|
||||
holder: properties.creator || 'Zotero Contributors',
|
||||
period: `${(new Date).getFullYear()}`,
|
||||
};
|
||||
if (properties.lastUpdated) {
|
||||
const year = properties.lastUpdated.split('-')[0] || '';
|
||||
if (year && year !== copyright.period) copyright.period = `${year}-${copyright.period}`;
|
||||
if (comment.value.includes(options.mustMatch)) {
|
||||
if (firstComment || comment.loc.start.line > header.followingStatement.start.line) {
|
||||
context.report({
|
||||
loc: comment.loc,
|
||||
message: 'Preferred to have license block at the top'
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const templateFile = fs.existsSync(options.templateFile)
|
||||
? options.templateFile
|
||||
: path.resolve(path.join(findRoot(context.getFilename()), options.templateFile));
|
||||
if (!fs.existsSync(templateFile)) throw new Error(`cannot find ${templateFile}`);
|
||||
const template = fs.readFileSync(templateFile, 'utf-8');
|
||||
if (comment.value.match(/copyright/i)) {
|
||||
copyright = comment;
|
||||
}
|
||||
|
||||
const licenseText = '\n\n' + template.trim().replace(/\${(.*?)\}/g, (_, id) => {
|
||||
id = id.trim();
|
||||
return copyright[id] || `<undefined '${id}'>`;
|
||||
}) + '\n\n';
|
||||
context.report({
|
||||
message: 'Missing license block',
|
||||
loc: node.body[1].loc.start,
|
||||
fix: fixer => fixer.insertTextBefore(node.body[1], licenseText),
|
||||
});
|
||||
return;
|
||||
firstComment = firstComment || comment;
|
||||
}
|
||||
|
||||
if (node.body.length > 2 && node.body[1].loc.start.line < license.loc.start.line) {
|
||||
if (copyright) {
|
||||
context.report({
|
||||
loc: license.loc,
|
||||
message: 'Preferred to have license block at the top'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!license.value.match(new RegExp(options.mustMatch))) {
|
||||
context.report({
|
||||
loc: license.loc,
|
||||
loc: copyright.loc,
|
||||
message: `Copyright preferred to be ${options.mustMatch}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.templateFile) throw new Error('templateFile not set');
|
||||
const templateFile = fs.existsSync(options.templateFile)
|
||||
? options.templateFile
|
||||
: path.resolve(path.join(findRoot(context.getFilename()), options.templateFile));
|
||||
if (!fs.existsSync(templateFile)) throw new Error(`cannot find ${templateFile}`);
|
||||
const template = fs.readFileSync(templateFile, 'utf-8');
|
||||
|
||||
copyright = {
|
||||
holder: header.properties.creator ? header.properties.creator.value : null,
|
||||
period: `${(new Date).getFullYear()}`,
|
||||
};
|
||||
if (header.properties.lastUpdated) {
|
||||
const year = header.properties.lastUpdated.value.split('-')[0] || '';
|
||||
if (year && year !== copyright.period) copyright.period = `${year}-${copyright.period}`;
|
||||
}
|
||||
const licenseText = '\n\n' + template.trim().replace(/\${(.*?)\}/g, (_, id) => {
|
||||
id = id.trim();
|
||||
return copyright[id] || `<undefined '${id}'>`;
|
||||
}) + '\n\n';
|
||||
|
||||
context.report({
|
||||
node: header.followingStatement,
|
||||
message: "Missing license block",
|
||||
fix: (firstComment && firstComment.type === 'Block')
|
||||
? undefined
|
||||
: fixer => fixer.insertTextBefore(header.followingStatement, licenseText),
|
||||
});
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (_node) {
|
||||
Program: function (node) {
|
||||
let lineno = 0;
|
||||
for (const line of context.getSourceCode().getText().split('\n')) {
|
||||
lineno += 1;
|
||||
|
|
@ -20,6 +20,7 @@ module.exports = {
|
|||
const m = line.match(/for each *\(/);
|
||||
if (m) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Deprecated JavaScript 'for each' statement",
|
||||
loc: { start: { line: lineno, column: line.indexOf(m[0]) + 1 } },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const { parsed } = require('../../processor').support;
|
||||
const translators = require('../translators').cache;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -17,10 +17,11 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
if (process.platform == 'win32') return; // X_OK always succeeds on Windows
|
||||
const translator = translators.get(context.getFilename());
|
||||
|
||||
if (!translator.source) return; // only check translators
|
||||
|
||||
const filename = context.getFilename();
|
||||
if (!parsed(filename)) return; // only check translators
|
||||
|
||||
try {
|
||||
fs.accessSync(filename, fs.constants.X_OK);
|
||||
|
|
|
|||
|
|
@ -1,45 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
// this is a very simplistic rule to find 'unnecessary use of indexOf' until I find a better eslint plugin that does this
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'suggest alternative to unnecessary use of indexOf or search',
|
||||
description: 'suggest alternative to unnecessary use of indexOf',
|
||||
category: 'Stylistic Issues',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
"BinaryExpression > CallExpression:matches([callee.property.name='indexOf'], [callee.property.name='search'])[arguments.length=1]": (node) => {
|
||||
let source = context.getSourceCode();
|
||||
let binary = node.parent;
|
||||
if (
|
||||
(binary.operator.startsWith('==')
|
||||
|| binary.operator.startsWith('!=')
|
||||
|| binary.operator === '>') && source.getText(binary.right) === '-1'
|
||||
|| (binary.operator === '<' || binary.operator === '>=') && source.getText(binary.right) === '0'
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
message: node.callee.property.name === 'indexOf'
|
||||
? "Unnecessary '.indexOf()', use '.includes()' instead"
|
||||
: "Unnecessary '.search()', use 'RegExp#test()' instead",
|
||||
* fix(fixer) {
|
||||
let test = node.callee.property.name === 'indexOf'
|
||||
? `${source.getText(node.callee.object)}.contains(${source.getText(node.arguments[0])})`
|
||||
: `${source.getText(node.arguments[0])}.test(${source.getText(node.callee.object)})`;
|
||||
let positiveMatch = binary.operator.startsWith('!=')
|
||||
|| binary.operator === '>'
|
||||
|| binary.operator === '>=';
|
||||
if (!positiveMatch) {
|
||||
// This might produce unnecessary parens, but unfortunately it's the best we can do
|
||||
test = `!(${test})`;
|
||||
}
|
||||
yield fixer.replaceText(binary, test);
|
||||
}
|
||||
});
|
||||
Program: function (node) {
|
||||
let lineno = 0;
|
||||
for (const line of context.getSourceCode().getText().split('\n')) { // eslint-disable-line newline-per-chained-call
|
||||
lineno += 1;
|
||||
|
||||
const m = line.match(/\.indexOf(.*) *(=+ *-1|!=+ *-1|> *-1|>= *0|< *0)/);
|
||||
if (m) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Unnecessary '.indexOf()', use '.includes()' instead",
|
||||
loc: { start: { line: lineno, column: line.indexOf(m[0]) + 1 } },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'suggest',
|
||||
docs: {
|
||||
description: 'suggest alternatives to brittle querySelector() strings',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
"CallExpression:matches([callee.property.name=/querySelector(All)?/], [callee.name=/attr|text|innerText/])[arguments.0.type=Literal]": (node) => {
|
||||
let arg = node.arguments[0].raw;
|
||||
if (typeof arg !== 'string') {
|
||||
return;
|
||||
}
|
||||
let idRe = /\[id=(["'])([^"'.#\s]+)\1]/g;
|
||||
if (idRe.test(arg)) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Prefer #id over [id=\"id\"]",
|
||||
* fix(fixer) {
|
||||
yield fixer.replaceText(node.arguments[0], arg.replaceAll(idRe, "#$2"));
|
||||
}
|
||||
});
|
||||
}
|
||||
let classRe = /\[class=(["'])([^"'.#]+)\1]/g;
|
||||
if (classRe.test(arg)) {
|
||||
context.report({
|
||||
node,
|
||||
message: "Prefer .class over [class=\"class\"]",
|
||||
* fix(fixer) {
|
||||
yield fixer.replaceText(node.arguments[0],
|
||||
arg.replaceAll(classRe, (_, __, name) => `.${name.replaceAll(/\s+/g, '.')}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators').cache;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'disallow invalid JSON in test cases',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (_node) {
|
||||
const translator = translators.get(context.getFilename());
|
||||
|
||||
if (!translator.testCases) return; // regular js or no test cases
|
||||
|
||||
if (translator.testCases.error) {
|
||||
context.report({
|
||||
message: `Could not parse testCases: ${translator.testCases.error.message}`,
|
||||
loc: { start: { line: translator.testCases.error.line, column: translator.testCases.error.column } },
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,29 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed, json } = require('../../processor').support;
|
||||
|
||||
function zip(arrays) {
|
||||
let zipped = null;
|
||||
for (const [key, array] of Object.entries(arrays)) {
|
||||
if (!zipped) {
|
||||
zipped = Array(array.length).fill(null).map((_, i) => ({ _: i }));
|
||||
}
|
||||
else if (array.length !== zipped.length) {
|
||||
throw new Error(`Array length mismatch: ${key} has ${array.length} elements, but ${zipped.length} expected`);
|
||||
}
|
||||
for (const [i, value] of array.entries()) {
|
||||
zipped[i][key] = value;
|
||||
}
|
||||
}
|
||||
return zipped;
|
||||
}
|
||||
const translators = require('../translators').cache;
|
||||
const astUtils = require("eslint/lib/util/ast-utils");
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
|
||||
docs: {
|
||||
description: 'disallow invalid tests',
|
||||
description: 'disallow invalid test input',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
},
|
||||
|
|
@ -31,154 +16,79 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const translator = parsed(context.getFilename());
|
||||
if (!translator || !translator.testcases.text) return; // regular js source, or no testcases
|
||||
const translator = translators.get(context.getFilename());
|
||||
|
||||
const err = json.try(translator.testcases.text, { line: translator.testcases.start, position: 3 });
|
||||
if (err) {
|
||||
context.report({
|
||||
message: `Could not parse testcases: ${err.message}`,
|
||||
loc: { start: { line: err.line, column: err.column } },
|
||||
});
|
||||
return;
|
||||
const declaration = node.body.find(node => node.type === 'VariableDeclaration' && node.declarations.length === 1 && node.declarations[0].id.name === 'testCases');
|
||||
const testCases = declaration
|
||||
&& declaration.declarations[0].init
|
||||
&& declaration.declarations[0].init.type === 'ArrayExpression'
|
||||
? declaration.declarations[0].init.elements
|
||||
: [];
|
||||
|
||||
if (declaration) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
if (astUtils.isSemicolonToken(sourceCode.getLastToken(node))) {
|
||||
context.report({
|
||||
message: 'testcases should not have trailing semicolon',
|
||||
loc: declaration.loc.end,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const declaration = node.body.find(node => (
|
||||
node.type === 'VariableDeclaration'
|
||||
&& node.declarations.length === 1
|
||||
&& node.declarations[0].id.name === 'testCases'
|
||||
));
|
||||
if (declaration.followingStatement) {
|
||||
context.report({
|
||||
node: declaration.followingStatement,
|
||||
message: 'testCases should not have trailing code',
|
||||
});
|
||||
}
|
||||
if (!translator.testCases || translator.testCases.error) return; // regular js or no test cases
|
||||
|
||||
const nodes = declaration.declarations[0].init.elements;
|
||||
if (!Array.isArray(nodes)) {
|
||||
context.report({
|
||||
node: declaration,
|
||||
message: 'testCases must be an array',
|
||||
});
|
||||
return;
|
||||
}
|
||||
let caseNo = -1;
|
||||
for (const testCase of translator.testCases.parsed) {
|
||||
caseNo += 1;
|
||||
const prefix = `test case${testCases[caseNo] ? '' : ' ' + (caseNo + 1)}`;
|
||||
const loc = testCases[caseNo] ? testCases[caseNo].loc.start : { start: { line: translator.testCases.start, column: 1 } };
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
const token = sourceCode.getLastToken(node);
|
||||
if (token.type === 'Punctuator' && token.value === ';') {
|
||||
context.report({
|
||||
message: 'testCases should not have trailing semicolon',
|
||||
loc: declaration.loc.end,
|
||||
});
|
||||
}
|
||||
|
||||
zip({
|
||||
testCase: JSON.parse(translator.testcases.text),
|
||||
node: nodes,
|
||||
})
|
||||
.forEach(({ testCase, node }) => {
|
||||
if (!['web', 'import', 'search'].includes(testCase.type)) {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case has invalid type "${testCase.type}"`,
|
||||
message: `${prefix} has invalid type "${testCase.type}"`,
|
||||
loc,
|
||||
});
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(Array.isArray(testCase.items) || (testCase.type === 'web' && testCase.items === 'multiple'))) {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs items`,
|
||||
message: `${prefix} of type "${testCase.type}" needs items`,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
|
||||
if (testCase.type === 'web' && typeof testCase.url !== 'string') {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" test needs url`,
|
||||
message: `${prefix} of type "${testCase.type}" test needs url`,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
|
||||
if (['import', 'search'].includes(testCase.type) && !testCase.input) {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs a string input`,
|
||||
message: `${prefix} of type "${testCase.type}" needs a string input`,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
else if (testCase.type === 'import' && typeof testCase.input !== 'string') {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs input`,
|
||||
message: `${prefix} of type "${testCase.type}" needs input`,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
else if (testCase.type === 'search') {
|
||||
// console.log(JSON.stringify(testCase.input))
|
||||
const expected = ['DOI', 'ISBN', 'PMID', 'arXiv', 'identifiers', 'contextObject', 'adsBibcode', 'ericNumber', 'openAlex'];
|
||||
let keys;
|
||||
if (Array.isArray(testCase.input)) {
|
||||
keys = testCase.input.flatMap(Object.keys);
|
||||
}
|
||||
else {
|
||||
keys = Object.keys(testCase.input);
|
||||
}
|
||||
if (!keys.every(key => expected.includes(key))) {
|
||||
const invalidKey = keys.find(key => !expected.includes(key));
|
||||
const term = Object.keys(testCase.input).join('/');
|
||||
const expected = ['DOI', 'ISBN', 'PMID', 'identifiers', 'contextObject'];
|
||||
if (!expected.includes(term)) {
|
||||
context.report({
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" has invalid search term '${invalidKey}' - expected one of ${expected.join(', ')}`,
|
||||
message: `${prefix} of type "${testCase.type}" has search term '${term}', expected one of ${expected.join(', ')}`,
|
||||
loc,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(testCase.items)) {
|
||||
zip({
|
||||
item: testCase.items,
|
||||
node: node.properties.find(prop => prop.key.type === 'Literal' && prop.key.value === 'items').value.elements,
|
||||
})
|
||||
.forEach(({ item, node }) => {
|
||||
if (!Array.isArray(item.creators)) {
|
||||
context.report({
|
||||
message: 'creators should be an array',
|
||||
node,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
zip({
|
||||
creator: item.creators,
|
||||
node: node.properties.find(prop => prop.key.type === 'Literal' && prop.key.value === 'creators').value.elements,
|
||||
})
|
||||
.forEach(({ creator, node }) => {
|
||||
if (creator.fieldMode !== undefined && creator.fieldMode !== 1) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator.fieldMode should be omitted or 1',
|
||||
});
|
||||
}
|
||||
else if (creator.fieldMode === 1 && (creator.firstName || !creator.lastName)) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator with fieldMode == 1 should have lastName and no firstName',
|
||||
});
|
||||
}
|
||||
else if (!creator.firstName && !creator.lastName) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator has no name',
|
||||
});
|
||||
}
|
||||
|
||||
if (!creator.creatorType) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator has no creatorType',
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const { parsed } = require('../../processor').support;
|
||||
const translators = require('../translators');
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -14,14 +14,19 @@ module.exports = {
|
|||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (_node) {
|
||||
const translator = parsed(context.getFilename());
|
||||
if (!translator || !translator.FW) return; // regular js source, or no FW present
|
||||
Program: function (node) {
|
||||
const header = translators.getHeaderFromAST(node);
|
||||
if (!header.body) return; // if there's no file header, assume it's not a translator
|
||||
|
||||
context.report({
|
||||
loc: translator.FW.loc,
|
||||
message: 'uses deprecated Translator Framework'
|
||||
});
|
||||
const sourceCode = context.getSourceCode();
|
||||
for (const comment of sourceCode.getAllComments()) {
|
||||
if (comment.value.match(/^\s*FW LINE [0-9]+:/)) {
|
||||
context.report({
|
||||
loc: comment.loc,
|
||||
message: 'uses deprecated Translator Framework'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const translators = require('../translators').cache;
|
||||
const getHeaderFromAST = require('../translators').getHeaderFromAST;
|
||||
|
||||
const deleted = new Set(
|
||||
fs.readFileSync(path.join(translators.repo, 'deleted.txt'), 'utf-8')
|
||||
.split('\n')
|
||||
.map(line => line.split(' ')[0])
|
||||
.filter(id => id && id.indexOf('-') > 0)
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'disallows translatorID re-use',
|
||||
category: 'Potential Problems',
|
||||
},
|
||||
fixable: 'code',
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const filename = context.getFilename();
|
||||
const header = getHeaderFromAST(node);
|
||||
if (!header.declaration) return;
|
||||
|
||||
if (!header.properties.translatorID) {
|
||||
context.report({
|
||||
node: header.declaration,
|
||||
message: 'Header has no translator ID',
|
||||
});
|
||||
}
|
||||
else if (deleted.has(header.properties.translatorID.value)) {
|
||||
context.report({
|
||||
node: header.properties.translatorID,
|
||||
message: 'Header re-uses translator ID of deleted translator',
|
||||
fix: function (fixer) {
|
||||
return fixer.replaceText(header.properties.translatorID, `"${uuid()}"`);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (!header.properties.translatorID.value) {
|
||||
context.report({
|
||||
node: header.properties.translatorID,
|
||||
message: 'Header has empty translator ID',
|
||||
});
|
||||
}
|
||||
else {
|
||||
const conflict = translators.conflicts(filename, header.properties.translatorID.value);
|
||||
if (conflict) {
|
||||
const translator = translators.get(filename);
|
||||
context.report({
|
||||
node: header.properties.translatorID,
|
||||
message: `Header re-uses translator ID of ${conflict.label}`,
|
||||
fix: !translator.modified ? undefined : (fixer => fixer.replaceText(header.properties.translatorID, `"${uuid()}"`)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
|
||||
const getHeaderFromAST = require('../translators').getHeaderFromAST;
|
||||
|
||||
function getFunction(programNode, name) {
|
||||
return programNode.body.find((node) => {
|
||||
if (node.type === 'FunctionDeclaration' && node.id && node.id.name === name) return true;
|
||||
if (node.type === 'VariableDeclaration'
|
||||
&& node.declarations.length === 1
|
||||
&& node.declarations[0].id.name === name
|
||||
&& node.declarations[0].init
|
||||
&& node.declarations[0].init.type === 'FunctionExpression'
|
||||
) return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'enforce translatorType against handler functions',
|
||||
category: 'Possible Errors',
|
||||
},
|
||||
},
|
||||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const header = getHeaderFromAST(node);
|
||||
if (!header.declaration) return;
|
||||
|
||||
const type = {
|
||||
import: 1,
|
||||
export: 2,
|
||||
web: 4,
|
||||
search: 8
|
||||
};
|
||||
|
||||
let translatorTypeNode = header.declaration;
|
||||
let translatorType = 0;
|
||||
let browserSupportNode = null;
|
||||
for (const [p, v] of Object.entries(header.properties)) {
|
||||
switch (p) {
|
||||
case 'translatorType':
|
||||
translatorTypeNode = v;
|
||||
translatorType = v.value;
|
||||
break;
|
||||
case 'browserSupport':
|
||||
browserSupportNode = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (browserSupportNode && !(translatorType & type.web)) context.report(browserSupportNode, `browserSupport set, but translatorType (${translatorType}) does not include web (${type.web})`);
|
||||
|
||||
for (const name of ['detectWeb', 'doWeb', 'detectImport', 'doImport', 'doExport']) {
|
||||
const handler = getFunction(node, name);
|
||||
const mode = name.replace(/^(detect|do)/, '').toLowerCase();
|
||||
const bit = type[mode];
|
||||
if (handler && !(translatorType & bit)) {
|
||||
context.report(handler, `${name} present, but translatorType (${translatorType}) does not specify ${mode} (${bit})`);
|
||||
}
|
||||
if (!handler && (translatorType & bit)) {
|
||||
context.report(translatorTypeNode, `translatorType specifies ${mode} (${bit}), but no ${name} present`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const findRoot = require('find-root');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
const repo = path.resolve(findRoot(__dirname, dir => fs.existsSync(path.resolve(dir, '.git'))));
|
||||
|
||||
const metaDataRules = [
|
||||
'zotero-translator/header-valid-json',
|
||||
'zotero-translator/last-updated',
|
||||
'zotero-translator/translator-id',
|
||||
'zotero-translator/test-cases-valid-json',
|
||||
'zotero-translator/test-cases',
|
||||
'zotero-translator/translator-type',
|
||||
'zotero-translator/prefer-index-of',
|
||||
'zotero-translator/no-for-each',
|
||||
'zotero-translator/not-executable',
|
||||
'indent',
|
||||
].join(', ');
|
||||
|
||||
const headerVar = '__eslintZoteroTranslatorHeader';
|
||||
const headerPrefix = `/* eslint-disable no-unused-vars */ const ${headerVar} = /* eslint-disable */(/* eslint-enable ${metaDataRules} */`;
|
||||
|
||||
function jsonParseWithErrorInfo(raw, source) {
|
||||
const target = { raw };
|
||||
target.lines = target.raw.split('\n').length;
|
||||
|
||||
try {
|
||||
target.parsed = JSON.parse(target.raw);
|
||||
}
|
||||
catch (err) {
|
||||
const position = err.message.match(/at position ([0-9]+)/);
|
||||
const at = position ? parseInt(position[1]) : 0;
|
||||
target.error = {
|
||||
message: err.message,
|
||||
line: source.substring(0, source.indexOf(raw)).split('\n').length // start of raw JSON
|
||||
+ target.raw.substring(0, at).split('\n').length, // line within raw JSON
|
||||
column: at - target.raw.lastIndexOf('\n', at),
|
||||
};
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
function escapeRE(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
const re = {
|
||||
undecorated: new RegExp(
|
||||
/^(\{[\s\S]+?\n\})/.source // the header
|
||||
+ /(\n[\s\S]+?)/.source // the code
|
||||
+ '(?:' // test cases
|
||||
+ /(\/\*\* BEGIN TEST CASES \*\*\/)([\s\S]+?)/.source // var testCases =
|
||||
+ /(\[[\s\S]+\])/.source // the test cases
|
||||
+ /([\s\S]+)/.source // trailing stuff after the test cases
|
||||
+ ')?$' // test cases are optional
|
||||
),
|
||||
|
||||
decorated: new RegExp(
|
||||
/^([\s\S]*?)/.source // anything the fixer might have placed at the top
|
||||
+ escapeRE(headerPrefix) // all the eslint junk we injected
|
||||
+ /(\{[\s\S]+\})/.source // the header
|
||||
+ escapeRE(');/* eslint-enable */') // more eslint stuff we injected
|
||||
+ /([\s\S]+?)/.source // the code
|
||||
+ '(?:' // optional test cases
|
||||
+ /(\/\*\* BEGIN TEST CASES \*\*\/)/.source
|
||||
+ escapeRE('/* eslint-disable */') // more eslint stuff we injected
|
||||
+ /([\s\S]+?)/.source // var testCases =
|
||||
+ escapeRE(`/* eslint-enable ${metaDataRules} */`)
|
||||
+ /([\s\S]+)/.source
|
||||
+ ')?$'
|
||||
),
|
||||
};
|
||||
|
||||
const tfw = {
|
||||
rules: [
|
||||
'block-spacing',
|
||||
'brace-style',
|
||||
'comma-spacing',
|
||||
'consistent-return',
|
||||
'consistent-this',
|
||||
'key-spacing',
|
||||
'keyword-spacing',
|
||||
'no-array-constructor',
|
||||
'no-cond-assign',
|
||||
'no-new-object',
|
||||
'no-sequences',
|
||||
'no-undef',
|
||||
'no-unused-expressions',
|
||||
'no-void',
|
||||
'object-curly-spacing',
|
||||
'semi',
|
||||
'semi-spacing',
|
||||
'space-before-blocks',
|
||||
'space-before-function-paren',
|
||||
'space-infix-ops',
|
||||
]
|
||||
};
|
||||
tfw.disable = ` // eslint-disable-line ${tfw.rules.join(', ')}`;
|
||||
tfw.disableRe = new RegExp('(\\n' + escapeRE('/* FW LINE 59:b820c6d */') + '[^\\n]+?)(' + escapeRE(tfw.disable) + ')?(\\n)');
|
||||
|
||||
function decorate(source) {
|
||||
const decorated = {};
|
||||
|
||||
if (!source.startsWith('{')) return decorated;
|
||||
|
||||
let m = source.match(re.undecorated);
|
||||
if (!m) throw new Error('no header');
|
||||
|
||||
let [, header, code, testCasesPrefix, testCasesVar, testCases, testCasesPostfix] = m;
|
||||
|
||||
code = code.replace(tfw.disableRe, `$1${tfw.disable}$3`);
|
||||
|
||||
// decorate header
|
||||
decorated.header = jsonParseWithErrorInfo(header, source);
|
||||
|
||||
decorated.source = headerPrefix
|
||||
+ header // the JSON
|
||||
+ ');/* eslint-enable */'
|
||||
+ code; // the actual code
|
||||
|
||||
if (testCasesPrefix) {
|
||||
decorated.testCases = jsonParseWithErrorInfo(testCases, source);
|
||||
|
||||
decorated.source += testCasesPrefix // the prefix
|
||||
+ '/* eslint-disable */' // disable all the rules
|
||||
+ testCasesVar
|
||||
+ `/* eslint-enable ${metaDataRules} */` // enable JSON rules
|
||||
+ testCases
|
||||
+ testCasesPostfix;
|
||||
}
|
||||
|
||||
return decorated;
|
||||
}
|
||||
|
||||
function tryFormatJSON(raw) {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(raw), null, '\t');
|
||||
}
|
||||
catch (_err) {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
function strip(source) {
|
||||
const m = source.match(re.decorated);
|
||||
if (!m) throw new Error('not decorated');
|
||||
|
||||
let [, prefix, header, code, testCasesPrefix, testCasesVar, testCases] = m;
|
||||
|
||||
code = code.replace(tfw.disableRe, '$1$3');
|
||||
|
||||
return tryFormatJSON(header) + (prefix ? '\n\n' + prefix.replace(/^\s*/, '') : '') + code + (testCasesPrefix || '') + tryFormatJSON(testCasesVar || '') + (testCases || '');
|
||||
}
|
||||
|
||||
function exec(cmd) {
|
||||
return childProcess.execSync(cmd, { cwd: repo, encoding: 'utf8' });
|
||||
}
|
||||
|
||||
class Cache {
|
||||
constructor() {
|
||||
this.decorated = {};
|
||||
|
||||
this.repo = path.resolve(repo);
|
||||
for (const translator of fs.readdirSync(this.repo)) {
|
||||
if (!translator.endsWith('.js')) continue;
|
||||
this.decorated[path.basename(translator)] = decorate(fs.readFileSync(path.join(repo, translator), 'utf-8'));
|
||||
}
|
||||
|
||||
const branch = exec('git rev-parse --abbrev-ref HEAD').trim();
|
||||
|
||||
const hasUpstream = exec('git remote -v').split('\n')
|
||||
.map(line => line.trim())
|
||||
.includes('upstream\thttps://github.com/zotero/translators.git');
|
||||
// branch to compare lastUpdated against -- assume that if have upstream/master, you want to compare against that
|
||||
const master = hasUpstream ? 'upstream/master' : 'master';
|
||||
|
||||
this.lastUpdated = {};
|
||||
if (branch !== master) {
|
||||
// `git diff --name-status ${master}` will fetch the names of the files that have changed against `${master}`
|
||||
for (const file of exec(`git diff --name-status ${master}`).split('\n')) {
|
||||
const m = file.match(/^M\t([^/]+\.js)$/); // js files that are modified but don't have a / in their path to pick out files in the root
|
||||
if (m && this.decorated[m[1]]) this.decorated[m[1]].modified = true;
|
||||
}
|
||||
|
||||
/*
|
||||
We do a `git grep '"lastUpdated"' ${master} *.js` to get the
|
||||
`lastUpdated` values from the `${master}` branch. For files that are
|
||||
deemed changed, the lastUpdated is remembered (so the presence of lastUpdated implies modified).
|
||||
This info is used in the 'last-updated' rule.
|
||||
*/
|
||||
for (const lu of exec(`git grep '"lastUpdated"' ${master} *.js`).split('\n')) {
|
||||
const m = lu.match(/^[a-z/]+:([^:]+):\s*"lastUpdated"\s*:\s*"([-0-9: ]+)"/);
|
||||
if (!m) continue;
|
||||
const translator = m[1];
|
||||
if (this.decorated[translator] && this.decorated[translator].modified) this.decorated[translator].lastUpdated = m[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get(filename) {
|
||||
const basename = path.basename(filename);
|
||||
|
||||
// don't load stuff outside the root dir
|
||||
if (!this.decorated[basename] && path.dirname(path.resolve(filename)) !== this.repo) this.decorated[basename] = {};
|
||||
|
||||
return this.decorated[basename];
|
||||
}
|
||||
|
||||
conflicts(filename, translatorID) {
|
||||
filename = path.basename(filename);
|
||||
for (const [otherFilename, otherHeader] of Object.entries(this.decorated)) {
|
||||
if (otherFilename !== filename && otherHeader.translatorID === translatorID) {
|
||||
return otherHeader.parsed;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getHeaderFromAST(programNode) {
|
||||
const declaration = programNode.body[0];
|
||||
if (!declaration) return {};
|
||||
if (declaration.type !== 'VariableDeclaration' || declaration.declarations.length !== 1 || declaration.declarations[0].id.name !== headerVar) return {};
|
||||
|
||||
const body = declaration.declarations[0].init;
|
||||
if (!body || body.type !== 'ObjectExpression') return {};
|
||||
|
||||
const properties = {};
|
||||
for (const property of body.properties) {
|
||||
properties[property.key.value] = property.value;
|
||||
}
|
||||
return { declaration, body, properties, followingStatement: programNode.body[1] };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
decorate,
|
||||
strip,
|
||||
cache: new Cache(),
|
||||
getHeaderFromAST,
|
||||
};
|
||||
|
||||
if (require.main === module) {
|
||||
const orig = fs.readFileSync(path.join(__dirname, '../../../Amazon.js'), 'utf-8');
|
||||
const decorated = decorate(orig);
|
||||
const stripped = strip(decorated.source);
|
||||
console.log(stripped === orig); // eslint-disable-line no-console
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
{
|
||||
"name": "eslint-plugin-zotero-translator",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "eslint-plugin-zotero-translator",
|
||||
"version": "0.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"commander": "^2.19.0",
|
||||
"find-root": "^1.1.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"require-dir": "^1.2.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"bin": {
|
||||
"teslint": "bin/teslint.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/find-root": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/recursive-readdir": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
||||
"integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
|
||||
"dependencies": {
|
||||
"minimatch": "^3.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-dir": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/require-dir/-/require-dir-1.2.0.tgz",
|
||||
"integrity": "sha512-LY85DTSu+heYgDqq/mK+7zFHWkttVNRXC9NKcKGyuGLdlsfbjEPrIEYdCVrx6hqnJb+xSu3Lzaoo8VnmOhhjNA==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"find-root": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"recursive-readdir": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
||||
"integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.5"
|
||||
}
|
||||
},
|
||||
"require-dir": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/require-dir/-/require-dir-1.2.0.tgz",
|
||||
"integrity": "sha512-LY85DTSu+heYgDqq/mK+7zFHWkttVNRXC9NKcKGyuGLdlsfbjEPrIEYdCVrx6hqnJb+xSu3Lzaoo8VnmOhhjNA=="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
"author": "Emiliano Heyns",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
"dependencies": {
|
||||
"commander": "^2.19.0",
|
||||
"find-root": "^1.1.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"recursive-readdir-synchronous": "0.0.4",
|
||||
"require-dir": "^1.2.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,257 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const espree = require('espree');
|
||||
const clarinet = require('clarinet');
|
||||
const findRoot = require('find-root');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
let repo;
|
||||
try {
|
||||
repo = path.resolve(findRoot(__dirname, dir => fs.existsSync(path.join(dir, '.git'))));
|
||||
}
|
||||
catch (e) {
|
||||
console.error('ERROR: Translators can only be linted inside a clone of the zotero/translators repo (not a ZIP downloaded from GitHub)');
|
||||
console.error(' git clone https://github.com/zotero/translators.git');
|
||||
process.exit(1); // eslint-disable-line no-process-exit
|
||||
}
|
||||
|
||||
function exec(cmd) {
|
||||
return childProcess.execSync(cmd, { cwd: repo, encoding: 'utf8' });
|
||||
}
|
||||
|
||||
// have to pre-load everything to test for conflicting headers
|
||||
const cache = new Map();
|
||||
|
||||
function updateCache(text, filename) {
|
||||
if (text[0] !== '{') return;
|
||||
if (cache.has(filename) && cache.get(filename).text === text) {
|
||||
// No change - no need to re-parse
|
||||
return;
|
||||
}
|
||||
|
||||
// detect header
|
||||
const prefix = `const ZoteroTranslator${Date.now()} = `;
|
||||
const decorated = `${prefix}${text}`;
|
||||
let ast;
|
||||
try {
|
||||
ast = espree.parse(decorated, { comment: true, loc: true, ecmaVersion: 2023 });
|
||||
}
|
||||
catch (err) {
|
||||
console.log(filename, err.message);
|
||||
process.exit(1); // eslint-disable-line no-process-exit
|
||||
}
|
||||
|
||||
const header = ((ast.body[0] || {}).declarations[0] || {}).init;
|
||||
const testcases = ast.body
|
||||
.filter((node, i) => i === ast.body.length - 1)
|
||||
.filter(node => node.type === 'VariableDeclaration' && node.declarations.length === 1).map(node => node.declarations[0])
|
||||
.filter(node => node.type === 'VariableDeclarator' && node.id.type === 'Identifier' && node.id.name === 'testCases')
|
||||
.map(node => node.init)[0];
|
||||
|
||||
const extract = (node) => {
|
||||
if (!node) return {};
|
||||
return {
|
||||
start: node.loc.start.line,
|
||||
end: node.loc.end.line,
|
||||
text: decorated.substring(node.start, node.end),
|
||||
};
|
||||
};
|
||||
|
||||
const entry = {
|
||||
text,
|
||||
header: extract(header),
|
||||
testcases: extract(testcases),
|
||||
FW: ast.comments.find(comment => comment.type === 'Block' && comment.value.trim === 'FW LINE 59:b820c6d')
|
||||
};
|
||||
|
||||
try {
|
||||
entry.header.fields = JSON.parse(entry.header.text);
|
||||
}
|
||||
catch (err) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
cache.set(filename, entry);
|
||||
}
|
||||
|
||||
for (let filename of fs.readdirSync(repo).sort()) {
|
||||
if (!filename.endsWith('.js')) continue;
|
||||
filename = path.join(repo, filename);
|
||||
|
||||
const text = fs.readFileSync(filename, 'utf-8');
|
||||
updateCache(text, filename);
|
||||
}
|
||||
|
||||
for (const lu of exec(`git grep '"lastUpdated"' HEAD~1`).split('\n')) {
|
||||
const m = lu.match(/^HEAD~1:([^:]+):\s*"lastUpdated"\s*:\s*"([-0-9: ]+)"/);
|
||||
if (!m) continue;
|
||||
const [, translator, lastUpdated] = m;
|
||||
const filename = path.join(repo, translator);
|
||||
if (cache.has(filename)) cache.get(filename).lastUpdated = lastUpdated;
|
||||
}
|
||||
|
||||
function tryJSON(json, offset) {
|
||||
const parser = clarinet.parser();
|
||||
let error;
|
||||
|
||||
const message = e => ({
|
||||
message: (e.message || '').split('\n', 1)[0],
|
||||
line: parser.line + offset.line,
|
||||
column: parser.column,
|
||||
position: parser.position + offset.position,
|
||||
});
|
||||
|
||||
// trigger the parse error
|
||||
parser.onerror = function (e) {
|
||||
error = message(e);
|
||||
parser.close();
|
||||
};
|
||||
|
||||
try {
|
||||
parser.write(json).close();
|
||||
}
|
||||
catch (e) {
|
||||
return error || message(e);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
function JSONTokens(json, offset) {
|
||||
const parser = clarinet.parser();
|
||||
const tokens = [];
|
||||
|
||||
parser.onvalue = function (v) {
|
||||
tokens.push({ type: 'value', value: v, line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
parser.onopenobject = function (key) {
|
||||
tokens.push({ type: 'object-open', key, line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
parser.onkey = function (key) {
|
||||
tokens.push({ type: 'key', key, line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
parser.oncloseobject = function () {
|
||||
tokens.push({ type: 'object-close', line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
parser.onopenarray = function () {
|
||||
tokens.push({ type: 'array-open', line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
parser.onclosearray = function () {
|
||||
tokens.push({ type: 'array-close', line: parser.line + offset.line, column: parser.column, position: parser.position + offset.position });
|
||||
};
|
||||
|
||||
parser.write(json).close();
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function header(program) {
|
||||
if (!program) return null;
|
||||
if (program.type !== 'Program') return null;
|
||||
if (program.body.length === 0) return null;
|
||||
if (program.body[0].type !== 'ExpressionStatement') return null;
|
||||
if (program.body[0].expression.type !== 'ObjectExpression') return null;
|
||||
return program.body[0].expression;
|
||||
}
|
||||
|
||||
function conflict(filename) {
|
||||
const translatorID = (((cache.get(filename) || {}).header || {}).fields || {}).translatorID;
|
||||
if (!translatorID) return null;
|
||||
for (const [other, header] of cache.entries()) {
|
||||
if (other !== filename && header.translatorID === translatorID) {
|
||||
return header.fields;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const junk = new RegExp(`${path.sep}0_`.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + '.*');
|
||||
module.exports = {
|
||||
support: {
|
||||
repo,
|
||||
parsed: filename => cache.get(filename.replace(junk, '')),
|
||||
header,
|
||||
IDconflict: conflict,
|
||||
json: {
|
||||
try: tryJSON,
|
||||
tokens: JSONTokens,
|
||||
}
|
||||
},
|
||||
|
||||
supportsAutofix: true,
|
||||
|
||||
preprocess: function (text, filename) {
|
||||
// We might be running on an in-memory version of the translator newer
|
||||
// than what we read from disk earlier, so update the cache
|
||||
updateCache(text, filename);
|
||||
|
||||
const parsed = cache.get(filename);
|
||||
if (text[0] !== '{' || !parsed) return [{ text, filename }];
|
||||
|
||||
if (parsed.header.text) {
|
||||
return [{ text: `(${text.slice(0, parsed.header.text.length)});${text.slice(parsed.header.text.length)}`, filename }];
|
||||
}
|
||||
else {
|
||||
return [{ text, filename }];
|
||||
}
|
||||
},
|
||||
|
||||
postprocess: function (messages, filename) {
|
||||
messages = [].concat(...messages);
|
||||
|
||||
const parsed = cache.get(filename);
|
||||
|
||||
if (parsed) {
|
||||
const header = parsed.header;
|
||||
if (header.text) {
|
||||
messages = messages.filter((m) => {
|
||||
if (!m.ruleId) return true;
|
||||
if (m.ruleId.startsWith('zotero-translator/header') && m.line > header.end) return false;
|
||||
switch (m.ruleId) {
|
||||
case 'no-unused-expressions':
|
||||
return m.line !== 1;
|
||||
case 'quote-props':
|
||||
return m.line > header.end;
|
||||
default:
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const adjust = (p) => {
|
||||
if (p > header.text.length) return p - 3; // remove '(' and ');'
|
||||
if (p > 1) return p - 1; // remove '('
|
||||
return p;
|
||||
};
|
||||
for (const m of messages) {
|
||||
if (m.fix) m.fix.range = m.fix.range.map(adjust);
|
||||
if (m.suggestions) {
|
||||
for (const s of m.suggestions) {
|
||||
if (s.fix) s.fix.range = s.fix.range.map(adjust);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const testcases = parsed.testcases;
|
||||
if (testcases && testcases.text) {
|
||||
messages = messages.filter((m) => {
|
||||
if (!m.ruleId) return true;
|
||||
if (m.ruleId.startsWith('zotero-translator/test-cases') && m.line < testcases.start) return false;
|
||||
|
||||
switch (m.ruleId) {
|
||||
case 'semi':
|
||||
case 'quote-props':
|
||||
return m.line < testcases.start || m.line > testcases.end;
|
||||
case 'lines-around-comment':
|
||||
return m.line !== testcases.end + 1;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return messages;
|
||||
},
|
||||
};
|
||||
|
|
@ -19,11 +19,41 @@ get_translator_id() {
|
|||
}
|
||||
|
||||
get_translators_to_check() {
|
||||
# Get the last commit on the target branch before this branch diverged
|
||||
# Fall back to translators changed on the last commit in case there's no GITHUB_BASE_REF
|
||||
# and no upstream/master (CI runs on push)
|
||||
local fork_point=$(git merge-base --fork-point ${GITHUB_BASE_REF:-upstream/master} HEAD 2>/dev/null || echo HEAD~)
|
||||
# Get translator scripts changed between that commit and now, excluding deleted files
|
||||
local all_translator_scripts="$(git rev-parse --show-toplevel)"/*.js
|
||||
git diff --name-only --diff-filter=d $fork_point -- $all_translator_scripts
|
||||
# If a PR branch has no conflicts with the master then git
|
||||
# creates a custom merge commit where it merges PR into master.
|
||||
# Travis-CI tests on that commit instead of the HEAD of the PR branch.
|
||||
#
|
||||
# Thus below we first determine if HEAD is a merge commit by checking how
|
||||
# many parents the current HEAD has. If number of parents > 1, then it's a merge commit
|
||||
# in which case we need to diff translator names between HEAD^2 and PR split commit from master.
|
||||
# The above will generally only be the case in CI or if using a custom PR pulling script which
|
||||
# pulls the merge PR commit instead of just the PR branch.
|
||||
#
|
||||
# If the HEAD commit is not a merge then we diff HEAD with PR split commit from master. This is the case
|
||||
# when running from a local development PR branch
|
||||
#
|
||||
# The branching point hash retrieval logic is based on https://stackoverflow.com/a/12185115/3199106
|
||||
|
||||
TRANSLATORS_TO_CHECK=""
|
||||
|
||||
# Push to master
|
||||
if [ "${GITHUB_REF:-}" = "refs/heads/master" ]; then
|
||||
before_commit=$(jq -r '.before' $(echo $GITHUB_EVENT_PATH))
|
||||
TRANSLATORS_TO_CHECK=$(git diff $before_commit --name-only | { grep -e "^[^/]*.js$" || true; })
|
||||
# Pull request
|
||||
else
|
||||
# Gets parent commits. Either one or two hashes
|
||||
parent_commits=($(git show --no-patch --format="%P" HEAD))
|
||||
# Size of $parent_commits array
|
||||
num_parent_commits=${#parent_commits[@]}
|
||||
if [ $num_parent_commits -gt 1 ]; then
|
||||
first_parent=$(git rev-list --first-parent ^master HEAD^2 | tail -n1)
|
||||
branch_point=$(git rev-list "$first_parent^^!")
|
||||
TRANSLATORS_TO_CHECK=$(git diff HEAD^2 $branch_point --name-only | { grep -e "^[^/]*.js$" || true; })
|
||||
else
|
||||
first_parent=$(git rev-list --first-parent ^master HEAD | tail -n1)
|
||||
branch_point=$(git rev-list "$first_parent^^!")
|
||||
TRANSLATORS_TO_CHECK=$(git diff $branch_point --name-only | { grep -e "^[^/]*.js$" || true; })
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,5 @@ dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||
|
||||
. "$dir/helper.sh"
|
||||
|
||||
translators_to_check=$(get_translators_to_check)
|
||||
if [ -n "$translators_to_check" ]; then
|
||||
# No `xargs -d` support in macOS, so workaround with `tr`
|
||||
echo "$translators_to_check" | tr '\n' '\0' | xargs -0 npm run lint --
|
||||
fi
|
||||
get_translators_to_check
|
||||
npm run lint -- "$TRANSLATORS_TO_CHECK"
|
||||
|
|
|
|||
|
|
@ -1,164 +0,0 @@
|
|||
import chalk from 'chalk';
|
||||
import path from 'path';
|
||||
import process from 'process';
|
||||
import { chromium } from 'playwright';
|
||||
import * as translatorServer from './translator-server.mjs';
|
||||
|
||||
const chromeExtensionDir = path.join(import.meta.dirname, 'connectors', 'build', 'manifestv3');
|
||||
const KEEP_BROWSER_OPEN = 'KEEP_BROWSER_OPEN' in process.env;
|
||||
const CI = 'CI' in process.env;
|
||||
const ZOTERO_CONNECTOR_EXTENSION_ID = 'ekhagklcjbdpajgpjgmbionohlpdbjgc';
|
||||
|
||||
async function getTranslatorsToTest() {
|
||||
const translatorFilenames = process.argv[2].split('\n').filter(filename => filename.trim().length > 0);
|
||||
let changedTranslatorIDs = [];
|
||||
let toTestTranslatorIDs = new Set();
|
||||
let toTestTranslatorNames = new Set();
|
||||
for (const translatorFilename of translatorFilenames) {
|
||||
let translator = translatorServer.filenameToTranslator[translatorFilename];
|
||||
if (!translator) {
|
||||
console.error(chalk.yellow(`Translator '${translatorFilename}' not found`));
|
||||
continue;
|
||||
}
|
||||
else if (translator.metadata === null) {
|
||||
console.error(chalk.red(`
|
||||
Translator '${translatorFilename}' is not correctly formatted.
|
||||
|
||||
Please use Scaffold (Tools → Translator Editor) to create translators, and test
|
||||
that your translator works before opening a PR.
|
||||
|
||||
AI tools may help with drafting code to add to your translator, but you should
|
||||
never use an AI tool to generate its overall structure without using Scaffold
|
||||
first. LLMs have very little Zotero translator code in their training sets and
|
||||
generally fail to generate translator code with a valid layout (or even a real
|
||||
UUID).
|
||||
`.trim()));
|
||||
continue;
|
||||
}
|
||||
let metadata = translator.metadata;
|
||||
changedTranslatorIDs.push(metadata.translatorID);
|
||||
toTestTranslatorIDs.add(metadata.translatorID);
|
||||
toTestTranslatorNames.add(metadata.label);
|
||||
}
|
||||
|
||||
// Find all translators that use the changed translators and add them to list/check them too
|
||||
let changedTranslatorIDRe = new RegExp(changedTranslatorIDs.join('|'));
|
||||
let tooManyTranslators = false;
|
||||
for (let translator of translatorServer.translators) {
|
||||
if (!changedTranslatorIDRe.test(translator.content)) continue;
|
||||
toTestTranslatorIDs.add(translator.metadata.translatorID);
|
||||
toTestTranslatorNames.add(translator.metadata.label);
|
||||
if (toTestTranslatorIDs.size >= 10) {
|
||||
tooManyTranslators = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tooManyTranslators) {
|
||||
console.log(
|
||||
`Over 10 translators need to be tested, but this will take too long
|
||||
and timeout the CI environment. Truncating to 10.
|
||||
|
||||
This is likely to happen when changing Embedded Metadata which is
|
||||
loaded by pretty much every other translator or when a PR contains
|
||||
a lot of changed translators.
|
||||
|
||||
You may want to consider adding '[ci skip]' in the commit message.`
|
||||
)
|
||||
}
|
||||
console.log(`Will run tests for translators ${JSON.stringify(Array.from(toTestTranslatorNames))}`);
|
||||
return Array.from(toTestTranslatorIDs);
|
||||
}
|
||||
|
||||
function report(results) {
|
||||
var allPassed = true;
|
||||
for (let translatorID in results) {
|
||||
let translatorResults = results[translatorID];
|
||||
console.log(chalk.bold(chalk.bgWhite(chalk.black(`Running tests for ${translatorID}: ${translatorResults.label}`))));
|
||||
let padding = 2;
|
||||
let output = translatorResults.message.split("\n");
|
||||
for (let line of output) {
|
||||
if (/^Running \d+ tests? for/.test(line)) {
|
||||
console.log(" ".repeat(padding - 1) + chalk.bgCyan(chalk.black(line)));
|
||||
}
|
||||
else if (line.match(/^-/)) {
|
||||
console.log(chalk.red("-" + " ".repeat(padding) + line.substr(1)));
|
||||
}
|
||||
else if (line.match(/^\+/)) {
|
||||
console.log(chalk.green("+" + " ".repeat(padding) + line.substr(1)));
|
||||
}
|
||||
else if (line.match(/^Test \d+: succeeded/)) {
|
||||
console.log(" ".repeat(padding) + chalk.bgGreen(line));
|
||||
}
|
||||
else if (line.match(/^Test \d+: failed/)) {
|
||||
console.log(" ".repeat(padding) + chalk.bgRed(line));
|
||||
allPassed = false;
|
||||
}
|
||||
else {
|
||||
console.log(" ".repeat(padding) + line);
|
||||
}
|
||||
}
|
||||
console.log("\n");
|
||||
}
|
||||
|
||||
return allPassed
|
||||
}
|
||||
|
||||
var allPassed = false;
|
||||
|
||||
let context;
|
||||
try {
|
||||
await translatorServer.serve();
|
||||
|
||||
context = await chromium.launchPersistentContext('/tmp/chromium-user-data-dir', {
|
||||
channel: 'chromium',
|
||||
headless: CI,
|
||||
args: [
|
||||
`--disable-extensions-except=${chromeExtensionDir}`,
|
||||
`--load-extension=${chromeExtensionDir}`
|
||||
]
|
||||
});
|
||||
console.log(`Browser version: ${context.browser().version()}`);
|
||||
|
||||
const translatorsToTest = await getTranslatorsToTest();
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
let testUrl = `chrome-extension://${ZOTERO_CONNECTOR_EXTENSION_ID}/tools/testTranslators/testTranslators.html#translators=${translatorsToTest.join(',')}`;
|
||||
let page = await context.newPage();
|
||||
await page.goto(testUrl);
|
||||
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
let title = (await page.title()).trim();
|
||||
if (title === 'Zotero Translator Tester') {
|
||||
break;
|
||||
}
|
||||
if (i === 3) {
|
||||
console.error('Failed to load Translator Tester extension page');
|
||||
process.exit(2);
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
await page.locator('#translator-tests-complete')
|
||||
.waitFor({
|
||||
state: 'attached',
|
||||
timeout: 5 * 60 * 1000,
|
||||
});
|
||||
|
||||
let testResults = await page.evaluate(() => window.seleniumOutput);
|
||||
allPassed = report(testResults);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
finally {
|
||||
if (!KEEP_BROWSER_OPEN) {
|
||||
await context.close();
|
||||
}
|
||||
translatorServer.stopServing();
|
||||
if (allPassed) {
|
||||
console.log(chalk.green("All translator tests passed"));
|
||||
} else {
|
||||
console.log(chalk.red("Some translator tests failed"));
|
||||
}
|
||||
process.exit(allPassed ? 0 : 1);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "::group::Setup"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ROOT_DIR="$( dirname "$DIR" )"
|
||||
|
||||
|
|
@ -12,8 +11,6 @@ mkdir -p connectors
|
|||
cd connectors
|
||||
|
||||
if [ -d .git ]; then
|
||||
# Temp fix for connectors/src/zotero/resource/schema/global submodule fetch failing
|
||||
git config url."https://".insteadOf git://
|
||||
git pull
|
||||
git submodule update
|
||||
git -C src/zotero/ submodule update -- resource/schema/global
|
||||
|
|
@ -21,7 +18,6 @@ if [ -d .git ]; then
|
|||
npm ci
|
||||
else
|
||||
git clone https://github.com/zotero/zotero-connectors.git --depth 1 .
|
||||
git config url."https://".insteadOf git://
|
||||
git submodule update --init --depth 1
|
||||
git -C src/zotero submodule update --init --depth 1 -- resource/schema/global
|
||||
git -C src/zotero submodule update --init --depth 1 -- resource/SingleFile
|
||||
|
|
@ -29,11 +25,11 @@ else
|
|||
fi
|
||||
|
||||
export ZOTERO_REPOSITORY_URL="http://localhost:8085/"
|
||||
export CHROME_EXTENSION_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDllBS5q+Z9T9tPgYwRN+/8T9wzyjo9tRo03Wy8zP2DQ5Iy+3q0Tjq2vKXGiMCxC/ZVuEMC68Ekv+jNT43VxPbEXI4dzpK1GMBqPJpAcEOB8B1ROBouQMbGGTG7fOdQVlmpdTTPVndVwysJ02CrDMn96IG2ytOq2PO7GR2xleCudQIDAQAB"
|
||||
./build.sh -p b -d
|
||||
cd ..
|
||||
|
||||
echo "::endgroup::"
|
||||
npm explore chromedriver -- npm run install --detect_chromedriver_version
|
||||
|
||||
node browser-test.mjs "$(get_translators_to_check)"
|
||||
get_translators_to_check
|
||||
./selenium-test.js "$TRANSLATORS_TO_CHECK"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const process = require('process');
|
||||
const selenium = require('selenium-webdriver');
|
||||
const until = require('selenium-webdriver/lib/until');
|
||||
const chalk = require('chalk');
|
||||
|
||||
const translatorServer = require('./translator-server');
|
||||
|
||||
const chromeExtensionDir = path.join(__dirname, 'connectors', 'build', 'chrome');
|
||||
const KEEP_BROWSER_OPEN = 'KEEP_BROWSER_OPEN' in process.env;
|
||||
|
||||
async function getTranslatorsToTest() {
|
||||
const translatorFilenames = process.argv[2].split('\n').filter(filename => filename.trim().length > 0);
|
||||
let changedTranslatorIDs = [];
|
||||
let toTestTranslatorIDs = new Set();
|
||||
let toTestTranslatorNames = new Set();
|
||||
for (const translatorFilename of translatorFilenames) {
|
||||
let translatorInfo = translatorServer.filenameToTranslator[translatorFilename].metadata;
|
||||
changedTranslatorIDs.push(translatorInfo.translatorID);
|
||||
toTestTranslatorIDs.add(translatorInfo.translatorID);
|
||||
toTestTranslatorNames.add(translatorInfo.label);
|
||||
}
|
||||
// Find all translators that use the changed translators and add them to list/check them too
|
||||
let tooManyTranslators = false;
|
||||
for (let translator of translatorServer.translators) {
|
||||
for (let translatorID of changedTranslatorIDs) {
|
||||
if (!translator.content.includes(translatorID)) continue;
|
||||
|
||||
toTestTranslatorIDs.add(translator.metadata.translatorID);
|
||||
toTestTranslatorNames.add(translator.metadata.label);
|
||||
if (toTestTranslatorIDs.size >= 10) {
|
||||
tooManyTranslators = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tooManyTranslators) break;
|
||||
}
|
||||
if (tooManyTranslators) {
|
||||
console.log(
|
||||
`Over 10 translators need to be tested, but this will take too long
|
||||
and timeout the CI environment. Truncating to 10.
|
||||
|
||||
This is likely to happen when changing Embedded Metadata which is
|
||||
loaded by pretty much every other translator or when a PR contains
|
||||
a lot of changed translators.
|
||||
|
||||
You may want to consider adding '[ci skip]' in the commit message.`
|
||||
)
|
||||
}
|
||||
console.log(`Will run tests for translators ${JSON.stringify(Array.from(toTestTranslatorNames))}`);
|
||||
return Array.from(toTestTranslatorIDs);
|
||||
}
|
||||
|
||||
function report(results) {
|
||||
var allPassed = true;
|
||||
for (let translatorID in results) {
|
||||
let translatorResults = results[translatorID];
|
||||
console.log(chalk.bold(chalk.bgWhite(chalk.black(`Beginning Tests for ${translatorID}: ${translatorResults.label}`))));
|
||||
let padding = 2;
|
||||
let output = translatorResults.message.split("\n");
|
||||
for (let line of output) {
|
||||
if (line.match(/^TranslatorTester: Running [^T]*Test [0-9]*$/) ||
|
||||
line.match(/^TranslatorTester: Running [0-9]* tests for .*$/)) {
|
||||
console.log(" ".repeat(padding-1) + chalk.bgCyan(chalk.black(line)));
|
||||
}
|
||||
else if (line.match(/^-/)) {
|
||||
console.log(chalk.red("-" + " ".repeat(padding) + line.substr(1)));
|
||||
}
|
||||
else if (line.match(/^\+/)) {
|
||||
console.log(chalk.green("+" + " ".repeat(padding) + line.substr(1)));
|
||||
}
|
||||
else if (line.match(/^TranslatorTester: [^T]*Test [0-9]*: succeeded/)) {
|
||||
console.log(" ".repeat(padding) + chalk.bgGreen(line));
|
||||
}
|
||||
else if (line.match(/^TranslatorTester: [^T]*Test [0-9]*: unknown/)) {
|
||||
console.log(" ".repeat(padding) + chalk.bgYellow(chalk.black(line)));
|
||||
allPassed = false;
|
||||
}
|
||||
else if (line.match(/^TranslatorTester: [^T]*Test [0-9]*: failed/)) {
|
||||
console.log(" ".repeat(padding) + chalk.bgRed(line));
|
||||
allPassed = false;
|
||||
}
|
||||
else {
|
||||
console.log(" ".repeat(padding) + line);
|
||||
}
|
||||
}
|
||||
console.log("\n");
|
||||
}
|
||||
|
||||
return allPassed
|
||||
}
|
||||
|
||||
var allPassed = false;
|
||||
|
||||
(async function() {
|
||||
let driver;
|
||||
try {
|
||||
translatorServer.serve();
|
||||
require('chromedriver');
|
||||
let chrome = require('selenium-webdriver/chrome');
|
||||
let options = new chrome.Options();
|
||||
options.addArguments(`load-extension=${chromeExtensionDir}`);
|
||||
if ('BROWSER_EXECUTABLE' in process.env) {
|
||||
options.setChromeBinaryPath(process.env['BROWSER_EXECUTABLE']);
|
||||
}
|
||||
|
||||
driver = new selenium.Builder()
|
||||
.forBrowser('chrome')
|
||||
.setChromeOptions(options)
|
||||
.build();
|
||||
|
||||
// No API to retrieve extension ID. Hacks, sigh.
|
||||
await driver.get("chrome://system/");
|
||||
await driver.wait(until.elementLocated({id: 'extensions-value-btn'}), 60*1000);
|
||||
let extBtn = await driver.findElement({css: '#extensions-value-btn'});
|
||||
await extBtn.click();
|
||||
let contentElem = await driver.findElement({css: '#content'});
|
||||
let text = await contentElem.getText();
|
||||
let extId = text.match(/([^\s]*) : Zotero Connector/)[1];
|
||||
|
||||
// We got the extension ID and test URL, let's test
|
||||
const translatorsToTest = await getTranslatorsToTest();
|
||||
let testUrl = `chrome-extension://${extId}/tools/testTranslators/testTranslators.html#translators=${translatorsToTest.join(',')}`;
|
||||
await new Promise((resolve) => setTimeout(() => resolve(driver.get(testUrl)), 500));
|
||||
await driver.wait(until.elementLocated({id: 'translator-tests-complete'}), 30*60*1000);
|
||||
testResults = await driver.executeScript('return window.seleniumOutput');
|
||||
|
||||
allPassed = report(testResults);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
finally {
|
||||
if (!KEEP_BROWSER_OPEN) {
|
||||
await driver.quit();
|
||||
}
|
||||
translatorServer.stopServing();
|
||||
if (allPassed) {
|
||||
console.log(chalk.green("All translator tests passed"));
|
||||
} else {
|
||||
console.log(chalk.red("Some translator tests failed"));
|
||||
}
|
||||
process.exit(allPassed ? 0 : 1);
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import http from 'http';
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
const http = require("http");
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
const host = 'localhost';
|
||||
const port = 8085;
|
||||
|
|
@ -9,7 +9,7 @@ var server;
|
|||
var translators = [];
|
||||
var idToTranslator = {};
|
||||
var filenameToTranslator = {};
|
||||
const rootPath = path.join(import.meta.dirname, '../..');
|
||||
const rootPath = path.join(__dirname, '../..');
|
||||
const infoRe = /^\s*{[\S\s]*?}\s*?[\r\n]/;
|
||||
|
||||
async function loadTranslators() {
|
||||
|
|
@ -19,17 +19,11 @@ async function loadTranslators() {
|
|||
const fullPath = path.join(rootPath, file);
|
||||
if (!fullPath.endsWith('.js') || !(await fs.stat(fullPath)).isFile()) continue;
|
||||
let content = await fs.readFile(fullPath);
|
||||
let translator;
|
||||
try {
|
||||
let translatorInfo = JSON.parse(infoRe.exec(content)[0]);
|
||||
translator = { metadata: translatorInfo, content };
|
||||
idToTranslator[translatorInfo.translatorID] = translator;
|
||||
}
|
||||
catch (e) {
|
||||
translator = { metadata: null, content };
|
||||
}
|
||||
let translatorInfo = JSON.parse(infoRe.exec(content)[0]);
|
||||
let translator = { metadata: translatorInfo, content };
|
||||
translators.push(translator);
|
||||
filenameToTranslator[file] = translator;
|
||||
idToTranslator[translatorInfo.translatorID] = translator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -62,16 +56,17 @@ async function requestListener(req, res) {
|
|||
res.end();
|
||||
}
|
||||
|
||||
async function serve() {
|
||||
await loadTranslators();
|
||||
server = http.createServer(requestListener);
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Translator server is running on http://${host}:${port}`);
|
||||
});
|
||||
}
|
||||
|
||||
function stopServing() {
|
||||
server.close();
|
||||
}
|
||||
|
||||
export { serve, stopServing, filenameToTranslator, translators };
|
||||
module.exports = {
|
||||
serve: async function() {
|
||||
await loadTranslators();
|
||||
server = http.createServer(requestListener);
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Translator server is running on http://${host}:${port}`);
|
||||
});
|
||||
},
|
||||
stopServing: function() {
|
||||
server.close();
|
||||
},
|
||||
filenameToTranslator,
|
||||
translators
|
||||
};
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
/usr/bin/xvfb-run /usr/bin/google-chrome $@
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { readFile, writeFile } from 'fs/promises';
|
||||
|
||||
const INDEX_D_TS_URL = new URL('../index.d.ts', import.meta.url);
|
||||
const SCHEMA_JSON_URL = new URL('../../zotero-client/resource/schema/global/schema.json', import.meta.url);
|
||||
|
||||
const BEGIN_MARKER = '\t/* *** BEGIN GENERATED TYPES *** */';
|
||||
const END_MARKER = '\t/* *** END GENERATED TYPES *** */';
|
||||
|
||||
async function updateIndexDTS() {
|
||||
let indexDTS = await readFile(INDEX_D_TS_URL, { encoding: 'utf8' });
|
||||
let schema = JSON.parse(await readFile(SCHEMA_JSON_URL));
|
||||
|
||||
let typeItemTypes = '\ttype ItemTypes = {';
|
||||
let itemTypeTypes = '';
|
||||
let creatorTypes = new Set();
|
||||
|
||||
for (let typeSchema of schema.itemTypes) {
|
||||
let itemType = typeSchema.itemType;
|
||||
if (['annotation', 'attachment', 'note'].includes(itemType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let itemTypeUppercase = itemType[0].toUpperCase() + itemType.substring(1) + 'Item';
|
||||
if (itemTypeUppercase == 'TvBroadcastItem') {
|
||||
itemTypeUppercase = 'TVBroadcastItem';
|
||||
}
|
||||
|
||||
typeItemTypes += `\n\t\t"${itemType}": ${itemTypeUppercase},`;
|
||||
itemTypeTypes += `\n\n\ttype ${itemTypeUppercase} = {`;
|
||||
itemTypeTypes += `\n\t\titemType: "${itemType}";`;
|
||||
for (let { field } of typeSchema.fields) {
|
||||
itemTypeTypes += `\n\t\t${field}?: string;`
|
||||
}
|
||||
|
||||
let creatorTypesJoined = typeSchema.creatorTypes.map(typeSchema => '"' + typeSchema.creatorType + '"').join(' | ');
|
||||
itemTypeTypes += `\n\n\t\tcreators: Creator<${creatorTypesJoined}>[];`;
|
||||
itemTypeTypes += '\n\t\tattachments: Attachment[];';
|
||||
itemTypeTypes += '\n\t\ttags: Tag[];';
|
||||
itemTypeTypes += '\n\t\tnotes: Note[];';
|
||||
itemTypeTypes += '\n\t\tseeAlso: string[];';
|
||||
itemTypeTypes += '\n\t\tcomplete(): void;';
|
||||
itemTypeTypes += '\n\n\t\t[key: string]: string;';
|
||||
itemTypeTypes += '\n\t};';
|
||||
|
||||
for (let { creatorType } of typeSchema.creatorTypes) {
|
||||
creatorTypes.add(creatorType);
|
||||
}
|
||||
}
|
||||
typeItemTypes += '\n\t};'
|
||||
|
||||
let typeCreatorType = '\n\ttype CreatorType =';
|
||||
for (let creatorType of Array.from(creatorTypes).sort()) {
|
||||
typeCreatorType += `\n\t\t| "${creatorType}"`;
|
||||
}
|
||||
typeCreatorType += ';';
|
||||
|
||||
let beginIdx = indexDTS.indexOf(BEGIN_MARKER);
|
||||
let endIdx = indexDTS.indexOf(END_MARKER);
|
||||
if (beginIdx == -1 || endIdx == -1) {
|
||||
throw new Error('Could not find generated types section in index.d.ts');
|
||||
}
|
||||
|
||||
indexDTS = indexDTS.substring(0, beginIdx) + BEGIN_MARKER + '\n'
|
||||
+ typeItemTypes
|
||||
+ itemTypeTypes
|
||||
+ '\n' + typeCreatorType
|
||||
+ '\n'
|
||||
+ indexDTS.substring(endIdx);
|
||||
|
||||
await writeFile(INDEX_D_TS_URL, indexDTS);
|
||||
}
|
||||
|
||||
updateIndexDTS();
|
||||
43
.eslintrc
43
.eslintrc
|
|
@ -1,60 +1,44 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
"browser": false,
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"@zotero"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "2023"
|
||||
"ecmaVersion": 2017
|
||||
},
|
||||
"globals": {
|
||||
"Zotero": "readonly",
|
||||
"Z": "readonly",
|
||||
"ZU": "readonly",
|
||||
"attr": "readonly",
|
||||
"innerText": "readonly",
|
||||
"text": "readonly",
|
||||
"request": "readonly",
|
||||
"requestText": "readonly",
|
||||
"requestJSON": "readonly",
|
||||
"requestDocument": "readonly"
|
||||
"DOMParser": "readonly",
|
||||
"XPathResult": "readonly",
|
||||
"XMLSerializer": "readonly",
|
||||
"atob": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^testCases$|^detectWeb$|^doWeb$|^detectImport$|^doImport$|^doExport$|^detectSearch$|^doSearch$|^exports$"
|
||||
"varsIgnorePattern": "^detectWeb$|^doWeb$|^detectImport$|^doImport$|^doExport$|^detectSearch$|^doSearch$|^exports$"
|
||||
}
|
||||
],
|
||||
|
||||
"no-redeclare": ["error", {"builtinGlobals": true}],
|
||||
"linebreak-style": ["error", "unix"],
|
||||
|
||||
"lines-around-comment": [
|
||||
"error",
|
||||
{
|
||||
"ignorePattern": "END TEST CASES"
|
||||
}
|
||||
],
|
||||
|
||||
"no-restricted-globals": ["error", {
|
||||
"name": "document",
|
||||
"message": "Use doc instead."
|
||||
}],
|
||||
|
||||
"zotero-translator/not-executable": "error",
|
||||
"zotero-translator/header-valid-json": "error",
|
||||
"zotero-translator/header-translator-id": "error",
|
||||
"zotero-translator/header-last-updated": "warn",
|
||||
"zotero-translator/header-translator-type": "warn",
|
||||
"zotero-translator/translator-id": "error",
|
||||
"zotero-translator/last-updated": "warn",
|
||||
"zotero-translator/translator-type": "warn",
|
||||
|
||||
"zotero-translator/no-for-each": "warn",
|
||||
"zotero-translator/prefer-index-of": "warn",
|
||||
"zotero-translator/robust-query-selector": "warn",
|
||||
|
||||
"zotero-translator/test-cases-valid-json": "error",
|
||||
"zotero-translator/test-cases": "error",
|
||||
"zotero-translator/translator-framework": "warn",
|
||||
|
||||
|
|
@ -65,6 +49,5 @@
|
|||
},
|
||||
"plugins": [
|
||||
"zotero-translator"
|
||||
],
|
||||
"processor": "zotero-translator/translator"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: "All other translator issues and requests: Post to the Zotero Forums"
|
||||
url: https://forums.zotero.org/post/discussion
|
||||
about: Please do not use GitHub Issues to report problems saving webpages or to request a new translator. Post to the Zotero Forums. Zotero developers will create issues as necessary in the relevant repositories.
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
name: Report a confirmed bug with technical details
|
||||
about: If you’re sure you’ve identified a bug in a specific Zotero translator and can provide technical details, you can open an issue here.
|
||||
---
|
||||
|
||||
**READ THIS BEFORE CREATING AN ISSUE**
|
||||
|
||||
Zotero generally does not use GitHub Issues for bug reports or feature requests in Zotero software.
|
||||
|
||||
If you’re sure you’ve identified a bug in a specific Zotero translator, you’re welcome to create an issue here.
|
||||
|
||||
Otherwise, please post all requests to the Zotero Forums at https://forums.zotero.org, where Zotero developers and many others can help. For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
||||
|
||||
Development questions involving code, APIs, or other technical topics can be posted to the zotero-dev mailing list at http://groups.google.com/group/zotero-dev.
|
||||
|
||||
See https://www.zotero.org/support/zotero_support for more information on how Zotero support works.
|
||||
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
|
@ -14,13 +14,18 @@ jobs:
|
|||
# and get more history on the current branch so we can find the branch point
|
||||
- run: git fetch origin master:master --depth=1
|
||||
if: github.ref != 'refs/heads/master'
|
||||
- run: git fetch --update-shallow --depth=100 origin $(git rev-list HEAD)
|
||||
- run: git fetch --update-shallow --depth=25 origin $(git rev-list HEAD)
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
node-version: 14
|
||||
|
||||
# Local via act
|
||||
- name: Install packages for act
|
||||
if: env.ACT == 'true'
|
||||
run: apt update && apt install -y xvfb git
|
||||
|
||||
- name: Get current connector hash
|
||||
id: get-connector-hash
|
||||
run: |
|
||||
|
|
@ -29,28 +34,29 @@ jobs:
|
|||
|
||||
- name: Cache connector code
|
||||
id: connector-cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .ci/pull-request-check/connectors
|
||||
key: connectors-${{ hashFiles('.ci/pull-request-check/check-pull-request.sh') }}-${{ steps.get-connector-hash.outputs.hash }}
|
||||
|
||||
- name: Install node packages
|
||||
run: npm ci
|
||||
|
||||
- name: Install Chromium
|
||||
run: npx playwright install chromium
|
||||
|
||||
- name: Test pull request
|
||||
if: github.event_name == 'pull_request'
|
||||
run: ./check-pull-request.sh
|
||||
working-directory: .ci/pull-request-check
|
||||
|
||||
- name: Check deleted.txt
|
||||
run: ./checkDeletedTxt.sh
|
||||
working-directory: .ci
|
||||
if: ${{ success() || failure() }}
|
||||
#- name: Debugging with tmate
|
||||
# uses: mxschmitt/action-tmate@v3.1
|
||||
# if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Lint
|
||||
run: ./lint.sh
|
||||
working-directory: .ci
|
||||
if: ${{ success() || failure() }}
|
||||
|
||||
- name: Check deleted.txt
|
||||
run: ./checkDeletedTxt.sh
|
||||
working-directory: .ci
|
||||
|
||||
- name: Test pull request
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
BROWSER_EXECUTABLE: /home/runner/work/translators/translators/.ci/pull-request-check/xvfb-run-chrome
|
||||
run: ./check-pull-request.sh
|
||||
working-directory: .ci/pull-request-check
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
node_modules
|
||||
.ci/pull-request-check/connectors
|
||||
.DS_Store
|
||||
|
|
|
|||
|
|
@ -0,0 +1,206 @@
|
|||
{
|
||||
"translatorID": "bbf1617b-d836-4665-9aae-45f223264460",
|
||||
"label": "A Contra Corriente",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://acontracorriente\\.chass\\.ncsu\\.edu/index\\.php/acontracorriente/",
|
||||
"minVersion": "2.1",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2016-08-18 20:51:04"
|
||||
}
|
||||
|
||||
/*
|
||||
A Contra Corriente Translator
|
||||
Copyright (C) 2012 Sebastian Karcher and Avram Lyon
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affer General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Affer General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.indexOf('/article/view/')>-1) {
|
||||
return "journalArticle";
|
||||
} else if (getSearchResults(doc, url, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
}
|
||||
|
||||
function getSearchResults(doc, url, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
if (url.indexOf('/issue/view/')>-1) {
|
||||
var rows = ZU.xpath(doc, '//*[@class="tocTitle"]/a');
|
||||
} else {
|
||||
var rows = ZU.xpath(doc, '//div[@id="results"]//tr');
|
||||
}
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
if (url.indexOf('/issue/view/')>-1) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
} else {
|
||||
var href = ZU.xpathText(rows[i], './/td/a[contains(@class, "file")][1]/@href');
|
||||
var title = ZU.xpathText(rows[i], './td[2]');
|
||||
}
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, url, false), function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
urlBibtex = url.replace('/article/view/', '/rt/captureCite/');
|
||||
if (!/\/article\/view\/.+\/.+/.test(url)) {
|
||||
urlBibtex += '/0';
|
||||
}
|
||||
urlBibtex += '/BibtexCitationPlugin';
|
||||
//Z.debug(urlBibtex);
|
||||
ZU.doGet(urlBibtex, function(text) {
|
||||
var parser = new DOMParser();
|
||||
var xml = parser.parseFromString(text, "text/html");
|
||||
var bibtex = ZU.xpathText(xml, '//pre');
|
||||
if (bibtex) {
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
translator.setString(text);
|
||||
translator.setHandler("itemDone", function(obj, item) {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://acontracorriente.chass.ncsu.edu/index.php/acontracorriente/article/view/102",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Carlos Iván Degregori: antropólogo del alma",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "José",
|
||||
"lastName": "Rénique",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"ISSN": "1548-7083",
|
||||
"abstractNote": "Remembranza de la reciente muerte (18 de Mayo de 2011) en Lima de Carlos Iván Degregori, uno de los intelectuales peruanos más importantes de las últimas décadas y uno de los estudiosos internacionales más destacados de la violencia política. A Contracorriente se suma a los innumerables homenajes que se tributan a su memoria. Su colega y amigo a lo largo de muchos años, el historiador José Luis Rénique, traza en esta nota el perfil humano, intelectual y político de Degregori. Al final incluimos también una lista de sus principales publicaciones.",
|
||||
"issue": "3",
|
||||
"itemID": "AC102",
|
||||
"libraryCatalog": "A Contra Corriente",
|
||||
"publicationTitle": "A Contracorriente",
|
||||
"shortTitle": "Carlos Iván Degregori",
|
||||
"url": "http://acontracorriente.chass.ncsu.edu/index.php/acontracorriente/article/view/102",
|
||||
"volume": "8",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Carlos Iván degregori",
|
||||
"Perú",
|
||||
"historia"
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://tools.chass.ncsu.edu/open_journal/index.php/acontracorriente/issue/view/16/showToc",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://acontracorriente.chass.ncsu.edu/index.php/acontracorriente/search/search?query=argentina&authors=&title=&abstract=&galleyFullText=&suppFiles=&dateFromMonth=&dateFromDay=&dateFromYear=&dateToMonth=&dateToDay=&dateToYear=&dateToHour=23&dateToMinute=59&dateToSecond=59&discipline=&subject=&type=&coverage=&indexTerms=",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://acontracorriente.chass.ncsu.edu/index.php/acontracorriente/article/view/174",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "\"La Huelga de los Conventillos\", Buenos Aires, Nueva Pompeya, 1936. Un aporte a los estudios sobre género y clase",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Verónica",
|
||||
"lastName": "Norando",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Ludmila",
|
||||
"lastName": "Scheinkman",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"ISSN": "1548-7083",
|
||||
"abstractNote": "Este trabajo se propone realizar un análisis de las relaciones de género y clase a través de un estudio de caso: la “Huelga de los Conventillos” de la fábrica textil Gratry en 1936, que se extendió por más de tres meses, pasando casi inadvertida, sin embargo, para la investigación histórica. Siendo la textil una rama de industria con una mayoría de mano de obra femenina, el caso de la casa Gratry, donde el 60% de los 800 obreros eran mujeres, aparece como ejemplar para la observación de la actividad de las mujeres en conflicto. En el trabajo se analiza el rol de las trabajadoras en la huelga, su participación política, sus formas de organización y resistencia, haciendo eje en las determinaciones de género y de clase que son abordadas de manera complementaria e interrelacionada, así como el complejo entramado de tensiones y solidaridades que éstas generan. De éste modo, se pretende ahondar en la compleja conformación de una identidad obrera femenina, a la vez que se discute con aquella mirada historiográfica tradicional que ha restado importancia a la participación de la mujer en el conflicto social. Esto se realizará a través de la exploración de una serie de variables: las relaciones inter-género e inter-clase (fundamentalmente el vínculo entre las trabajadoras y la patronal masculina), inter-género e intra-clase (la relación entre trabajadoras y trabajadores), intra-género e inter-clase (los lazos entre las trabajadoras y las vecinas comerciantes del barrio), intra-género e intra-clase (relaciones de solidaridad entre trabajadoras en huelga, y de antagonismo entre huelguistas y “carneras”). Para ello se trabajó un corpus documental que incluye información de tipo cuantitativa (las estadísticas del Boletín Informativo del Departamento Nacional del Trabajo), y cualitativa: periódicos obreros –fundamentalmente El Obrero Textil, órgano gremial de la Unión Obrera Textil, Semanario de la CGT-Independencia (órgano de la Confederación General del Trabajo (CGT)-Independencia) y La Vanguardia (periódico del Partido Socialista), entre otros, y entrevistas orales a vecinas de Nueva Pompeya y familiares de trabajadoras de la fábrica Gratry. Se desarrollará una metodología cuali-cuantitativa para el cruce de estas fuentes.",
|
||||
"issue": "1",
|
||||
"itemID": "AC174",
|
||||
"libraryCatalog": "A Contra Corriente",
|
||||
"pages": "1–37",
|
||||
"publicationTitle": "A Contracorriente",
|
||||
"url": "http://acontracorriente.chass.ncsu.edu/index.php/acontracorriente/article/view/174",
|
||||
"volume": "9",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"huelga",
|
||||
"relaciones de género",
|
||||
"trabajadores",
|
||||
"trabajadroras"
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
{
|
||||
"translatorID": "92d45016-5f7b-4bcf-bb63-193033f02f2b",
|
||||
"label": "ABC News Australia",
|
||||
"creator": "Joyce Chia",
|
||||
"target": "https?://(www\\.)?abc\\.net\\.au/news/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-23 00:29:10"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2020-2021 Joyce Chia
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
let contentType = attr(doc, 'meta[property="ABC.ContentType"]', 'content');
|
||||
if (contentType == 'CMChannel' && getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
else if (contentType == 'Video') {
|
||||
return 'videoRecording';
|
||||
}
|
||||
else if (contentType == 'Article') {
|
||||
return 'newspaperArticle';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h3 a');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) return;
|
||||
ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.language = "en-AU";
|
||||
// og:url does not preserve https prefixes, so use canonical link until fixed
|
||||
var canonical = doc.querySelector('link[rel="canonical"]');
|
||||
if (canonical) {
|
||||
item.url = canonical.href;
|
||||
}
|
||||
|
||||
if (item.itemType == 'videoRecording') {
|
||||
item.studio = "ABC News"; // i guess this is correct...
|
||||
}
|
||||
else {
|
||||
item.publicationTitle = "ABC News";
|
||||
}
|
||||
|
||||
item.language = "en-AU";
|
||||
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
else {
|
||||
item.date = ZU.strToISO(attr(doc, 'time', 'datetime'));
|
||||
}
|
||||
|
||||
var authors = text(doc, '[data-component="Byline"] p');
|
||||
if (authors && item.creators.length <= 1) {
|
||||
authors = authors.replace(/^By /, '');
|
||||
if (authors == authors.toUpperCase()) { // convert to title case if all caps
|
||||
authors = ZU.capitalizeTitle(authors, true);
|
||||
}
|
||||
item.creators = [];
|
||||
var authorsList = authors.split(/,|\band\b/);
|
||||
for (let i = 0; i < authorsList.length; i++) {
|
||||
item.creators.push(ZU.cleanAuthor(authorsList[i], "author"));
|
||||
}
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.abc.net.au/news/2020-05-22/nt-government-coronavirus-recovery-commission-michael-gunner/12276832?section=politics",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "NT 'uniquely positioned' to solve Australia's economic woes post-COVID-19, says Chief Minister",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Lauren",
|
||||
"lastName": "Roberts",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-05-22",
|
||||
"abstractNote": "The NT Labor Government establishes a new commission to help it financially recover from the coronavirus pandemic, with the former opposition leader and a former chief minister in key roles.",
|
||||
"language": "en-AU",
|
||||
"libraryCatalog": "www.abc.net.au",
|
||||
"publicationTitle": "ABC News",
|
||||
"url": "https://www.abc.net.au/news/2020-05-22/nt-government-coronavirus-recovery-commission-michael-gunner/12276832",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "chief minister michael gunner"
|
||||
},
|
||||
{
|
||||
"tag": "coronavirus budget"
|
||||
},
|
||||
{
|
||||
"tag": "nt budget"
|
||||
},
|
||||
{
|
||||
"tag": "parliament house"
|
||||
},
|
||||
{
|
||||
"tag": "territory economic reconstruction commission"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.abc.net.au/news/2021-07-23/tracey-holmes-on-the-ground-in-tokyo/13467310",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "Tracey Holmes on the ground in Tokyo",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Tracey",
|
||||
"lastName": "Holmes",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-07-22",
|
||||
"abstractNote": "Brisbane is named the host of the 2032 Olympics, Tracey speaks with Federal Sports Minister Richard Colbeck to get his reaction. Plus we look at the COVID safety measures athletes, officials and the media are subjected to as they land in the Japanese capital.",
|
||||
"language": "en-AU",
|
||||
"libraryCatalog": "www.abc.net.au",
|
||||
"studio": "ABC News",
|
||||
"url": "https://www.abc.net.au/news/2021-07-23/tracey-holmes-on-the-ground-in-tokyo/13467310",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "olympics"
|
||||
},
|
||||
{
|
||||
"tag": "tokyo olympics 2021"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
{
|
||||
"translatorID": "2553b683-dc1b-4a1e-833a-7a7755326186",
|
||||
"label": "ACLS Humanities EBook",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://www\\.fulcrum\\.org/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-03 01:54:15"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.querySelector('meta[name="citation_title"]')) {
|
||||
return "book";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.document a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(text(row, 'h3'));
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = 'ACLS Humanities EBook';
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.fulcrum.org/concern/monographs/79408038k?locale=en",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Empire, Architecture, and the City: French-Ottoman Encounters, 1830-1914",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Zeynep",
|
||||
"lastName": "Celik",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2008",
|
||||
"ISBN": "9780295987798",
|
||||
"language": "en",
|
||||
"libraryCatalog": "ACLS Humanities EBook",
|
||||
"publisher": "U of Washington Press",
|
||||
"shortTitle": "Empire, Architecture, and the City",
|
||||
"url": "https://hdl.handle.net/2027/heb.33994",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.fulcrum.org/concern/monographs/9z9032224?locale=en",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Black Rock: Mining Folklore of the Pennsylvania Dutch",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "George",
|
||||
"lastName": "Korson",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1960",
|
||||
"ISBN": "9780801803451",
|
||||
"language": "en",
|
||||
"libraryCatalog": "ACLS Humanities EBook",
|
||||
"publisher": "Johns Hopkins UP",
|
||||
"shortTitle": "Black Rock",
|
||||
"url": "https://hdl.handle.net/2027/heb.33116",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.fulcrum.org/heb?utf8=%E2%9C%93&press=heb&q=istanbul",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
43
ACLWeb.js
43
ACLWeb.js
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "f4a5876a-3e53-40e2-9032-d99a30d7a6fc",
|
||||
"label": "ACLWeb",
|
||||
"creator": "Guy Aglionby",
|
||||
"target": "^https?://(www\\.)?(aclanthology\\.org|aclweb\\.org/anthology)/",
|
||||
"target": "^https?://(www\\.)?aclweb\\.org/anthology/[^#]+",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-11-10 10:36:48"
|
||||
"lastUpdated": "2020-07-08 09:55:39"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -49,19 +49,12 @@ var ext2mime = {
|
|||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
ppt: 'application/vnd.ms-powerpoint',
|
||||
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
xls: 'application/vnd.ms-excel',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
html: 'text/html',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
mp4: 'video/mp4',
|
||||
tsv: 'text/tab-separated-values',
|
||||
csv: 'text/csv',
|
||||
py: 'text/x-python',
|
||||
tex: 'text/x-tex',
|
||||
bbl: 'text/x-tex'
|
||||
mp4: 'video/mp4'
|
||||
};
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
|
|
@ -108,7 +101,7 @@ function doWeb(doc, url) {
|
|||
}
|
||||
|
||||
function scrape(doc) {
|
||||
let bibtex = ZU.xpath(doc, '//pre[@id = "citeBibtexContent"]')[0].textContent;
|
||||
let bibtex = ZU.xpath(doc, '//button[contains(text(), "Copy BibTeX to Clipboard")]/@data-clipboard-text')[0].value;
|
||||
let pdfURL = ZU.xpath(doc, '//a[span[contains(text(), "PDF")]]/@href')[0].value;
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
|
|
@ -170,7 +163,7 @@ function getVenue(doc, pubTitle) {
|
|||
// better to use full proceedingsTitle to cite these publications
|
||||
return '';
|
||||
}
|
||||
if (venueString.includes('SemEval')) {
|
||||
if (venueString.includes('*SEMEVAL')) {
|
||||
if (pubTitle.includes('SENSEVAL')) {
|
||||
return 'SENSEVAL ' + year;
|
||||
}
|
||||
|
|
@ -217,7 +210,7 @@ function getSearchResults(doc, url) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
let papers = ZU.xpath(doc, '//section[@id="main"]//strong/a');
|
||||
let papers = ZU.xpath(doc, '//strong/a[contains(@href, "/anthology/")]');
|
||||
for (let paper of papers) {
|
||||
items[paper.href] = paper.text;
|
||||
}
|
||||
|
|
@ -229,22 +222,22 @@ function getSearchResults(doc, url) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/events/acl-2018/",
|
||||
"url": "https://aclweb.org/anthology/events/acl-2018/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/volumes/P18-1/",
|
||||
"url": "https://aclweb.org/anthology/volumes/P18-1/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/people/i/iryna-gurevych/",
|
||||
"url": "https://aclweb.org/anthology/people/i/iryna-gurevych/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/Q18-1001/",
|
||||
"url": "https://aclweb.org/anthology/Q18-1001/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -289,7 +282,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/W04-0801/",
|
||||
"url": "https://www.aclweb.org/anthology/W04-0801/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -348,7 +341,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/W19-0101/",
|
||||
"url": "https://www.aclweb.org/anthology/W19-0101/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -385,7 +378,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/N12-2001/",
|
||||
"url": "https://www.aclweb.org/anthology/N12-2001/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -434,7 +427,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/N18-1001/",
|
||||
"url": "https://www.aclweb.org/anthology/N18-1001/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -515,7 +508,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/2020.lrec-1.2/",
|
||||
"url": "https://www.aclweb.org/anthology/2020.lrec-1.2/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -545,7 +538,7 @@ var testCases = [
|
|||
"libraryCatalog": "ACLWeb",
|
||||
"pages": "11–20",
|
||||
"place": "Marseille, France",
|
||||
"proceedingsTitle": "Proceedings of the 12th Language Resources and Evaluation Conference",
|
||||
"proceedingsTitle": "Proceedings of The 12th Language Resources and Evaluation Conference",
|
||||
"publisher": "European Language Resources Association",
|
||||
"url": "https://www.aclweb.org/anthology/2020.lrec-1.2",
|
||||
"attachments": [
|
||||
|
|
@ -562,12 +555,12 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/volumes/2020.lrec-1/",
|
||||
"url": "https://www.aclweb.org/anthology/volumes/2020.lrec-1/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aclanthology.org/T87-1010.bib",
|
||||
"url": "https://www.aclweb.org/anthology/T87-1010.bib",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-07-30 05:19:59"
|
||||
"lastUpdated": "2020-04-20 05:31:35"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -34,6 +34,10 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
// attr()/text() v2
|
||||
// eslint-disable-next-line
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (isContentUrl(url)) {
|
||||
let subtypeMatch = getItemSubtype(doc);
|
||||
|
|
@ -150,33 +154,23 @@ function scrape(doc) {
|
|||
// The (co-)chair(s) or supervisor(s) are included in CSL as additional authors.
|
||||
cslItem.author.splice(1);
|
||||
}
|
||||
|
||||
if (cslItem.source && (cslItem.source.includes('19') || cslItem.source.includes('20'))) {
|
||||
// Issue date sometimes goes in source (libraryCatalog)
|
||||
delete cslItem.source;
|
||||
}
|
||||
|
||||
let item = new Zotero.Item();
|
||||
ZU.itemFromCSLJSON(item, cslItem);
|
||||
|
||||
item.title = ZU.unescapeHTML(item.title);
|
||||
|
||||
let abstractElements = doc.querySelectorAll('div.article__abstract p, div.abstractSection p');
|
||||
let abstract = Array.from(abstractElements).map(x => x.textContent).join('\n\n');
|
||||
if (abstract.length && abstract.toLowerCase() != 'no abstract available.') {
|
||||
item.abstractNote = ZU.trimInternal(abstract);
|
||||
}
|
||||
|
||||
let pdfElement = doc.querySelector('a[title="View PDF"]');
|
||||
let pdfElement = doc.querySelector('a[title=PDF]');
|
||||
if (pdfElement) {
|
||||
item.attachments.push({
|
||||
url: pdfElement.href,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
if (item.DOI) {
|
||||
item.url = 'https://dl.acm.org/doi/' + ZU.cleanDOI(item.DOI);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.itemType == 'journalArticle') {
|
||||
|
|
@ -239,7 +233,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/abs/10.1145/1596655.1596682",
|
||||
"detectedItemType": "conferencePaper",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -248,13 +241,13 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Mostafa",
|
||||
"firstName": "Nagy",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Krintz",
|
||||
"firstName": "Chandra",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -269,7 +262,7 @@ var testCases = [
|
|||
"proceedingsTitle": "Proceedings of the 7th International Conference on Principles and Practice of Programming in Java",
|
||||
"publisher": "Association for Computing Machinery",
|
||||
"series": "PPPJ '09",
|
||||
"url": "https://dl.acm.org/doi/10.1145/1596655.1596682",
|
||||
"url": "https://doi.org/10.1145/1596655.1596682",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -295,7 +288,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/10.5555/1717186",
|
||||
"detectedItemType": "book",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -304,7 +296,7 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Loeliger",
|
||||
"firstName": "Jon",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -314,7 +306,6 @@ var testCases = [
|
|||
"edition": "1st",
|
||||
"itemID": "10.5555/1717186",
|
||||
"libraryCatalog": "ACM Digital Library",
|
||||
"numPages": "336",
|
||||
"publisher": "O'Reilly Media, Inc.",
|
||||
"shortTitle": "Version Control with Git",
|
||||
"attachments": [],
|
||||
|
|
@ -327,7 +318,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/abs/10.1023/A:1008286901817",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -336,13 +326,13 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Tegethoff",
|
||||
"firstName": "Mick",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Chen",
|
||||
"firstName": "Tom",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -393,7 +383,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/abs/10.1145/258948.258973",
|
||||
"detectedItemType": "conferencePaper",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -402,13 +391,13 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Elliott",
|
||||
"firstName": "Conal",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Hudak",
|
||||
"firstName": "Paul",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -423,7 +412,7 @@ var testCases = [
|
|||
"proceedingsTitle": "Proceedings of the second ACM SIGPLAN international conference on Functional programming",
|
||||
"publisher": "Association for Computing Machinery",
|
||||
"series": "ICFP '97",
|
||||
"url": "https://dl.acm.org/doi/10.1145/258948.258973",
|
||||
"url": "https://doi.org/10.1145/258948.258973",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -439,7 +428,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/abs/10.1145/2566617",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -448,19 +436,19 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Joseph",
|
||||
"firstName": "Kenneth",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Carley",
|
||||
"firstName": "Kathleen M.",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Hong",
|
||||
"firstName": "Jason I.",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -475,7 +463,7 @@ var testCases = [
|
|||
"pages": "46:1–46:22",
|
||||
"publicationTitle": "ACM Transactions on Intelligent Systems and Technology",
|
||||
"shortTitle": "Check-ins in “Blau Space”",
|
||||
"url": "https://dl.acm.org/doi/10.1145/2566617",
|
||||
"url": "https://doi.org/10.1145/2566617",
|
||||
"volume": "5",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -505,7 +493,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/abs/10.5555/3336323.C5474411",
|
||||
"detectedItemType": "bookSection",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -527,9 +514,8 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "November 20, 2019",
|
||||
"ISBN": "9781450372763",
|
||||
"abstractNote": "This organizational history relates the role of the National Science Foundation (NSF) in the development of modern computing. Drawing upon new and existing oral histories, extensive use of NSF documents, and the experience of two of the authors as senior managers, this book describes how NSF's programmatic activities originated and evolved to become the primary source of funding for fundamental research in computing and information technologies.The book traces how NSF's support has provided facilities and education for computing usage by all scientific disciplines, aided in institution and professional community building, supported fundamental research in computer science and allied disciplines, and led the efforts to broaden participation in computing by all segments of society.Today, the research and infrastructure facilitated by NSF computing programs are significant economic drivers of American society and industry. For example, NSF supported work that led to the first widelyused web browser, Netscape; sponsored the creation of algorithms at the core of the Google search engine; facilitated the growth of the public Internet; and funded research on the scientific basis for countless other applications and technologies. NSF has advanced the development of human capital and ideas for future advances in computing and its applications.This account is the first comprehensive coverage of NSF's role in the extraordinary growth and expansion of modern computing and its use. It will appeal to historians of computing, policy makers and leaders in government and academia, and individuals interested in the history and development of computing and the NSF.",
|
||||
"abstractNote": "This organizational history relates the role of the National Science Foundation (NSF) in the development of modern computing. Drawing upon new and existing oral histories, extensive use of NSF documents, and the experience of two of the authors as senior managers, this book describes how NSF's programmatic activities originated and evolved to become the primary source of funding for fundamental research in computing and information technologies. The book traces how NSF's support has provided facilities and education for computing usage by all scientific disciplines, aided in institution and professional community building, supported fundamental research in computer science and allied disciplines, and led the efforts to broaden participation in computing by all segments of society. Today, the research and infrastructure facilitated by NSF computing programs are significant economic drivers of American society and industry. For example, NSF supported work that led to the first widelyused web browser, Netscape; sponsored the creation of algorithms at the core of the Google search engine; facilitated the growth of the public Internet; and funded research on the scientific basis for countless other applications and technologies. NSF has advanced the development of human capital and ideas for future advances in computing and its applications. This account is the first comprehensive coverage of NSF's role in the extraordinary growth and expansion of modern computing and its use. It will appeal to historians of computing, policy makers and leaders in government and academia, and individuals interested in the history and development of computing and the NSF.",
|
||||
"bookTitle": "Computing and the National Science Foundation, 1950--2016: Building a Foundation for Modern Computing",
|
||||
"itemID": "10.5555/3336323.C5474411",
|
||||
"libraryCatalog": "ACM Digital Library",
|
||||
|
|
@ -550,7 +536,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/10.1145/3264631.3264634",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -559,13 +544,13 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Gross",
|
||||
"firstName": "Mikaylah",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Bolchini",
|
||||
"firstName": "Davide",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -591,7 +576,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/10.1145/2854146",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -600,13 +584,13 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Potvin",
|
||||
"firstName": "Rachel",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Levenberg",
|
||||
"firstName": "Josh",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -620,7 +604,7 @@ var testCases = [
|
|||
"libraryCatalog": "ACM Digital Library",
|
||||
"pages": "78–87",
|
||||
"publicationTitle": "Communications of the ACM",
|
||||
"url": "https://dl.acm.org/doi/10.1145/2854146",
|
||||
"url": "https://doi.org/10.1145/2854146",
|
||||
"volume": "59",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -637,7 +621,6 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dl.acm.org/doi/book/10.5555/1087674",
|
||||
"detectedItemType": "thesis",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "thesis",
|
||||
|
|
@ -646,7 +629,7 @@ var testCases = [
|
|||
{
|
||||
"lastName": "Yuan",
|
||||
"firstName": "Wei",
|
||||
"creatorTypeID": 8,
|
||||
"creatorTypeID": 1,
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
391
ACM Queue.js
391
ACM Queue.js
|
|
@ -1,391 +0,0 @@
|
|||
{
|
||||
"translatorID": "212ffcc8-927c-4e84-a097-bd24fd4a44b6",
|
||||
"label": "ACM Queue",
|
||||
"creator": "Bogdan Lynn",
|
||||
"target": "^https://queue\\.acm\\.org/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-12-04 18:10:19"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2025 Bogdan Lynn
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('detail.cfm?id=')) {
|
||||
return 'journalArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('a[href*="detail.cfm?id="]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
// Skip links to specific parts of the article, like #comments,
|
||||
// since those normally appear below the actual top-level link
|
||||
if (href.includes("#")) continue;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
// DOI can be found in the URL of the PDF link
|
||||
let pdfUrl = doc.querySelector('a[href*="/doi/pdf"]');
|
||||
let doi = pdfUrl.href.split("/pdf/")[1];
|
||||
let translate = Zotero.loadTranslator("search");
|
||||
// DOI Content Negotiation translator
|
||||
translate.setTranslator("b28d0d42-8549-4c6d-83fc-8382874a5cb9");
|
||||
translate.setSearch({ itemType: "journalArticle", DOI: doi });
|
||||
|
||||
// Do nothing on error
|
||||
translate.setHandler("error", () => {});
|
||||
translate.setHandler("itemDone", (obj, item) => {
|
||||
item.publicationTitle = "ACM Queue";
|
||||
item.publisher = "Association for Computing Machinery";
|
||||
|
||||
// 'DOI Content Negotiation' translator does not add attachments
|
||||
let pdfUrl = doc.querySelector('a[href*="/doi/pdf"]');
|
||||
item.attachments.push({
|
||||
url: pdfUrl.href,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
item.complete();
|
||||
});
|
||||
|
||||
// Try to resolve the DOI, and if it does not work, scrape the DOM.
|
||||
try {
|
||||
await translate.translate();
|
||||
return;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(`Failed to resolve DOI. Scrape the page.`);
|
||||
}
|
||||
await scrapeDocument(doc, url);
|
||||
}
|
||||
|
||||
|
||||
async function scrapeDocument(doc, url) {
|
||||
let item = new Zotero.Item("journalArticle");
|
||||
item.title = text(doc, "h1");
|
||||
item.publicationTitle = "ACM Queue";
|
||||
item.publisher = "Association for Computing Machinery";
|
||||
item.journalAbbreviation = "Queue";
|
||||
item.language = "en";
|
||||
item.ISSN = "1542-7730";
|
||||
item.url = url;
|
||||
|
||||
// Extract volume and issue from "Volume X, issue Y" at the top
|
||||
let descriptor = text(doc, ".descriptor").toLowerCase();
|
||||
let re = /^volume\s+(\d+),\s*issue\s+(\d+)\s*$/i;
|
||||
let matches = descriptor.match(re) || [];
|
||||
item.volume = matches[1];
|
||||
item.issue = matches[2];
|
||||
|
||||
// Add PDF attachment and DOI
|
||||
let pdfUrl = doc.querySelector('a[href*="/doi/pdf"]');
|
||||
let doi = pdfUrl.href.split("/pdf/")[1];
|
||||
item.DOI = doi;
|
||||
item.attachments.push({
|
||||
url: pdfUrl.href,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
|
||||
// Some info needs to be fetched from the page of the entire issue
|
||||
// because it appears in difference places on the article page
|
||||
let issueDoc = await requestDocument(attr(doc, ".descriptor", "href"));
|
||||
|
||||
// Fetch date
|
||||
let dateContainer = text(issueDoc, "#lead p");
|
||||
let date = dateContainer.split(" ").slice(-2).join(" ");
|
||||
if (date.includes("/")) {
|
||||
date = date.split("/")[1];
|
||||
}
|
||||
item.date = date;
|
||||
|
||||
// Find link to the article on the page of the issue
|
||||
let searchParams = new URLSearchParams(url.split("?")[1]);
|
||||
let id = searchParams.get("id");
|
||||
let articleLinkOnissueDoc = issueDoc.querySelector(`a[href*="detail.cfm?id=${id}"]`);
|
||||
// Fetch abstract below the link
|
||||
item.abstractNote = articleLinkOnissueDoc.parentNode.nextElementSibling.textContent;
|
||||
// Fetch creators below the abstract
|
||||
let potentialAuthors = articleLinkOnissueDoc.parentNode.nextElementSibling.nextElementSibling;
|
||||
if (potentialAuthors?.classList.contains("meta")) {
|
||||
let creators = potentialAuthors.textContent.split(",");
|
||||
for (let creator of creators) {
|
||||
item.creators.push(ZU.cleanAuthor(creator, "author"));
|
||||
}
|
||||
}
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3664275",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Make Two Trips: Larry David's New Year's resolution works for IT too.",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Thomas A.",
|
||||
"lastName": "Limoncelli"
|
||||
}
|
||||
],
|
||||
"date": "2024-04-30",
|
||||
"DOI": "10.1145/3664275",
|
||||
"ISSN": "1542-7730, 1542-7749",
|
||||
"abstractNote": "Whether your project is as simple as carrying groceries into the house or as complex as a multiyear engineering project, \"make two trips\" can simplify the project, reduce the chance of error, improve the probability of success, and lead to easier explanations.",
|
||||
"issue": "2",
|
||||
"journalAbbreviation": "Queue",
|
||||
"language": "en",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "5-14",
|
||||
"publicationTitle": "ACM Queue",
|
||||
"shortTitle": "Make Two Trips",
|
||||
"url": "https://dl.acm.org/doi/10.1145/3664275",
|
||||
"volume": "22",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3762991",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Understanding the Harm Teens Experience on Social Media",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Arturo",
|
||||
"lastName": "Béjar",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "August 2025",
|
||||
"DOI": "10.1145/3762991",
|
||||
"ISSN": "1542-7730",
|
||||
"abstractNote": "The current approach to online safety, focusing on objectively harmful content and deletion or downranking, is necessary but not sufficient, as it addresses only a small fraction of the harm that teens experience. In order to understand harm, it is essential to understand it from their perspective by surveying and creating safety tools and reporting that make it easy to capture what happens and provide immediate help. Many of the recommendations in this article come from what you learn when you analyze behavioral correlates: that you need approaches that rely on conduct in context, better personalization, and providing feedback to actors.",
|
||||
"issue": "4",
|
||||
"journalAbbreviation": "Queue",
|
||||
"language": "en",
|
||||
"libraryCatalog": "ACM Queue",
|
||||
"publicationTitle": "ACM Queue",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3762991",
|
||||
"volume": "23",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3546935",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "I'm Probably Less Deterministic Than I Used to Be: Embracing randomness is necessary in cloud environments.",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Pat",
|
||||
"lastName": "Helland"
|
||||
}
|
||||
],
|
||||
"date": "2022-06-30",
|
||||
"DOI": "10.1145/3546935",
|
||||
"ISSN": "1542-7730, 1542-7749",
|
||||
"abstractNote": "In my youth, I thought the universe was ruled by cause and effect like a big clock. In this light, computing made sense. Now I see that both life and computing can be a crapshoot, and that has given me a new peace.",
|
||||
"issue": "3",
|
||||
"journalAbbreviation": "Queue",
|
||||
"language": "en",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "5-13",
|
||||
"publicationTitle": "ACM Queue",
|
||||
"shortTitle": "I'm Probably Less Deterministic Than I Used to Be",
|
||||
"url": "https://dl.acm.org/doi/10.1145/3546935",
|
||||
"volume": "20",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3501293",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Federated Learning and Privacy",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Kallista",
|
||||
"lastName": "Bonawitz",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Peter",
|
||||
"lastName": "Kairouz",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Brendan",
|
||||
"lastName": "McMahan",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Daniel",
|
||||
"lastName": "Ramage",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "September-October 2021",
|
||||
"DOI": "10.1145/3494834.3501293",
|
||||
"ISSN": "1542-7730",
|
||||
"abstractNote": "Centralized data collection can expose individuals to privacy risks and organizations to legal risks if data is not properly managed. Federated learning is a machine learning setting where multiple entities collaborate in solving a machine learning problem, under the coordination of a central server or service provider. Each client's raw data is stored locally and not exchanged or transferred; instead, focused updates intended for immediate aggregation are used to achieve the learning objective. This article provides a brief introduction to key concepts in federated learning and analytics with an emphasis on how privacy technologies may be combined in real-world systems and how their use charts a path toward societal benefit from aggregate statistics in new domains and with minimized risk to individuals and to the organizations who are custodians of the data.",
|
||||
"issue": "5",
|
||||
"journalAbbreviation": "Queue",
|
||||
"language": "en",
|
||||
"libraryCatalog": "ACM Queue",
|
||||
"publicationTitle": "ACM Queue",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3501293",
|
||||
"volume": "19",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3773095",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Memory Safety for Skeptics",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Andrew Lilley",
|
||||
"lastName": "Brinker",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "October 2025",
|
||||
"DOI": "10.1145/3773095",
|
||||
"ISSN": "1542-7730",
|
||||
"abstractNote": "The state of possibility with memory safety today is similar to the state of automobile safety just prior to the widespread adoption of mandatory seat-belt laws. As car manufacturers began to integrate seat belts as a standard feature across their model lines and states began to require that drivers wear seat belts while driving, the rate of traffic fatalities and severity of traffic-related injuries dropped drastically. Seat belts did not solve automobile safety, but they credibly improved it, and at remarkably low cost.",
|
||||
"issue": "5",
|
||||
"journalAbbreviation": "Queue",
|
||||
"language": "en",
|
||||
"libraryCatalog": "ACM Queue",
|
||||
"publicationTitle": "ACM Queue",
|
||||
"url": "https://queue.acm.org/detail.cfm?id=3773095",
|
||||
"volume": "23",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/issuedetail.cfm?issue=2838344",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://queue.acm.org/listing.cfm?item_topic=Blockchain&qc_type=theme_list&filter=Blockchain&page_title=Blockchain&order=desc",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -2,81 +2,76 @@
|
|||
"translatorID": "938ebe32-2b2e-4349-a5b3-b3a05d3de627",
|
||||
"label": "ACS Publications",
|
||||
"creator": "Sean Takats, Michael Berkowitz, Santawort, and Aurimas Vinckevicius",
|
||||
"target": "^https?://pubs\\.acs\\.org/(toc/|journal/|topic/|isbn/\\d|doi/(full/|abs/|epdf/|book/)?10\\.|action/(doSearch\\?|showCitFormats\\?.*doi))",
|
||||
"target": "^https?://pubs\\.acs\\.org/(toc/|journal/|topic/|isbn/\\d|doi/(full/|abs/)?10\\.|action/doSearch\\?)",
|
||||
"minVersion": "4.0.5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-09-30 13:50:18"
|
||||
"lastUpdated": "2019-10-07 09:04:25"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2008 Sean Takats, Michael Berkowitz, Santawort, Aurimas
|
||||
Vinckevicius, Philipp Zumstein, and other contributors.
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
function getSearchResults(doc, checkOnly, itemOpts) {
|
||||
var items = {}, found = false;
|
||||
var rows = doc.querySelectorAll('.issue-item_title a, .teaser_title a');
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
var doi = getDoi(href);
|
||||
if (!doi) continue;
|
||||
if (!href || !title || !doi) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
items[doi] = title;
|
||||
|
||||
// Not sure if this is still working on the new websites...
|
||||
itemOpts[doi] = {};
|
||||
|
||||
/*
|
||||
//check if article contains supporting info,
|
||||
//so we don't have to waste an HTTP request later if it doesn't
|
||||
var articleBox = titles[i].parentNode.parentNode;
|
||||
if (!articleBox.classList.contains('articleBox')) {
|
||||
// e.g. Most Recently Published under Subject Search
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ZU.xpath(articleBox, './/a[text()="Supporting Info"]').length) {
|
||||
itemOpts[doi].hasSupp = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
// Return the DOI indicated by the URL, or null when no DOI is found
|
||||
// The input should be a properly encoded URL
|
||||
function getDoi(url) {
|
||||
let urlObj = new URL(url);
|
||||
let doi = decodeURIComponent(urlObj.pathname).match(/^\/doi\/(?:.+\/)?(10\.\d{4,}\/.+)$/);
|
||||
if (doi) {
|
||||
doi = doi[1];
|
||||
var m = url.match(/https?:\/\/[^/]*\/doi\/(?:abs\/|full\/)?(10\.[^?#]+)/);
|
||||
if (m) {
|
||||
var doi = m[1];
|
||||
if (doi.includes("prevSearch")) {
|
||||
doi = doi.substring(0, doi.indexOf("?"));
|
||||
}
|
||||
return decodeURIComponent(doi);
|
||||
}
|
||||
else {
|
||||
doi = urlObj.searchParams.get("doi");
|
||||
}
|
||||
return doi;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** ***************************
|
||||
* BEGIN: Supplementary data *
|
||||
*****************************/
|
||||
// Get supplementary file names either from the Supporting Info page or the tooltip
|
||||
function getSuppFiles(div) {
|
||||
var fileNames = ZU.xpath(div, './/li//li');
|
||||
var attach = [];
|
||||
for (var i = 0, n = fileNames.length; i < n; i++) {
|
||||
attach.push(fileNames[i].textContent.trim().replace(/\s[\s\S]+/, ''));
|
||||
}
|
||||
return attach;
|
||||
}
|
||||
|
||||
var suppTypeMap = {
|
||||
txt: 'text/plain',
|
||||
csv: 'text/csv',
|
||||
bz2: 'application/x-bzip2',
|
||||
gz: 'application/gzip',
|
||||
zip: 'application/zip',
|
||||
pdf: 'application/pdf',
|
||||
doc: 'application/msword',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
|
|
@ -84,33 +79,28 @@ var suppTypeMap = {
|
|||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
};
|
||||
|
||||
function getSupplements(doc, supplementAsLink = false) {
|
||||
let supplements = [];
|
||||
// Note that the lists of supplements are duplicated in the main
|
||||
// content side and right-side panel (if any). We want to confine it to
|
||||
// one (or the only) side in order to avoid having to deduplicate.
|
||||
let supplementLinks = doc.querySelectorAll(".article_content-left .suppl-anchor");
|
||||
for (let i = 0; i < supplementLinks.length; i++) {
|
||||
let elem = supplementLinks[i];
|
||||
let url = elem.href;
|
||||
if (!url) continue;
|
||||
let pathComponents = url.replace(/[?#].+$/, "").split(".");
|
||||
// possible location of file extension (following the last dot)
|
||||
let ext = pathComponents[pathComponents.length - 1].toLowerCase();
|
||||
let mimeType = suppTypeMap[ext];
|
||||
// Only save file when MIME type is known *and* when we aren't
|
||||
// specifically told otherwise
|
||||
let snapshot = Boolean(!supplementAsLink && mimeType);
|
||||
// The "title" (text describing what the supplement file is for) can be
|
||||
// substantially long, while the filename is redundant (and it doesn't
|
||||
// inform the user that the file is meant to be a supplement). We
|
||||
// simply number them in the order they appear.
|
||||
let title = `Supplement ${i + 1}`;
|
||||
let attachment = { title, url, snapshot };
|
||||
if (mimeType) attachment.mimeType = mimeType;
|
||||
supplements.push(attachment);
|
||||
function getSuppMimeType(fileName) {
|
||||
var ext = fileName.substr(fileName.lastIndexOf('.') + 1);
|
||||
var mimeType = suppTypeMap[ext];
|
||||
return mimeType ? mimeType : undefined;
|
||||
}
|
||||
|
||||
function attachSupp(item, doi, opts) {
|
||||
if (!opts.attach) return;
|
||||
if (!item.attachments) item.attachments = [];
|
||||
var attachment;
|
||||
for (var i = 0, n = opts.attach.length; i < n; i++) {
|
||||
attachment = {
|
||||
title: opts.attach[i]
|
||||
};
|
||||
attachment.url = '/doi/suppl/' + doi + '/suppl_file/' + attachment.title;
|
||||
attachment.mimeType = getSuppMimeType(attachment.title);
|
||||
if (opts.attachAsLink || !attachment.mimeType) { // don't download unknown file types
|
||||
attachment.snapshot = false;
|
||||
}
|
||||
|
||||
item.attachments.push(attachment);
|
||||
}
|
||||
return supplements;
|
||||
}
|
||||
|
||||
/** *************************
|
||||
|
|
@ -121,28 +111,7 @@ function detectWeb(doc, url) {
|
|||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
let urlObj = new URL(url);
|
||||
// standalone "download citation" page
|
||||
if (urlObj.pathname === "/action/showCitFormats"
|
||||
&& urlObj.searchParams.get("doi")) {
|
||||
// May be inaccurate, but better than not detecting
|
||||
return "journalArticle";
|
||||
}
|
||||
// epdf viewer web app
|
||||
if (urlObj.pathname.startsWith("/doi/epdf/")) {
|
||||
// TODO: check if "epdf" viewer is always for journal articles
|
||||
return "journalArticle";
|
||||
}
|
||||
// books such as https://pubs.acs.org/doi/book/10.1021/acsguide
|
||||
if (urlObj.pathname.startsWith("/doi/book/")) {
|
||||
return "book";
|
||||
}
|
||||
if (doc.querySelector("#returnToBook")) {
|
||||
// Some of them may be conference articles, but the RIS doesn't say so
|
||||
return "bookSection";
|
||||
}
|
||||
else if (getDoi(url)) {
|
||||
// TODO: check if this block still works
|
||||
var type = doc.getElementsByClassName("content-navigation__contentType");
|
||||
if (type.length && type[0].textContent.includes("Chapter")) {
|
||||
return "bookSection";
|
||||
|
|
@ -154,117 +123,160 @@ function detectWeb(doc, url) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function cleanNumberField(item, field) {
|
||||
if (item[field]) {
|
||||
let n = parseInt(item[field]);
|
||||
if (n <= 0 || isNaN(n)) {
|
||||
delete item[field];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In most cases the URL contains the DOI which is sufficient for obtaining the
|
||||
// RIS, so there's no need to download the document if it's not already there.
|
||||
// But when supplements as attachments are desired, we need the actual document
|
||||
// for the supplement links. Our convention here is to pass falsy as the "doc"
|
||||
// argument when supplements are not requested, and the actual doc (maybe
|
||||
// fetched by us) when we want the supplements.
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
let attachSupplement = false;
|
||||
let supplementAsLink = false;
|
||||
function doWeb(doc, url) {
|
||||
var opts = {};
|
||||
// reduce some overhead by fetching these only once
|
||||
if (Z.getHiddenPref) {
|
||||
attachSupplement = Z.getHiddenPref("attachSupplementary");
|
||||
supplementAsLink = Z.getHiddenPref("supplementaryAsLink");
|
||||
opts.attachSupp = Z.getHiddenPref("attachSupplementary");
|
||||
opts.attachAsLink = Z.getHiddenPref("supplementaryAsLink");
|
||||
}
|
||||
|
||||
var itemOpts = {};
|
||||
if (detectWeb(doc, url) == "multiple") { // search
|
||||
let items = await Z.selectItems(getSearchResults(doc));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(
|
||||
attachSupplement && await requestDocument(url),
|
||||
url,
|
||||
supplementAsLink
|
||||
);
|
||||
await delay(500);
|
||||
}
|
||||
Zotero.selectItems(getSearchResults(doc, false, itemOpts), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dois = [];
|
||||
for (let i in items) {
|
||||
itemOpts[i].pdf = '/doi/pdf/' + i;
|
||||
dois.push({ doi: i, opts: itemOpts[i] });
|
||||
}
|
||||
|
||||
scrape(dois, opts);
|
||||
});
|
||||
}
|
||||
else {
|
||||
// single article
|
||||
await scrape(attachSupplement && doc, url, supplementAsLink);
|
||||
}
|
||||
}
|
||||
|
||||
function delay(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
async function scrape(doc, url, supplementAsLink) {
|
||||
let doi = getDoi(url);
|
||||
|
||||
if (doc && /\/action\/showCitFormats\?|\/doi\/epdf\//.test(url)) {
|
||||
// standalone "export citation" page or "epdf viewer", *and*
|
||||
// supplements are desired; we need to fetch the actual article page
|
||||
// and scrape that
|
||||
url = `https://pubs.acs.org/doi/${doi}`;
|
||||
doc = await requestDocument(url);
|
||||
}
|
||||
|
||||
let risURL = new URL("/action/downloadCitation?include=abs&format=ris&direct=true", url);
|
||||
risURL.searchParams.set("doi", doi);
|
||||
risURL.searchParams.set("downloadFileName", doi.replace(/^10\.\d{4,}\//, ""));
|
||||
let risText = await requestText(risURL.href, { headers: { Referer: url } });
|
||||
// Delete redundant DOI info
|
||||
risText = risText.replace(/\nN1 {2}- doi:[^\n]+/, "");
|
||||
// Fix noise in DO field
|
||||
risText = risText.replace("\nDO - doi:", "\nDO - ");
|
||||
// Fix the wrong mapping for journal abbreviations
|
||||
risText = risText.replace("\nJO -", "\nJ2 -");
|
||||
// Use publication date when available
|
||||
if (risText.includes("\nDA -")) {
|
||||
risText = risText.replace(/\nY1 {2}- [^\n]*/, "")
|
||||
.replace("\nDA -", "\nY1 -");
|
||||
}
|
||||
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
// RIS
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(risText);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
item.attachments = [];
|
||||
if (/\/doi\/book\//.test(url)) {
|
||||
// books as standalone items don't have full pdfs (TODO: verify)
|
||||
if (doc) {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
url: url,
|
||||
mimeType: "text/html"
|
||||
});
|
||||
else { // single article
|
||||
var doi = getDoi(url);
|
||||
Zotero.debug("DOI= " + doi);
|
||||
// we can determine file names from the tooltip, which saves us an HTTP request
|
||||
var suppTip = doc.getElementById('suppTipDiv');
|
||||
if (opts.attachSupp && suppTip) {
|
||||
try {
|
||||
opts.attach = getSuppFiles(suppTip, opts);
|
||||
}
|
||||
catch (e) {
|
||||
Z.debug("Error getting supplementary files.");
|
||||
Z.debug(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// standard pdf
|
||||
|
||||
// if we couldn't find this on the individual item page,
|
||||
// then it doesn't have supp info anyway. This way we know not to check later
|
||||
if (!opts.attach) opts.attach = [];
|
||||
|
||||
itemOpts.pdf = ZU.xpathText(doc, '(//a[i[contains(@class, "icon-file-pdf-o")]]/@href)[1]') || '/doi/pdf/' + doi;
|
||||
|
||||
scrape([{ doi: doi, opts: itemOpts }], opts);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(items, opts) {
|
||||
for (var i = 0, n = items.length; i < n; i++) {
|
||||
processCallback(items[i], opts);
|
||||
}
|
||||
}
|
||||
|
||||
function processCallback(fetchItem, opts) {
|
||||
var baseurl = "/action/downloadCitation";
|
||||
var doi = fetchItem.doi;
|
||||
var post = "https//pubs.acs.org/action/downloadCitation?direct=true&doi=" + encodeURIComponent(fetchItem.doi) + "&format=ris&include=abs&submit=Download+Citation";
|
||||
ZU.doPost(baseurl, post, function (text) {
|
||||
// Fix the RIS doi mapping
|
||||
text = text.replace("\nN1 - doi:", "\nDO - ");
|
||||
// Fix the wrong mapping for journal abbreviations
|
||||
text = text.replace("\nJO -", "\nJ2 -");
|
||||
// Use publication date when available
|
||||
if (text.includes("\nDA -")) {
|
||||
text = text.replace(/\nY1 {2}- [^\n]*/, "")
|
||||
.replace("\nDA -", "\nY1 -");
|
||||
}
|
||||
// Zotero.debug("ris= "+ text);
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
item.attachments = [];
|
||||
|
||||
// standard pdf and snapshot
|
||||
if (fetchItem.opts.pdf) {
|
||||
item.attachments.push({
|
||||
title: "Full Text PDF",
|
||||
url: fetchItem.opts.pdf,
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
item.attachments.push({
|
||||
title: "Full Text PDF",
|
||||
url: `/doi/pdf/${doi}`,
|
||||
mimeType: "application/pdf"
|
||||
title: "ACS Full Text Snapshot",
|
||||
url: '/doi/full/' + doi,
|
||||
mimeType: "text/html"
|
||||
});
|
||||
}
|
||||
// supplements
|
||||
if (doc) {
|
||||
item.attachments.push(...getSupplements(doc, supplementAsLink));
|
||||
}
|
||||
// Cleanup fields that may contain invalid numeric values
|
||||
cleanNumberField(item, "numberOfVolumes");
|
||||
cleanNumberField(item, "numPages");
|
||||
item.complete();
|
||||
|
||||
// supplementary data
|
||||
try {
|
||||
if (opts.attachSupp && opts.attach) {
|
||||
// came from individual item page
|
||||
attachSupp(item, doi, opts);
|
||||
}
|
||||
else if (opts.attachSupp && fetchItem.opts.hasSupp) {
|
||||
// was a search result and has supp info
|
||||
var suppUrl = '/doi/suppl/' + doi;
|
||||
|
||||
if (opts.attachAsLink) {
|
||||
// if we're only attaching links, it's not worth linking to each doc
|
||||
item.attachments.push({
|
||||
title: "Supporting Information",
|
||||
url: suppUrl,
|
||||
mimeType: 'text/html',
|
||||
snapshot: false
|
||||
});
|
||||
}
|
||||
else {
|
||||
ZU.processDocuments(suppUrl, function (suppDoc) {
|
||||
try {
|
||||
var div = suppDoc.getElementById('supInfoBox');
|
||||
if (div) {
|
||||
var files = getSuppFiles(div);
|
||||
attachSupp(item, doi, {
|
||||
attach: files,
|
||||
attachAsLink: opts.attachAsLink
|
||||
});
|
||||
}
|
||||
else {
|
||||
Z.debug("Div not found");
|
||||
item.attachments.push({
|
||||
title: "Supporting Information",
|
||||
url: suppUrl,
|
||||
mimeType: 'text/html',
|
||||
snapshot: false
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Z.debug("Error attaching supplementary files.");
|
||||
Z.debug(e);
|
||||
}
|
||||
item.complete();
|
||||
}, null, function () {
|
||||
item.complete();
|
||||
});
|
||||
return; // don't call item.complete() yet
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Z.debug("Error attaching supplementary files.");
|
||||
Z.debug(e);
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
|
|
@ -308,6 +320,10 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -346,6 +362,7 @@ var testCases = [
|
|||
"bookTitle": "Aquatic Redox Chemistry",
|
||||
"extra": "DOI: 10.1021/bk-2011-1071.ch005",
|
||||
"libraryCatalog": "ACS Publications",
|
||||
"numberOfVolumes": "0",
|
||||
"pages": "85-111",
|
||||
"publisher": "American Chemical Society",
|
||||
"series": "ACS Symposium Series",
|
||||
|
|
@ -357,6 +374,10 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -414,6 +435,10 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -422,6 +447,11 @@ var testCases = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/isbn/9780841239999",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/journal/acbcct",
|
||||
|
|
@ -431,203 +461,6 @@ var testCases = [
|
|||
"type": "web",
|
||||
"url": "https://pubs.acs.org/action/doSearch?text1=zotero&field1=AllField",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/doi/book/10.1021/acsguide",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "The ACS Guide to Scholarly Communication",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Banik",
|
||||
"firstName": "Gregory M.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Baysinger",
|
||||
"firstName": "Grace",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Kamat",
|
||||
"firstName": "Prashant V.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Pienta",
|
||||
"firstName": "Norbert",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2019-10-02",
|
||||
"ISBN": "9780841235861",
|
||||
"extra": "DOI: 10.1021/acsguide",
|
||||
"libraryCatalog": "ACS Publications",
|
||||
"publisher": "American Chemical Society",
|
||||
"series": "ACS Guide to Scholarly Communication",
|
||||
"url": "https://doi.org/10.1021/acsguide",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/action/showCitFormats?doi=10.1021%2Facscentsci.3c00243",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Generic Platform for the Multiplexed Targeted Electrochemical Detection of Osteoporosis-Associated Single Nucleotide Polymorphisms Using Recombinase Polymerase Solid-Phase Primer Elongation and Ferrocene-Modified Nucleoside Triphosphates",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Ortiz",
|
||||
"firstName": "Mayreli",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Jauset-Rubio",
|
||||
"firstName": "Miriam",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Trummer",
|
||||
"firstName": "Olivia",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Foessl",
|
||||
"firstName": "Ines",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Kodr",
|
||||
"firstName": "David",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Acero",
|
||||
"firstName": "Josep Lluís",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Botero",
|
||||
"firstName": "Mary Luz",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Biggs",
|
||||
"firstName": "Phil",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Lenartowicz",
|
||||
"firstName": "Daniel",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Trajanoska",
|
||||
"firstName": "Katerina",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Rivadeneira",
|
||||
"firstName": "Fernando",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Hocek",
|
||||
"firstName": "Michal",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Obermayer-Pietsch",
|
||||
"firstName": "Barbara",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "O’Sullivan",
|
||||
"firstName": "Ciara K.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-08-23",
|
||||
"DOI": "10.1021/acscentsci.3c00243",
|
||||
"ISSN": "2374-7943",
|
||||
"abstractNote": "Osteoporosis is a multifactorial disease influenced by genetic and environmental factors, which contributes to an increased risk of bone fracture, but early diagnosis of this disease cannot be achieved using current techniques. We describe a generic platform for the targeted electrochemical genotyping of SNPs identified by genome-wide association studies to be associated with a genetic predisposition to osteoporosis. The platform exploits isothermal solid-phase primer elongation with ferrocene-labeled nucleoside triphosphates. Thiolated reverse primers designed for each SNP were immobilized on individual gold electrodes of an array. These primers are designed to hybridize to the SNP site at their 3′OH terminal, and primer elongation occurs only where there is 100% complementarity, facilitating the identification and heterozygosity of each SNP under interrogation. The platform was applied to real blood samples, which were thermally lysed and directly used without the need for DNA extraction or purification. The results were validated using Taqman SNP genotyping assays and Sanger sequencing. The assay is complete in just 15 min with a total cost of 0.3€ per electrode. The platform is completely generic and has immense potential for deployment at the point of need in an automated device for targeted SNP genotyping with the only required end-user intervention being sample addition.",
|
||||
"issue": "8",
|
||||
"journalAbbreviation": "ACS Cent. Sci.",
|
||||
"libraryCatalog": "ACS Publications",
|
||||
"pages": "1591-1602",
|
||||
"publicationTitle": "ACS Central Science",
|
||||
"url": "https://doi.org/10.1021/acscentsci.3c00243",
|
||||
"volume": "9",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/doi/epdf/10.1021/acscentsci.3c00323",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Dynamics of Rayleigh Fission Processes in ∼100 nm Charged Aqueous Nanodrops",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Hanozin",
|
||||
"firstName": "Emeline",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Harper",
|
||||
"firstName": "Conner C.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "McPartlan",
|
||||
"firstName": "Matthew S.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Williams",
|
||||
"firstName": "Evan R.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-08-23",
|
||||
"DOI": "10.1021/acscentsci.3c00323",
|
||||
"ISSN": "2374-7943",
|
||||
"abstractNote": "Fission of micron-size charged droplets has been observed using optical methods, but little is known about fission dynamics and breakup of smaller nanosize droplets that are important in a variety of natural and industrial processes. Here, spontaneous fission of individual aqueous nanodrops formed by electrospray is investigated using charge detection mass spectrometry. Fission processes ranging from formation of just two progeny droplets in 2 ms to production of dozens of progeny droplets over 100+ ms are observed for nanodrops that are charged above the Rayleigh limit. These results indicate that Rayleigh fission is a continuum of processes that produce progeny droplets that vary widely in charge, mass, and number.",
|
||||
"issue": "8",
|
||||
"journalAbbreviation": "ACS Cent. Sci.",
|
||||
"libraryCatalog": "ACS Publications",
|
||||
"pages": "1611-1622",
|
||||
"publicationTitle": "ACS Central Science",
|
||||
"url": "https://doi.org/10.1021/acscentsci.3c00323",
|
||||
"volume": "9",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
664
ADS Bibcode.js
664
ADS Bibcode.js
|
|
@ -1,664 +0,0 @@
|
|||
{
|
||||
"translatorID": "09bd8037-a9bb-4f9a-b3b9-d18b2564b49e",
|
||||
"label": "ADS Bibcode",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "",
|
||||
"minVersion": "6.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 8,
|
||||
"lastUpdated": "2025-04-29 03:02:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
// Logic for accurate type detection. In general, the type in the RIS export is
|
||||
// fairly accurate. However, it may misidentify a proceedings book as JOUR (but
|
||||
// usually identifies conference papers fine). Theses are also identified as
|
||||
// JOUR in the RIS file. Preprints are usually correctly identified.
|
||||
function getRealType(bibStem, exportType) {
|
||||
if (/^(PhDT|MsT)/.test(bibStem)) {
|
||||
return "thesis";
|
||||
}
|
||||
|
||||
// Fix misidentifying full proceedings book as JOUR
|
||||
let volume = bibStem.substring(5, 9);
|
||||
if (volume === "conf" && exportType === "journalArticle") {
|
||||
return "book";
|
||||
}
|
||||
|
||||
return exportType;
|
||||
}
|
||||
|
||||
// https://github.com/yymao/adstex/blob/64989c9e75d7401ea2b33b546664cbc34cce6a27/adstex.py
|
||||
const bibcodeRe = /^\d{4}\D\S{13}[A-Z.:]$/;
|
||||
|
||||
function detectSearch(items) {
|
||||
return !!filterQuery(items).length;
|
||||
}
|
||||
|
||||
async function doSearch(items) {
|
||||
let bibcodes = filterQuery(items);
|
||||
if (!bibcodes.length) return;
|
||||
await scrape(bibcodes);
|
||||
}
|
||||
|
||||
function filterQuery(items) {
|
||||
if (!items) return [];
|
||||
|
||||
if (!items.length) items = [items];
|
||||
|
||||
// filter out invalid queries
|
||||
let bibcodes = [];
|
||||
for (let item of items) {
|
||||
if (item.adsBibcode && typeof item.adsBibcode == 'string') {
|
||||
let bibcode = item.adsBibcode.trim();
|
||||
if (bibcodeRe.test(bibcode)) {
|
||||
bibcodes.push(bibcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bibcodes;
|
||||
}
|
||||
|
||||
function extractId(url) {
|
||||
let m = url.match(/\/abs\/([^/]+)/);
|
||||
return m && decodeURIComponent(m[1]);
|
||||
}
|
||||
|
||||
function makePdfUrl(id) {
|
||||
return "https://ui.adsabs.harvard.edu/link_gateway/" + id + "/ARTICLE";
|
||||
}
|
||||
|
||||
// Detect if an item is from arXiv. This is necessary because bibcodes of older
|
||||
// arXiv preprints don't start with "arXiv"
|
||||
function isArXiv(item, bibStem) {
|
||||
if (item.DOI && item.DOI.startsWith("10.48550/")) return true;
|
||||
if (bibStem.startsWith("arXiv")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
async function scrape(ids) {
|
||||
let bootstrap = await requestJSON("https://api.adsabs.harvard.edu/v1/accounts/bootstrap");
|
||||
if (!bootstrap || !bootstrap.access_token) {
|
||||
throw new Error("ADS Bibcode: cannot obtain access token");
|
||||
}
|
||||
let body = JSON.stringify({ bibcode: ids, sort: ['no sort'] });
|
||||
let response = await requestJSON("https://api.adsabs.harvard.edu/v1/export/ris", {
|
||||
method: "POST",
|
||||
body,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${bootstrap.access_token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7"); // RIS
|
||||
translator.setString(response.export);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
let id = extractId(item.url);
|
||||
let bibStem = id.slice(4);
|
||||
|
||||
let type = getRealType(bibStem, item.itemType);
|
||||
if (type !== item.itemType) {
|
||||
Z.debug(`ADS Bibcode: changing item type: ${item.itemType} -> ${type}`);
|
||||
item.itemType = type;
|
||||
}
|
||||
|
||||
if (isArXiv(item, bibStem)) {
|
||||
item.itemType = "preprint";
|
||||
item.publisher = "arXiv";
|
||||
delete item.pages;
|
||||
delete item.publicationTitle;
|
||||
delete item.journalAbbreviation;
|
||||
}
|
||||
|
||||
item.extra = (item.extra || '') + `\nADS Bibcode: ${id}`;
|
||||
|
||||
// for thesis-type terminology, see
|
||||
// https://adsabs.harvard.edu/abs_doc/journals1.html
|
||||
if (item.itemType === "thesis") {
|
||||
if (bibStem.startsWith("PhDT")) {
|
||||
item.thesisType = "Ph.D. thesis";
|
||||
}
|
||||
else if (bibStem.startsWith("MsT")) {
|
||||
item.thesisType = "Masters thesis";
|
||||
}
|
||||
delete item.journalAbbreviation; // from spurious JO tag
|
||||
delete item.publicationTitle;
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
url: makePdfUrl(id),
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
|
||||
if (item.journalAbbreviation == item.publicationTitle) {
|
||||
delete item.journalAbbreviation;
|
||||
}
|
||||
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
|
||||
item.libraryCatalog = 'NASA ADS';
|
||||
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2022MSSP..16208070W"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Research and application of neural network for tread wear prediction and optimization",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Wang",
|
||||
"firstName": "Meiqi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Jia",
|
||||
"firstName": "Sixian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Chen",
|
||||
"firstName": "Enli",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Yang",
|
||||
"firstName": "Shaopu",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Liu",
|
||||
"firstName": "Pengfei",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Qi",
|
||||
"firstName": "Zhuang",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022-01-01",
|
||||
"DOI": "10.1016/j.ymssp.2021.108070",
|
||||
"ISSN": "0888-3270",
|
||||
"abstractNote": "The wheel tread wear of heavy haul freight car in operation leads to shortened wheel turning period, reduced operation life, and poor train operation performance. In addition, wheel rail wear is a complex non-linear problem that integrates multiple disciplines. Thus, using a single physical or mathematical model to accurately describe and predict it is difficult. How to establish a model that could accurately predict wheel tread wear is an urgent problem and challenge that needs to be solved. In this paper, a tread wear prediction and optimization method based on chaotic quantum particle swarm optimization (CQPSO)-optimized derived extreme learning machine (DELM), namely CQPSO-DELM, is proposed to overcome this problem. First, an extreme learning machine model with derivative characteristics is proposed (DELM). Next, the chaos algorithm is introduced into the quantum particle swarm optimization algorithm to optimize the parameters of DELM. Then, through the CQPSO-DELM prediction model, the vehicle dynamics model simulates the maximum wheel tread wear under different test parameters to train and predict. Results show that the error performance index of the CQPSO-DELM prediction model is smaller than that of other algorithms. Thus, it could better reflect the influence of different parameters on the value of wheel tread wear. CQPSO is used to optimize the tread coordinates to obtain a wheel profile with low wear. The optimized wheel profile is fitted and reconstructed by the cubic non-uniform rational B-spline (NURBS) theory, and the optimized wear value of the tread is compared with the original wear value. The optimized wear value is less than the original wear value, thus verifying the effectiveness of the optimization model. The CQPSO-DELM model proposed in this paper could predict the wear value of different working conditions and tree shapes and solve the problem that different operating conditions and complex environment could have a considerable effect on the prediction of tread wear value. The optimization of wheel tread and the wear prediction of different tread shapes are realized from the angle of artificial intelligence for the first time.",
|
||||
"extra": "ADS Bibcode: 2022MSSP..16208070W",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"pages": "108070",
|
||||
"publicationTitle": "Mechanical Systems and Signal Processing",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2022MSSP..16208070W",
|
||||
"volume": "162",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "00-01"
|
||||
},
|
||||
{
|
||||
"tag": "99-00"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2021PhDT.........5C"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "thesis",
|
||||
"title": "Searching for the Astrophysical Gravitational-Wave Background and Prompt Radio Emission from Compact Binaries",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Callister",
|
||||
"firstName": "Thomas A.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-06-01",
|
||||
"abstractNote": "Gravitational-wave astronomy is now a reality. During my time at Caltech, the Advanced LIGO and Virgo observatories have detected gravitational waves from dozens of compact binary coalescences. All of these gravitational-wave events occurred in the relatively local Universe. In the first part of this thesis, I will instead look towards the remote Universe, investigating what LIGO and Virgo may be able to learn about cosmologically-distant compact binaries via observation of the stochastic gravitational-wave background. The stochastic gravitational-wave background is composed of the incoherent superposition of all distant, individually-unresolvable gravitational-wave sources. I explore what we learn from study of the gravitational-wave background, both about the astrophysics of compact binaries and the fundamental nature of gravitational waves. Of course, before we can study the gravitational-wave background we must first detect it. I therefore present searches for the gravitational-wave background using data from Advanced LIGO's first two observing runs, obtaining the most stringent upper limits to date on strength of the stochastic background. Finally, I consider how one might validate an apparent detection of the gravitational-wave background, confidently distinguishing a true astrophysical signal from spurious terrestrial artifacts. The second part of this thesis concerns the search for electromagnetic counterparts to gravitational-wave events. The binary neutron star merger GW170817 was accompanied by a rich set of electromagnetic counterparts spanning nearly the entire electromagnetic spectrum. Beyond these counterparts, compact binaries may additionally generate powerful radio transients at or near their time of merger. First, I consider whether there is a plausible connection between this so-called \"prompt radio emission\" and fast radio bursts — enigmatic radio transients of unknown origin. Next, I present the first direct search for prompt radio emission from a compact binary merger using the Owens Valley Radio Observatory Long Wavelength Array (OVRO-LWA). While no plausible candidates are identified, this effort successfully demonstrates the prompt radio follow-up of a gravitational-wave source, providing a blueprint for LIGO and Virgo follow-up in their O3 observing run and beyond.",
|
||||
"extra": "ADS Bibcode: 2021PhDT.........5C",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"thesisType": "Ph.D. thesis",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2021PhDT.........5C",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2021wfc..rept....8D"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"title": "WFC3 IR Blob Classification with Machine Learning",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Dauphin",
|
||||
"firstName": "F.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Medina",
|
||||
"firstName": "J. V.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "McCullough",
|
||||
"firstName": "P. R.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-06-01",
|
||||
"abstractNote": "IR blobs are small, circular, dark artifacts in WFC3 IR images caused by particulates that occasionally are deposited on a flat mirror that is nearly optically conjugate to the IR detector. Machine learning can potentially reduce the effort currently devoted to visually inspecting blobs. We describe how machine learning (ML) techniques have been implemented to develop software that will automatically find new IR blobs and notify the WFC3 Quicklook team. This report describes the data preparation, development of the ML model, and criteria for success. The results of our latest test cases demonstrate that the model finds blobs reliably, with the model correctly classifying blob and non-blob images 94% and 88% of the time, respectively. We also report tips and lessons learned from our experience in machine learning as a result of this project.",
|
||||
"extra": "ADS Bibcode: 2021wfc..rept....8D",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"pages": "8",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2021wfc..rept....8D",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Blobs"
|
||||
},
|
||||
{
|
||||
"tag": "Convolutional Neural Networks"
|
||||
},
|
||||
{
|
||||
"tag": "HST"
|
||||
},
|
||||
{
|
||||
"tag": "Hubble Space Telescope"
|
||||
},
|
||||
{
|
||||
"tag": "IR"
|
||||
},
|
||||
{
|
||||
"tag": "Machine Learning"
|
||||
},
|
||||
{
|
||||
"tag": "STScI"
|
||||
},
|
||||
{
|
||||
"tag": "Space Telescope Science Institute"
|
||||
},
|
||||
{
|
||||
"tag": "WFC3"
|
||||
},
|
||||
{
|
||||
"tag": "Wide Field Camera 3"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2021sti..book.....P"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Stochastic Thermodynamics: An Introduction",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Peliti",
|
||||
"firstName": "Luca",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Pigolotti",
|
||||
"firstName": "Simone",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-07-01",
|
||||
"abstractNote": "The first comprehensive graduate-level introduction to stochastic thermodynamics. Stochastic thermodynamics is a well-defined subfield of statistical physics that aims to interpret thermodynamic concepts for systems ranging in size from a few to hundreds of nanometers, the behavior of which is inherently random due to thermal fluctuations. This growing field therefore describes the nonequilibrium dynamics of small systems, such as artificial nanodevices and biological molecular machines, which are of increasing scientific and technological relevance. This textbook provides an up-to-date pedagogical introduction to stochastic thermodynamics, guiding readers from basic concepts in statistical physics, probability theory, and thermodynamics to the most recent developments in the field. Gradually building up to more advanced material, the authors consistently prioritize simplicity and clarity over exhaustiveness and focus on the development of readers' physical insight over mathematical formalism. This approach allows the reader to grow as the book proceeds, helping interested young scientists to enter the field with less effort and to contribute to its ongoing vibrant development. Chapters provide exercises to complement and reinforce learning. Appropriate for graduate students in physics and biophysics, as well as researchers, Stochastic Thermodynamics serves as an excellent initiation to this rapidly evolving field. Emphasizes a pedagogical approach to the subject Highlights connections with the thermodynamics of information Pays special attention to molecular biophysics applications Privileges physical intuition over mathematical formalism Solutions manual available on request for instructors adopting the book in a course",
|
||||
"extra": "ADS Bibcode: 2021sti..book.....P",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"shortTitle": "Stochastic Thermodynamics",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2021sti..book.....P",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2020jsrs.conf.....B"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Proceedings of the Journées Systèmes de Référence Spatio-temporels 2019 \"Astrometry, Earth Rotation and Reference System in the Gaia era\"",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Bizouard",
|
||||
"firstName": "Christian",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-09-01",
|
||||
"extra": "ADS Bibcode: 2020jsrs.conf.....B",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2020jsrs.conf.....B",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2020jsrs.conf..209S"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Atmospheric angular momentum related to Earth rotation studies: history and modern developments",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Salstein",
|
||||
"firstName": "D.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-09-01",
|
||||
"abstractNote": "It was noted some time ago that the angular momentum of the atmosphere varies, both regionally as well as in total. Given the conservation of angular momentum in the Earth system, except for known external torques, such variability implies transfer of the angular momentum across the atmosphere's lower boundary. As nearly all is absorbed by the Earth below, the solid Earth changes its overall rotation from this impact. Due to the large difference between in the moments of inertia of the atmosphere and Earth, relatively big differences in the atmosphere are translated as relatively very small differences in the Earth, measurable as changes in Earth rotation rate, and polar motion. The atmospheric angular momentum (AAM) is that due to the motion of the winds and to the changes in mass distribution, closely related to the atmosphere pressure patterns; its variability in the atmosphere is mirrored in the Earth rotation rate and polar motion. This connection between the global solid Earth properties and the global and regional atmosphere on a number of time scales, especially seasonal and interannual, was much appreciated by Barbara Kolaczek, with Jolanta Nastula, at the Space Research Center in Warsaw, and this was a subject of our collaborative studies. Many calculations were made of atmospheric angular momentum, leading to a service under the Global Geophysical Fluids Center of the IERS based on calculations using both operational meteorological series, determined for weather forecasting purposes, and retrospective analyses of the atmosphere. Theoretical development of the connection between the AAM, Earth rotation/polar motion, and also the angular momentum of the other geophysical fluids occurred at the same time that space-based observations and enhanced computer power were allowing improved skills for both weather analysis and forecasting. Hence better determination of the AAM became possible, which could be used as a measure for forecasting Earth rotation. Today we are looking at the atmosphere in combination with the ocean and other fluids, and also assessing the implications of climate variability on Earth rotation through climate model research. According to models of the Earth system, significant changes in winds appear to be a possible result of climate change, with implications for the Earth rotation parameters.",
|
||||
"conferenceName": "Astrometry, Earth Rotation, and Reference Systems in the GAIA era",
|
||||
"extra": "ADS Bibcode: 2020jsrs.conf..209S",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"pages": "209-213",
|
||||
"shortTitle": "Atmospheric angular momentum related to Earth rotation studies",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2020jsrs.conf..209S",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": [
|
||||
{
|
||||
"adsBibcode": "2002math.....11159P"
|
||||
},
|
||||
{
|
||||
"adsBibcode": "2003math......3109P"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"itemType": "preprint",
|
||||
"title": "The entropy formula for the Ricci flow and its geometric applications",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Perelman",
|
||||
"firstName": "Grisha",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2002-11-01",
|
||||
"DOI": "10.48550/arXiv.math/0211159",
|
||||
"abstractNote": "We present a monotonic expression for the Ricci flow, valid in all dimensions and without curvature assumptions. It is interpreted as an entropy for a certain canonical ensemble. Several geometric applications are given. In particular, (1) Ricci flow, considered on the space of riemannian metrics modulo diffeomorphism and scaling, has no nontrivial periodic orbits (that is, other than fixed points); (2) In a region, where singularity is forming in finite time, the injectivity radius is controlled by the curvature; (3) Ricci flow can not quickly turn an almost euclidean region into a very curved one, no matter what happens far away. We also verify several assertions related to Richard Hamilton's program for the proof of Thurston geometrization conjecture for closed three-manifolds, and give a sketch of an eclectic proof of this conjecture, making use of earlier results on collapsing with local lower curvature bound.",
|
||||
"extra": "ADS Bibcode: 2002math.....11159P",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"repository": "arXiv",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2002math.....11159P",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "53C"
|
||||
},
|
||||
{
|
||||
"tag": "Differential Geometry"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
},
|
||||
{
|
||||
"itemType": "preprint",
|
||||
"title": "Ricci flow with surgery on three-manifolds",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Perelman",
|
||||
"firstName": "Grisha",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2003-03-01",
|
||||
"DOI": "10.48550/arXiv.math/0303109",
|
||||
"abstractNote": "This is a technical paper, which is a continuation of math.DG/0211159. Here we construct Ricci flow with surgeries and verify most of the assertions, made in section 13 of that e-print; the exceptions are (1) the statement that manifolds that can collapse with local lower bound on sectional curvature are graph manifolds - this is deferred to a separate paper, since the proof has nothing to do with the Ricci flow, and (2) the claim on the lower bound for the volume of maximal horns and the smoothness of solutions from some time on, which turned out to be unjustified and, on the other hand, irrelevant for the other conclusions.",
|
||||
"extra": "ADS Bibcode: 2003math......3109P",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"repository": "arXiv",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2003math......3109P",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "53C"
|
||||
},
|
||||
{
|
||||
"tag": "Differential Geometry"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "1995LNP...463...51E"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Observations and Cosmological Models",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Ellis",
|
||||
"firstName": "G. F. R.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1995-01-01",
|
||||
"bookTitle": "Galaxies in the Young Universe",
|
||||
"extra": "DOI: 10.1007/BFb0102359\nADS Bibcode: 1995LNP...463...51E",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"pages": "51",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/1995LNP...463...51E",
|
||||
"volume": "463",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "1997MsT...........B"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "thesis",
|
||||
"title": "Comparative Analysis of Selected Radiation Effects in Medium Earth Orbits",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Bolin",
|
||||
"firstName": "Jennifer A.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1997-12-01",
|
||||
"abstractNote": "Satellite design is well developed for the common Low Earth Orbit (LEO) and Geosynchronous Orbit (GEO) and Highly Elliptical Orbits (HEO), i.e., Molniya, cases; Medium Earth Orbit (MEO) satellite design is a relatively new venture. MEO is roughly defined as being altitudes above LEO and below GEO. A primary concern, and a major reason for the delay in exploiting the MEO altitudes, has been the expected radiation environment and corresponding satellite degradation anticipated to occur at MEO altitudes. The presence of the Van Allen belts, a major source of radiation, along with the suitability of GEO and LEO orbits, has conventionally discouraged satellite placement in MEO. As conventional Earth orbits become increasingly crowded, MEO will become further populated. This thesis investigates the major sources of radiation (geomagnetically trapped particles, solar particle events and galactic cosmic radiation) with respect to specific Naval Research Laboratory (NRL) designated MEO (altitudes between 3,000 nautical miles (nmi) and 9,000 nmi; (inclination angle of 15 degrees). The contribution of each of these components to the total radiation experienced in MEO and the effects of the expected radiation on a representative spacecraft are analyzed in comparison to a baseline LEO orbit of 400 nmi and 70 degrees inclination. Dose depth curves are calculated for several configurations, and show that weight gains from necessary expected shielding are not extreme. The radiation effects considered include proton displacement dose and solar cell degradation.",
|
||||
"extra": "ADS Bibcode: 1997MsT...........B",
|
||||
"libraryCatalog": "NASA ADS",
|
||||
"thesisType": "Masters thesis",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/1997MsT...........B",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Aerospace Environments"
|
||||
},
|
||||
{
|
||||
"tag": "Astrophysics"
|
||||
},
|
||||
{
|
||||
"tag": "Cosmic Rays"
|
||||
},
|
||||
{
|
||||
"tag": "Degradation"
|
||||
},
|
||||
{
|
||||
"tag": "Elliptical Orbits"
|
||||
},
|
||||
{
|
||||
"tag": "Galactic Radiation"
|
||||
},
|
||||
{
|
||||
"tag": "Geosynchronous Orbits"
|
||||
},
|
||||
{
|
||||
"tag": "Low Earth Orbits"
|
||||
},
|
||||
{
|
||||
"tag": "Radiation Belts"
|
||||
},
|
||||
{
|
||||
"tag": "Radiation Effects"
|
||||
},
|
||||
{
|
||||
"tag": "Satellite Design"
|
||||
},
|
||||
{
|
||||
"tag": "Solar Activity"
|
||||
},
|
||||
{
|
||||
"tag": "Solar Cells"
|
||||
},
|
||||
{
|
||||
"tag": "Solar Corpuscular Radiation"
|
||||
},
|
||||
{
|
||||
"tag": "Solar Storms"
|
||||
},
|
||||
{
|
||||
"tag": "Unmanned Spacecraft"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
235
AEA Web.js
235
AEA Web.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-05-08 17:43:18"
|
||||
"lastUpdated": "2016-08-27 10:23:44"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -93,13 +93,6 @@ function scrape(doc, url) {
|
|||
//and another text node with the actual abstract.
|
||||
var abstract = ZU.xpathText(doc, '//section[contains(@class,"abstract")]/text()[last()]');
|
||||
item.abstractNote = abstract;
|
||||
|
||||
for (let jelCode of doc.querySelectorAll('.jel-codes .code')) {
|
||||
let jelTag = jelCode.nextSibling;
|
||||
if (jelTag && jelTag.textContent.trim()) {
|
||||
item.tags.push({ tag: jelTag.textContent.trim() });
|
||||
}
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
|
@ -109,7 +102,7 @@ function scrape(doc, url) {
|
|||
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
|
|
@ -140,7 +133,6 @@ var testCases = [
|
|||
"ISSN": "0895-3309",
|
||||
"abstractNote": "As economists endeavor to build better models of human behavior, they cannot ignore that humans are fundamentally a social species with interaction patterns that shape their behaviors. People's opinions, which products they buy, whether they invest in education, become criminals, and so forth, are all influenced by friends and acquaintances. Ultimately, the full network of relationships—how dense it is, whether some groups are segregated, who sits in central positions—affects how information spreads and how people behave. Increased availability of data coupled with increased computing power allows us to analyze networks in economic settings in ways not previously possible. In this paper, I describe some of the ways in which networks are helping economists to model and understand behavior. I begin with an example that demonstrates the sorts of things that researchers can miss if they do not account for network patterns of interaction. Next I discuss a taxonomy of network properties and how they impact behaviors. Finally, I discuss the problem of developing tractable models of network formation.",
|
||||
"issue": "4",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.aeaweb.org",
|
||||
"pages": "3-22",
|
||||
"publicationTitle": "Journal of Economic Perspectives",
|
||||
|
|
@ -150,46 +142,12 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Belief"
|
||||
},
|
||||
{
|
||||
"tag": "Communication"
|
||||
},
|
||||
{
|
||||
"tag": "Consumer Economics: Theory"
|
||||
},
|
||||
{
|
||||
"tag": "Consumer Economics: Theory, Search"
|
||||
},
|
||||
{
|
||||
"tag": "Economic Anthropology"
|
||||
},
|
||||
{
|
||||
"tag": "Economic Sociology; Economic Anthropology; Social and Economic Stratification"
|
||||
},
|
||||
{
|
||||
"tag": "Information and Knowledge"
|
||||
},
|
||||
{
|
||||
"tag": "Learning"
|
||||
},
|
||||
{
|
||||
"tag": "Network Formation and Analysis: Theory"
|
||||
},
|
||||
{
|
||||
"tag": "Search; Learning; Information and Knowledge; Communication; Belief; Unawareness"
|
||||
},
|
||||
{
|
||||
"tag": "Social and Economic Stratification"
|
||||
},
|
||||
{
|
||||
"tag": "Unawareness, Network Formation and Analysis: Theory, Economic Sociology"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
|
|
@ -219,7 +177,6 @@ var testCases = [
|
|||
"ISSN": "0002-8282",
|
||||
"abstractNote": "Using a model of statistical discrimination and educational sorting,\nwe explain why blacks get more education than whites of similar\ncognitive ability, and we explore how the Armed Forces Qualification\nTest (AFQT), wages, and education are related. The model suggests\nthat one should control for both AFQT and education when comparing\nthe earnings of blacks and whites, in which case a substantial\nblack-white wage differential emerges. We reject the hypothesis that\ndifferences in school quality between blacks and whites explain the\nwage and education differentials. Our findings support the view that\nsome of the black-white wage differential reflects the operation of the\nlabor market. (JEL I21, J15, J24, J31, J71)",
|
||||
"issue": "4",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.aeaweb.org",
|
||||
"pages": "1467-1496",
|
||||
"publicationTitle": "American Economic Review",
|
||||
|
|
@ -229,43 +186,12 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Analysis of Education"
|
||||
},
|
||||
{
|
||||
"tag": "Analysis of Education, Economics of Minorities and Races"
|
||||
},
|
||||
{
|
||||
"tag": "Economics of Minorities and Races; Non-labor Discrimination"
|
||||
},
|
||||
{
|
||||
"tag": "Human Capital; Skills; Occupational Choice; Labor Productivity"
|
||||
},
|
||||
{
|
||||
"tag": "Labor Discrimination"
|
||||
},
|
||||
{
|
||||
"tag": "Labor Productivity, Wage Level and Structure"
|
||||
},
|
||||
{
|
||||
"tag": "Non-labor Discrimination, Human Capital"
|
||||
},
|
||||
{
|
||||
"tag": "Occupational Choice"
|
||||
},
|
||||
{
|
||||
"tag": "Skills"
|
||||
},
|
||||
{
|
||||
"tag": "Wage Differentials, Labor Discrimination"
|
||||
},
|
||||
{
|
||||
"tag": "Wage Level and Structure; Wage Differentials"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
|
|
@ -295,7 +221,6 @@ var testCases = [
|
|||
"ISSN": "0895-3309",
|
||||
"abstractNote": "We can imagine a plausible case for government support of science based on traditional economic reasons of externalities and public goods. Yet when it comes to government support of grants from the National Science Foundation (NSF) for economic research, our sense is that many economists avoid critical questions, skimp on analysis, and move straight to advocacy. In this essay, we take a more skeptical attitude toward the efforts of the NSF to subsidize economic research. We offer two main sets of arguments. First, a key question is not whether NSF funding is justified relative to laissez-faire, but rather, what is the marginal value of NSF funding given already existing government and nongovernment support for economic research? Second, we consider whether NSF funding might more productively be shifted in various directions that remain within the legal and traditional purview of the NSF. Such alternative focuses might include data availability, prizes rather than grants, broader dissemination of economic insights, and more. Given these critiques, we suggest some possible ways in which the pattern of NSF funding, and the arguments for such funding, might be improved.",
|
||||
"issue": "3",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.aeaweb.org",
|
||||
"pages": "235-248",
|
||||
"publicationTitle": "Journal of Economic Perspectives",
|
||||
|
|
@ -305,146 +230,16 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Higher Education; Research Institutions"
|
||||
},
|
||||
{
|
||||
"tag": "Market for Economists, Higher Education"
|
||||
},
|
||||
{
|
||||
"tag": "Research Institutions, Technological Change: Government Policy"
|
||||
},
|
||||
{
|
||||
"tag": "Role of Economics"
|
||||
},
|
||||
{
|
||||
"tag": "Role of Economics; Role of Economists; Market for Economists"
|
||||
},
|
||||
{
|
||||
"tag": "Role of Economists"
|
||||
},
|
||||
{
|
||||
"tag": "Technological Change: Government Policy"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aeaweb.org/articles?id=10.1257/jel.20201641",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "The 1918 Influenza Pandemic and Its Lessons for COVID-19",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Brian",
|
||||
"lastName": "Beach",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Karen",
|
||||
"lastName": "Clay",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Martin",
|
||||
"lastName": "Saavedra",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022/03",
|
||||
"DOI": "10.1257/jel.20201641",
|
||||
"ISSN": "0022-0515",
|
||||
"abstractNote": "This article reviews the global health and economic consequences of the 1918 influenza pandemic, with a particular focus on topics that have seen a renewed interest because of COVID-19. We begin by providing an overview of key contextual and epidemiological details as well as the data that are available to researchers. We then examine the effects on mortality, fertility, and the economy in the short and medium run. The role of non-pharmaceutical interventions in shaping those outcomes is discussed throughout. We then examine longer-lasting health consequences and their impact on human capital accumulation and socioeconomic status. Throughout the paper we highlight important areas for future work.",
|
||||
"issue": "1",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.aeaweb.org",
|
||||
"pages": "41-84",
|
||||
"publicationTitle": "Journal of Economic Literature",
|
||||
"url": "https://www.aeaweb.org/articles?id=10.1257/jel.20201641",
|
||||
"volume": "60",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Aggregate Human Capital"
|
||||
},
|
||||
{
|
||||
"tag": "Aggregate Labor Productivity, Business Fluctuations"
|
||||
},
|
||||
{
|
||||
"tag": "Business Fluctuations; Cycles"
|
||||
},
|
||||
{
|
||||
"tag": "Child Care"
|
||||
},
|
||||
{
|
||||
"tag": "Children"
|
||||
},
|
||||
{
|
||||
"tag": "Cycles, Health Behavior, Health and Economic Development, Fertility"
|
||||
},
|
||||
{
|
||||
"tag": "Economic History: Labor and Consumers, Demography, Education, Health, Welfare, Income, Wealth, Religion, and Philanthropy: General, International, or Comparative"
|
||||
},
|
||||
{
|
||||
"tag": "Employment"
|
||||
},
|
||||
{
|
||||
"tag": "Employment; Unemployment; Wages; Intergenerational Income Distribution; Aggregate Human Capital; Aggregate Labor Productivity"
|
||||
},
|
||||
{
|
||||
"tag": "Family Planning"
|
||||
},
|
||||
{
|
||||
"tag": "Fertility; Family Planning; Child Care; Children; Youth"
|
||||
},
|
||||
{
|
||||
"tag": "Health Behavior"
|
||||
},
|
||||
{
|
||||
"tag": "Health and Economic Development"
|
||||
},
|
||||
{
|
||||
"tag": "Human Capital; Skills; Occupational Choice; Labor Productivity"
|
||||
},
|
||||
{
|
||||
"tag": "Intergenerational Income Distribution"
|
||||
},
|
||||
{
|
||||
"tag": "Labor Productivity, Economic History: Labor and Consumers, Demography, Education, Health, Welfare, Income, Wealth, Religion, and Philanthropy: General, International, or Comparative"
|
||||
},
|
||||
{
|
||||
"tag": "Occupational Choice"
|
||||
},
|
||||
{
|
||||
"tag": "Skills"
|
||||
},
|
||||
{
|
||||
"tag": "Unemployment"
|
||||
},
|
||||
{
|
||||
"tag": "Wages"
|
||||
},
|
||||
{
|
||||
"tag": "Youth, Human Capital"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
311
AGRIS.js
311
AGRIS.js
|
|
@ -1,311 +0,0 @@
|
|||
{
|
||||
"translatorID": "48a67d12-1bcf-44ac-a4f4-11457ebfc0bb",
|
||||
"label": "AGRIS",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://agris\\.fao\\.org/agris-search/search",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-12 21:34:16"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.querySelector('.docType_ico img[title*="Dataset"]')) {
|
||||
return "document";
|
||||
}
|
||||
else if (doc.querySelector('meta[name="citation_journal_title"]')) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (doc.querySelector('meta[name="citation_title"]')) {
|
||||
return "report";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h3 > a[href*="search.do"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
// item.url will be empty if there's no full-text link; we don't want
|
||||
// to use the catalog page as the URL in that case.
|
||||
item.url = attr(doc, '.link-full-text a', 'href');
|
||||
item.attachments = [];
|
||||
|
||||
if (item.itemType == 'document') {
|
||||
item.extra = (item.extra || '') + '\nType: dataset';
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://agris.fao.org/agris-search/search.do?recordID=IR2012044101",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"title": "Possibility of artificial propagation in farmed great sturgeon (Huso huso)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Mahmoud",
|
||||
"lastName": "Bahmani",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Porkazemi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "H.",
|
||||
"lastName": "Khara",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Rahimidanesh",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M. A.",
|
||||
"lastName": "Tolooei",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "A.",
|
||||
"lastName": "Abasalizadeh",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Hassanzadehsaber",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "H.",
|
||||
"lastName": "Mohamadiparashkohi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "O.",
|
||||
"lastName": "Asghari",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "R.",
|
||||
"lastName": "Kazemi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "S.",
|
||||
"lastName": "Dezhandian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "A.",
|
||||
"lastName": "Yousefi Jourdehi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Mohseni",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M. A.",
|
||||
"lastName": "Yazdani",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "A.",
|
||||
"lastName": "Hallajian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Shakourian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Pourdehghani",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"abstractNote": "In this research, morphometrical and physiological indicators of farmed great sturgeon, Huso huso in the Dr.Dadman International Sturgeon Research Institute studied. After biopsy of male and female gonads, two groups in terms of sexual maturity stage were observed. According to the histological observations, gonad development of male fish in the test group 1, stage II to III and in the test group 2 stage II to IV and in female fish in the test group 1 from stage II to stage II-III and in the test group 2 in stage III of sexual development and maturity stage was determined Maximum average weight and total length in a group of male fish in the summer (39/07±5/79 kg and 170 ± 6/48cm) and minimum average weight and total length in the two test groups of male fish in the autumn (26/25±3/65 kg and 155/5±4/40 cm) were measured. In the female test groups, the maximum average of weight and total length of the test group 2 in the summer (40/32±3/09 kg 170/12±1/96 cm), and the minimum of the test group 1 in the fall (25/8±1/30 kg and 160/6± 1/97 cm) were determined. The results of measuring the cortisol hormone in male test group, maximum and minimum average in the test group 1, respectively, in the summer (41/25±6/34 ng/ml) and fall (24/62±13/96 ng/ml) showed a significant difference between groups (p0.05). While the results of female group tests in test groups in relation with cortisol hormone had suggested that the maximum in group 2 in winter (58±25/92 ng/ml) and minimum in group 1 in the autumn (9/32±5/6 ng/ml) were observed and there were significant difference between groups (p0.05). Male, the results had suggested that the maximum average testosterone in the test group 2 in winter (71/25±15/52 ng / ml) and minimum in group 1 and in winter (27±6/60 ng/ml), respectively. So that showed significant difference between groups (P0.05). progesterone hormone were in the test group 2 and in summer (1/52±0/18 ng/ml) and its minimum in winter (0/14± 0/10 ng/ml) in test group 1 (p0.05), respectively. Maximum hormone levels 17-beta estradiol in the test group 2 in the autumn (16/42±6/36 ng/ml) and its minimum in the test group 1 in the winter (3/1±0/74 ng/ml) was observed and showed no statistical difference between groups (p 0.05). Based on the results, levels of female sex hormones in the test group showed that maximum testosterone (19/87±10/72 ng/ml) in the test group 2 in summer and minimum16/0±0/02 ng/ml) in the test group 1, were determined and had significant difference in all seasons (p0.05 (0/03±0/01 ng/ml) in the test group 1 was observed in winter that a significant difference between groups showed at fall (P0.05). Maximum and minimum levels of the hormone 17-beta estradiol in the test group 2 was observed in autumn (12/37±7/23 ng/ml), respectively (p0.05). The results of plasma metabolites (glucose, cholesterol, triglycerides and total lipid in the male test groups had suggested that the maximum and minimum of glucose in the test group 1 was (75/25±8/71 mg/dl) in winter and (39/5±6/71 mg / dl) summer, respectively. Maximum and minimum levels of cholesterol in group 1 was observed in autumn (128/75±54/34 mg/dl) and in winter (74/5±8/19 mg/dl), respectively. Maximum and minimum amount of triglycerides in the test group 2 observed in winter (384/75±50/93 mg/dl) and (156/25±16/34 mg / dl) in spring, so that in the spring between the groups showed significant difference (p0.05). Maximum total lipid in the test group 2 was observed in summer (686/25 ± 83/27 mg/dl) and minimum in the test group 1 in spring (410±62/03 mg/dl). Maximum and minimum glucose levels in a female group was observed in winter (82/7±11/55 mg/dl) and autumn (27/6±6 /41 mg/dl), respectively. The maximum cholesterol amount of the test group 1 was observed in winter (87±3/66 mg/dl) and minimum in the test group 2 in autumn (63/5±5/23 mg/dl). Maximum and minimum amount of triglycerides in the test group 2 was in the spring (281±33/67 mg/dl) and its minimum in autumn (213/75 ± 32/44 mg/dl), respectively, so that in the spring showed significant difference between the groups (p0.05).Maximum total lipid amount was in the test group 2 in spring (554/7±31/59 mg/dl) and minimum in the test group 1 in winter (367±21/22 mg/dl) and in summer between groups significant difference was observed (p0.05). The results of calcium and sodium cations and osmolarity in males suggested that calcium in females and sodium in males showed significant difference related to sexual maturation stage (P0.05). But osmolarity didn t show significant difference in both sex (p0.05).",
|
||||
"institution": "Iranian Fisheries Research Organization",
|
||||
"language": "Farsi",
|
||||
"libraryCatalog": "agris.fao.org",
|
||||
"url": "https://agris.fao.org/agris-search/search.do?recordID=IR2012044101",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://agris.fao.org/agris-search/search.do?recordID=TH2005000236",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Efficiency of antimicrobial residue screening test kit for meat CM-Test",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Thongchai",
|
||||
"lastName": "Chalermchaikit",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Kriengsak",
|
||||
"lastName": "Poonsook",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Kriengsuk",
|
||||
"lastName": "Dangprom",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Monthon",
|
||||
"lastName": "Lertworapreecha",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Kittikorn",
|
||||
"lastName": "Jotisakulratana",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2002",
|
||||
"ISSN": "0125-0369",
|
||||
"abstractNote": "Concerns of antimicrobial residues in food of animal origins are not only the adverse health effect to consumers but also the impact on exportation. The conventional methods for detecting antimicrobial residues in meat are European Four Pate Test (EDPR) method which use Bacillus subtilis and Micrococcus luteus in Test agar or Microbial Inhibition Disk Assay (MIDA) which use Bacillus mycoides, Bacillus subtilis and Micrococcus luteus in Antibiotic medium as indicators. However, EFPT and MIDA are required incubating time at least 18 hours for reading the results. Besides, EFPT and MIDA have been showed low specificity, which lead to false negative results. Therefore, antimicrobial screening test kit for meat has been developed by the full support from Thai Research Fund (TRF). The concept of new developed antimicrobial screening test kit (CM-Test) is tube diffusion method. There are consisted of Bacillus stearothermophilus in appropriated medium, which contained in polypropylene tube (1*4 cm). The tested results can be read after the meat extract supernatant of 0.1 ml is put into the test kit and incubated at 65+-1 deg C for 3 1/2-4 1/2 hours. The color of test kit will not be changed if the sample is positive (contain antimicrobial residue). If the sample is negative, test kit color will be changed to yellow. The prevalence of antimicrobial residues in 300 chicken meat samples and 300 pork samples, randomly purchased from markets and supermarkets in Bangkok during July 2001 to February 2002, had been studied. The results of chicken meat samples were found positive 12.3, 0 and 1.7 percent by using CM-Test, EFPT and MIDA methods, respectively. The results of pork samples were found positive 8.3, 2 and 2.7 percent by using CM-Test, EFPT and MIDA methods, respectively. Positive samples were confirmed by Charm II Test method. These results reveal that the detection limits developed antimicrobial residue screening test kit are better than conventional methods, EFPT and MIDA.",
|
||||
"language": "Thai",
|
||||
"libraryCatalog": "agris.fao.org",
|
||||
"publicationTitle": "Warasan Witthayasat Kaset",
|
||||
"url": "https://agris.fao.org/agris-search/search.do?recordID=TH2005000236",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://agris.fao.org/agris-search/search.do?request_locale=ar&recordID=AV20120164931&query=&sourceQuery=&sortField=&sortOrder=&countryResource=&agrovocString=&advQuery=¢erString=&enableField=",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"title": "Petroleum Hydrocarbons in Saudi Red Sea Coastal Waters الهيدروكربونات البترولية في المياه السطحية لساحل البحر الاحمر السعودية (منطقة بترومين)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sultan",
|
||||
"lastName": "Al-Lihaibi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Turki",
|
||||
"lastName": "Al-Ghamdy",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1997",
|
||||
"abstractNote": "Total petroleum hydrocarbons in surface water samples collected from the Red Sea coast al area of Jeddah (Saudi Arabia), have been measured using ultraviolet fluorescence spectroscopy (UVF). Concentration level ranged between 1.79 and 17.9 J..I.g 1,1 light Arabian oil equivalents . Samples taken near the oil terminal (Petromin) showed relatively high concentrations (2.8-17.9 J..I.g I\" 1). whereas in the relatively clean Obhur Creek concentrations wer~ low (2 J..I.g 1- I). Perfect agreement has been obtained between concentrations calculated as chrysene and light Arabian equivalents. However, the light Arabian equivalent concentration is almost 6 times the chrysene equivalent concentration . تم قياس الهيدروكربونات البترولية في المياه السطحية للمنطقة الساحلية لمدينة جدة باستخدام مطياف الفلورة فوق البنفسجية . وجد أن مستوى التركيز في العينات تراوح بين 1.8 و 17.9 مايكروجرام / لتر وحدات زيت عربي خفيف مكافئة . وقد لوحظ أن العينات القريبة من مصرف مصفاة الزيت (بترومين) أعطت تراكيز عالية ( 2.8-17.9 مايكروجرام/ لتر ) بينما أعطت العينات المأخوذة من شرم أبحر ، والذي يعتبر الأنظف نسبيا ، قراءات منخفضة ( 2.0 مايكروجرام / لتر أو أقل ) . كما لوحظ وجود علاقة بين التركيزات المحسوبة على أساس وحدات كرايسين مكافئة وتلك المحسوبة على أساس وحدات زيت عربي خفيف مكافئة بحيث يكون الأخير مساويا لما يقارب 6 أضعاف الأول.",
|
||||
"institution": "KAU - Scientific Publishing Center",
|
||||
"language": "English",
|
||||
"libraryCatalog": "agris.fao.org",
|
||||
"url": "http://www.kau.edu.sa/centers/spc/jkau/Doc/Mar/8/Petroleum%20Hydrocarbons%20in%20Saudi%20Red%20Sea%20Coastal%20Waters.pdf",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://agris.fao.org/agris-search/searchIndex.do?query=soil+water",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,313 +0,0 @@
|
|||
{
|
||||
"translatorID": "a354331-981b-43de-a61-bc26dd1be3a9",
|
||||
"label": "AMS MathSciNet (Legacy)",
|
||||
"creator": "Simon Kornblith, Sebastian Karcher",
|
||||
"target": "^https?://(mathscinet\\.)?ams\\.[^/]*/(mathscinet/2006/)?mathscinet(\\-getitem\\?|/search/(publications\\.html|publdoc\\.html))",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-07-06 17:03:34"
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2015-2023 Simon Kornblith & Sebastian Karcher
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
var itemType;
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
else if (ZU.xpathText(doc, '//div[@class="headlineMenu"]/*[last()-1]')) {
|
||||
itemType = ZU.xpathText(doc, '//div[@class="headlineMenu"]/*[last()-1]');
|
||||
switch (itemType.trim().toLowerCase()) {
|
||||
case 'article':
|
||||
return "journalArticle";
|
||||
case 'book':
|
||||
return "book";
|
||||
case 'chapter':
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = ZU.xpath(doc, '//div[@class="headlineText"]');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var href = ZU.xpathText(rows[i], './a[@class="mrnum"]/@href');
|
||||
var title = ZU.xpathText(rows[i], './span[@class="title"]');
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
var host = url.match(/^(.+)\/mathscinet/);
|
||||
var pub = host[0] + "/search/publications.html?fmt=bibtex";
|
||||
var MR = ZU.xpathText(doc, '//div[@id="content"]/div[@class="doc"]/div[@class="headline"]/strong[1]');
|
||||
pub += "&pg1=MR&s1=" + MR.replace(/^MR0*/, "");
|
||||
|
||||
let text = await requestText(pub);
|
||||
var preRE = /<pre>\s*([\s\S]*?)\s*<\/pre>/g;
|
||||
var bibTeXString = "";
|
||||
|
||||
var m;
|
||||
//eslint-disable-next-line no-cond-assign
|
||||
while (m = preRE.exec(text)) {
|
||||
bibTeXString += m[1] + '\n';
|
||||
}
|
||||
|
||||
// import using BibTeX
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
translator.setString(bibTeXString);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
// Fix/fetch MR number
|
||||
var mrnumber;
|
||||
if (item.extra) {
|
||||
item.extra = item.extra.replace(/^MR:\s*(?:MR)?(\d+).*/gm,
|
||||
function (m, mr) {
|
||||
mrnumber = mr;
|
||||
return 'MR: ' + mr;
|
||||
});
|
||||
}
|
||||
|
||||
if (mrnumber) {
|
||||
url = 'https://mathscinet.ams.org/mathscinet-getitem?mr=' + mrnumber;
|
||||
}
|
||||
item.attachments.push({ title: "MathSciNet Snapshot", document: doc });
|
||||
item.url = url;
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/search/publications.html?pg4=AUCN&s4=Karcher&co4=AND&pg5=TI&s5=&co5=AND&pg6=PC&s6=&co6=AND&pg7=ALLF&s7=&co7=AND&Submit=Search&dr=all&yrop=eq&arg3=&yearRangeFirst=&yearRangeSecond=&pg8=ET&s8=All&review_format=html",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/2006/mathscinet/search/publdoc.html?arg3=&co4=AND&co5=AND&co6=AND&co7=AND&dr=all&pg4=MR&pg5=TI&pg6=PC&pg7=ALLF&pg8=ET&r=1&review_format=html&s4=3004573",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Extrapolation of stable random fields",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Wolfgang",
|
||||
"lastName": "Karcher",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Elena",
|
||||
"lastName": "Shmileva",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Evgeny",
|
||||
"lastName": "Spodarev",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2013",
|
||||
"DOI": "10.1016/j.jmva.2012.11.004",
|
||||
"ISSN": "0047-259X",
|
||||
"extra": "MR: 3004573",
|
||||
"itemID": "MR3004573",
|
||||
"journalAbbreviation": "J. Multivariate Anal.",
|
||||
"libraryCatalog": "AMS MathSciNet (Legacy)",
|
||||
"pages": "516–536",
|
||||
"publicationTitle": "Journal of Multivariate Analysis",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=3004573",
|
||||
"volume": "115",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "MathSciNet Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/search/publications.html?pg1=ISSI&s1=308850",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/2006/mathscinet/search/publdoc.html?arg3=&co4=AND&co5=AND&co6=AND&co7=AND&dr=all&pg4=MR&pg5=TI&pg6=PC&pg7=ALLF&pg8=ET&r=1&review_format=html&s4=2767535",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "On implementation of the Markov chain Monte Carlo stochastic approximation algorithm",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Yihua",
|
||||
"lastName": "Jiang",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Peter",
|
||||
"lastName": "Karcher",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Yuedong",
|
||||
"lastName": "Wang",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"bookTitle": "Advances in directional and linear statistics",
|
||||
"extra": "MR: 2767535\nDOI: 10.1007/978-3-7908-2628-9_7",
|
||||
"itemID": "MR2767535",
|
||||
"libraryCatalog": "AMS MathSciNet (Legacy)",
|
||||
"pages": "97–111",
|
||||
"publisher": "Physica-Verlag/Springer, Heidelberg",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2767535",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "MathSciNet Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/2006/mathscinet/search/publdoc.html?arg3=&co4=AND&co5=AND&co6=AND&co7=AND&dr=all&pg4=MR&pg5=TI&pg6=PC&pg7=ALLF&pg8=ET&r=1&review_format=html&s4=2663710",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Advances in directional and linear statistics",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Martin T.",
|
||||
"lastName": "Wells",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ashis",
|
||||
"lastName": "SenGupta",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"ISBN": "9783790826272",
|
||||
"extra": "MR: 2663710\nDOI: 10.1007/978-3-7908-2628-9",
|
||||
"itemID": "MR2663710",
|
||||
"libraryCatalog": "AMS MathSciNet (Legacy)",
|
||||
"numPages": "xiv+321",
|
||||
"publisher": "Physica-Verlag/Springer, Heidelberg",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2663710",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "MathSciNet Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<p>A Festschrift for Sreenivasa Rao Jammalamadaka</p>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=1346201",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Sommation des séries divergentes",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Bernard",
|
||||
"lastName": "Malgrange",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1995",
|
||||
"ISSN": "0723-0869",
|
||||
"extra": "MR: 1346201",
|
||||
"issue": "2-3",
|
||||
"itemID": "MR1346201",
|
||||
"journalAbbreviation": "Exposition. Math.",
|
||||
"libraryCatalog": "AMS MathSciNet",
|
||||
"pages": "163–222",
|
||||
"publicationTitle": "Expositiones Mathematicae. International Journal",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=1346201",
|
||||
"volume": "13",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "MathSciNet Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,61 +1,45 @@
|
|||
{
|
||||
"translatorID": "16f2936d-a059-40e8-a48e-f0acbb1e93e0",
|
||||
"translatorID": "a354331-981b-43de-a61-bc26dd1be3a9",
|
||||
"label": "AMS MathSciNet",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://mathscinet\\.ams\\.[^/]*/mathscinet/(article\\?|publications-search\\?|author\\?)",
|
||||
"creator": "Simon Kornblith",
|
||||
"target": "^https?://(mathscinet\\.)?ams\\.[^/]*/mathscinet(\\-getitem\\?|/search/(publications\\.html|publdoc\\.html))",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-07-14 11:04:37"
|
||||
"lastUpdated": "2017-10-20 16:08:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Sebastian Karcher
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
|
||||
var itemType;
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
return "multiple"
|
||||
} else if (itemType = ZU.xpathText(doc, '//div[@class="headlineMenu"]/*[last()-1]')) {
|
||||
switch (itemType.trim().toLowerCase()) {
|
||||
case 'article':
|
||||
return "journalArticle";
|
||||
case 'book':
|
||||
return "book";
|
||||
case 'chapter':
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
else if (url.includes("article?mr=")) {
|
||||
if (doc.querySelector('div[data-testid="ap-book-isbn"]')) {
|
||||
if (doc.querySelector('div[data-testid="ap-book-collection"] a.router-link-active')) return "bookSection";
|
||||
else return "book";
|
||||
}
|
||||
else return "journalArticle";
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.results div.font-weight-bold');
|
||||
for (let row of rows) {
|
||||
let href = attr(row, 'a', 'href');
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
//TODO: adjust the xpath
|
||||
var rows = ZU.xpath(doc, '//div[@class="headlineText"]');
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
//TODO: check and maybe adjust
|
||||
var href = ZU.xpathText(rows[i], './a[@class="mrnum"]/@href')
|
||||
//TODO: check and maybe adjust
|
||||
var title = ZU.xpathText(rows[i], './span[@class="title"]')
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
|
|
@ -64,51 +48,74 @@ function getSearchResults(doc, checkOnly) {
|
|||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
let id = url.match(/\?mr=(\d+)/);
|
||||
if (!id) {
|
||||
throw new Error("No MR ID, can't proceed");
|
||||
}
|
||||
let bibJSONUrl = '/mathscinet/api/publications/format?formats=bib&ids=' + id[1];
|
||||
// Z.debug(bibJSONUrl)
|
||||
let bibJSON = await requestText(bibJSONUrl);
|
||||
// Z.debug(bibJSON)
|
||||
bibJSON = JSON.parse(bibJSON);
|
||||
let bibTex = bibJSON[0].bib;
|
||||
// Z.debug(bibTex)
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator('9cb70025-a888-4a29-a210-93ec52da40d4');
|
||||
translator.setString(bibTex);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.url = ""; // these aren't full text URLs
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var host = url.match(/^(.+)\/mathscinet/)
|
||||
var pub = host[0] + "/search/publications.html?fmt=bibtex";
|
||||
var MR = ZU.xpathText(doc, '//div[@id="content"]/div[@class="doc"]/div[@class="headline"]/strong[1]');
|
||||
pub += "&pg1=MR&s1="+MR.replace(/^MR0*/, "");
|
||||
|
||||
ZU.doGet(pub, function(text) {
|
||||
var preRE = /<pre>\s*([\s\S]*?)\s*<\/pre>/g;
|
||||
var bibTeXString = "";
|
||||
|
||||
var m;
|
||||
while (m = preRE.exec(text)) {
|
||||
bibTeXString += m[1] + '\n';
|
||||
}
|
||||
|
||||
// import using BibTeX
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
translator.setString(bibTeXString);
|
||||
translator.setHandler("itemDone", function(obj, item) {
|
||||
// Fix/fetch MR number
|
||||
var mrnumber;
|
||||
if (item.extra) {
|
||||
item.extra = item.extra.replace(/^MR:\s*(?:MR)?(\d+).*/gm,
|
||||
function(m, mr) {
|
||||
mrnumber = mr;
|
||||
return 'MR: ' + mr;
|
||||
});
|
||||
}
|
||||
|
||||
if (mrnumber) {
|
||||
url = 'https://mathscinet.ams.org/mathscinet-getitem?mr=' + mrnumber;
|
||||
}
|
||||
item.attachments.push({title: "MathSciNet Snapshot", document: doc});
|
||||
item.url = url;
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
}
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=3004573",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/search/publications.html?pg4=AUCN&s4=Karcher&co4=AND&pg5=TI&s5=&co5=AND&pg6=PC&s6=&co6=AND&pg7=ALLF&s7=&co7=AND&Submit=Search&dr=all&yrop=eq&arg3=&yearRangeFirst=&yearRangeSecond=&pg8=ET&s8=All&review_format=html",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=3004573",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -132,18 +139,18 @@ var testCases = [
|
|||
],
|
||||
"date": "2013",
|
||||
"DOI": "10.1016/j.jmva.2012.11.004",
|
||||
"ISSN": "0047-259X,1095-7243",
|
||||
"ISSN": "0047-259X",
|
||||
"extra": "MR: 3004573",
|
||||
"itemID": "MR3004573",
|
||||
"journalAbbreviation": "J. Multivariate Anal.",
|
||||
"libraryCatalog": "AMS MathSciNet",
|
||||
"pages": "516–536",
|
||||
"publicationTitle": "Journal of Multivariate Analysis",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=3004573",
|
||||
"volume": "115",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "MathSciNet Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -154,7 +161,12 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=2767535",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/search/publications.html?pg1=ISSI&s1=308850",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2767535",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -177,17 +189,16 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"ISBN": "9783790826272",
|
||||
"bookTitle": "Advances in directional and linear statistics",
|
||||
"extra": "MR: 2767535\nDOI: 10.1007/978-3-7908-2628-9_7",
|
||||
"itemID": "MR2767535",
|
||||
"libraryCatalog": "AMS MathSciNet",
|
||||
"pages": "97–111",
|
||||
"publisher": "Physica-Verlag/Springer, Heidelberg",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2767535",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "MathSciNet Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -195,10 +206,10 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=2663710",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2663710",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -222,10 +233,10 @@ var testCases = [
|
|||
"libraryCatalog": "AMS MathSciNet",
|
||||
"numPages": "xiv+321",
|
||||
"publisher": "Physica-Verlag/Springer, Heidelberg",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2663710",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "MathSciNet Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -240,7 +251,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=1346201",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=1346201",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -261,11 +272,11 @@ var testCases = [
|
|||
"libraryCatalog": "AMS MathSciNet",
|
||||
"pages": "163–222",
|
||||
"publicationTitle": "Expositiones Mathematicae. International Journal",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=1346201",
|
||||
"volume": "13",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "MathSciNet Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -273,16 +284,6 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/publications-search?query=karcher&page=1&size=20&sort=newest&facets=",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/author?authorId=98350",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
454
APA PsycNET.js
454
APA PsycNET.js
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
"translatorID": "1e1e35be-6264-45a0-ad2e-7212040eb984",
|
||||
"label": "APA PsycNet",
|
||||
"label": "APA PsycNET",
|
||||
"creator": "Philipp Zumstein",
|
||||
"target": "^https?://(psycnet|doi)\\.apa\\.org/",
|
||||
"target": "^https?://psycnet\\.apa\\.org/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-03-10 19:48:42"
|
||||
"lastUpdated": "2020-09-21 07:34:07"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2017-2021 Philipp Zumstein
|
||||
Copyright © 2017 Philipp Zumstein
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
|
@ -46,18 +46,35 @@
|
|||
// to avoid some automatic download detection.
|
||||
|
||||
|
||||
// attr()/text() v2
|
||||
// eslint-disable-next-line
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
// the dection will only work if the page is load completely,
|
||||
// thus we have to hardcode some test cases
|
||||
if (url.includes('://psycnet.apa.org/record/1992-98221-010')) return "bookSection";
|
||||
if (url.includes('://psycnet.apa.org/record/2004-16329-000')) return "book";
|
||||
if (url.includes('://psycnet.apa.org/buy/2004-16329-002')) return "bookSection";
|
||||
if (url.includes('://psycnet.apa.org/buy/2010-19350-001')) return "journalArticle";
|
||||
if (url.includes('://psycnet.apa.org/record/2010-09295-002')) return "bookSection";
|
||||
|
||||
// normal cases
|
||||
// It seems that the url sometimes changes after Zotero has inspected it,
|
||||
// which leads to the wrong Zotero icon. However, saving will still do the
|
||||
// correct action. Reload the page might also solve some edge cases.
|
||||
if (url.includes('/PsycBOOKS/')) {
|
||||
return "book";
|
||||
}
|
||||
if (url.includes('/search/display?')
|
||||
|| url.includes('/record/')
|
||||
|| url.includes('/fulltext/')
|
||||
|| url.includes('/buy/')
|
||||
|| url.includes('/doiLanding?doi=')) {
|
||||
if (attr(doc, 'meta[name="og:type"]', 'content') == 'Chapter') {
|
||||
if (doc.getElementById('bookchapterstoc')) {
|
||||
return "bookSection";
|
||||
}
|
||||
else if (doc.getElementById('bookchapterstoc')) {
|
||||
return "book";
|
||||
}
|
||||
else {
|
||||
return "journalArticle";
|
||||
}
|
||||
|
|
@ -74,7 +91,7 @@ function getSearchResults(doc, checkOnly) {
|
|||
var found = false;
|
||||
var rows = doc.querySelectorAll('a.article-title');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var href = attr(rows[i].parentNode, '#buy, a.fullTextHTMLLink, a.fullTextLink', 'href');
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
|
|
@ -85,42 +102,45 @@ function getSearchResults(doc, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url), url);
|
||||
}
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function scrape(doc, url) {
|
||||
var uid = await getIds(doc, url.replace(/#.*$/, ''));
|
||||
function scrape(doc, url) {
|
||||
var uid = getIds(doc, url.replace(/[?#].*$/, ''));
|
||||
if (!uid) {
|
||||
throw new Error("ID not found");
|
||||
}
|
||||
|
||||
var productCode;
|
||||
var db = doc.getElementById('database') || doc.querySelector('doi-landing .meta span');
|
||||
var db = doc.getElementById('database');
|
||||
if (db) {
|
||||
db = db.parentNode.textContent.toLowerCase();
|
||||
if (db.includes('psycarticles')) {
|
||||
db = db.parentNode.textContent;
|
||||
if (db.includes('PsycARTICLES')) {
|
||||
productCode = 'PA';
|
||||
}
|
||||
else if (db.includes('psycbooks')) {
|
||||
else if (db.includes('PsycBOOKS')) {
|
||||
productCode = 'PB';
|
||||
}
|
||||
else if (db.includes('psycinfo')) {
|
||||
else if (db.includes('PsycINFO')) {
|
||||
productCode = 'PI';
|
||||
}
|
||||
else if (db.includes('psycextra')) {
|
||||
else if (db.includes('PsycEXTRA')) {
|
||||
productCode = 'PE';
|
||||
}
|
||||
}
|
||||
|
|
@ -129,70 +149,44 @@ async function scrape(doc, url) {
|
|||
productCode = 'PI';
|
||||
}
|
||||
|
||||
var postData = JSON.stringify({
|
||||
api: "record.exportRISFile",
|
||||
params: {
|
||||
UIDList: [{ UID: uid, ProductCode: productCode }],
|
||||
exportType: "zotero"
|
||||
}
|
||||
});
|
||||
var postData = '{"api":"record.exportRISFile","params":{"UIDList":[{"UID":"' + uid + '","ProductCode":"' + productCode + '"}],"exportType":"zotero"}}';
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Referer: url
|
||||
};
|
||||
|
||||
let apiReturnData = await requestJSON('/api/request/record.exportRISFile', {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: postData,
|
||||
});
|
||||
|
||||
if (apiReturnData && apiReturnData.isRisExportCreated) {
|
||||
// 2. Download the requested data (after step 1)
|
||||
let data = await requestText('/ris/download');
|
||||
if (data.includes('Content: application/x-research-info-systems')) {
|
||||
await processRIS(data, doc);
|
||||
// 1. We have to set the uid, product code and format with a post request
|
||||
ZU.doPost('/api/request/record.exportRISFile', postData, function (apiReturnMessage) {
|
||||
var apiReturnData;
|
||||
try {
|
||||
apiReturnData = JSON.parse(apiReturnMessage);
|
||||
}
|
||||
else {
|
||||
// sometimes (e.g. during testing) the data is not loaded
|
||||
// but a meta redirect to a captcha page mentioning
|
||||
Z.debug("The APA anomaly detection think we are doing "
|
||||
+ "something unusual (sigh). Please reload any APA page e.g. "
|
||||
+ "http://psycnet.apa.org/ in your browser and try again.");
|
||||
Z.debug(data);
|
||||
catch (e) {
|
||||
Z.debug('POST request did not result in valid JSON');
|
||||
Z.debug(apiReturnMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (apiReturnData && apiReturnData.isRisExportCreated) {
|
||||
// 2. Download the requested data (after step 1)
|
||||
ZU.doGet('/ris/download', function (data) {
|
||||
if (data.includes('Content: application/x-research-info-systems')) {
|
||||
processRIS(data, doc);
|
||||
}
|
||||
else {
|
||||
// sometimes (e.g. during testing) the data is not loaded
|
||||
// but a meta redirect to a captcha page mentioning
|
||||
Z.debug("The APA anomaly detection think we are doing "
|
||||
+ "something unusual (sigh). Please reload any APA page e.g. "
|
||||
+ "http://psycnet.apa.org/ in your browser and try again.");
|
||||
Z.debug(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, headers);
|
||||
}
|
||||
|
||||
|
||||
async function processRIS(text, doc) {
|
||||
let pdfURL = attr(doc, 'a[href*="/fulltext"]', 'href');
|
||||
if (!pdfURL) {
|
||||
Zotero.debug('Fetching institution ID for PDF');
|
||||
try {
|
||||
let uid = doc.location.pathname.match(/\/(?:record|fulltext)\/([^/.]+)/)[1];
|
||||
let { institution } = await requestJSON(
|
||||
'https://psycnet.apa.org/api/request/institution.getInstitutionByIpAddress', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
api: 'institution.getInstitutionByIpAddress',
|
||||
params: { uid }
|
||||
})
|
||||
}
|
||||
);
|
||||
if (institution) {
|
||||
pdfURL = `https://psycnet.apa.org/fulltext/${uid}.pdf?auth_id=${institution.ringGoldId}&returnUrl=${encodeURIComponent(doc.location.href)}`;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug('Failed to fetch institution ID');
|
||||
Zotero.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
function processRIS(text, doc) {
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
|
|
@ -202,13 +196,10 @@ async function processRIS(text, doc) {
|
|||
if (item.bookTitle) item.bookTitle = cleanTitle(item.bookTitle);
|
||||
if (item.series) item.series = cleanTitle(item.series);
|
||||
if (item.place) item.place = item.place.replace(/\s+/g, ' ');
|
||||
if (item.ISSN) item.ISSN = ZU.cleanISSN(item.ISSN);
|
||||
if (item.pages && item.pages.includes('No Pagination Specified')) {
|
||||
delete item.pages;
|
||||
}
|
||||
for (var i = 0; i < item.tags.length; i++) {
|
||||
item.tags[i] = item.tags[i].replace(/^\*/, '');
|
||||
}
|
||||
var pdfURL = attr(doc, 'a[href*="/fulltext"]', 'href');
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
|
|
@ -216,21 +207,18 @@ async function processRIS(text, doc) {
|
|||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
translator.translate();
|
||||
}
|
||||
|
||||
|
||||
// try to figure out ids that we can use for fetching RIS
|
||||
async function getIds(doc, url) {
|
||||
Z.debug('Finding IDs in ' + url);
|
||||
function getIds(doc, url) {
|
||||
// try to extract uid from the table
|
||||
var uid = text(doc, '#uid + dd') || text(doc, '#bookUID');
|
||||
if (uid) {
|
||||
|
|
@ -238,16 +226,8 @@ async function getIds(doc, url) {
|
|||
}
|
||||
|
||||
// try to extract uid from the url
|
||||
if (url.includes('/record/') || url.includes('/fulltext/')) {
|
||||
let m = url.match(/\/(?:record|fulltext)\/([\d-]*)/);
|
||||
if (m && m[1]) {
|
||||
return m[1];
|
||||
}
|
||||
}
|
||||
|
||||
// DOI landing pages include a link to the /record/ page
|
||||
if (url.includes('/doiLanding') && doc.querySelector('.title > a')) {
|
||||
let m = attr(doc, '.title > a', 'href').match(/\/record\/([\d-]*)/);
|
||||
if (url.includes('/record/')) {
|
||||
let m = url.match(/\/record\/([\d-]*)/);
|
||||
if (m && m[1]) {
|
||||
return m[1];
|
||||
}
|
||||
|
|
@ -282,48 +262,13 @@ async function getIds(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
/** check for a purchase link
|
||||
/** last option: check for a purchase link
|
||||
*/
|
||||
var purchaseLink = attr(doc, 'a.purchase[href*="/buy/"]', 'href');
|
||||
if (purchaseLink) {
|
||||
let m = purchaseLink.match(/\/buy\/([\d-]*)/);
|
||||
return m[1];
|
||||
}
|
||||
|
||||
// Worst-case fallback if we're on a search result page: make some requests
|
||||
if (url.includes('/search/display?')) {
|
||||
let searchParams = new URL(url).searchParams;
|
||||
let id = searchParams.get('id');
|
||||
if (id) {
|
||||
let searchObj = await requestJSON('/api/request/recentSearch.get', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
api: 'recentSearch.get',
|
||||
params: {
|
||||
id
|
||||
}
|
||||
})
|
||||
});
|
||||
let recordId = parseInt(searchParams.get('recordId'));
|
||||
let recordWithCount = await requestJSON('/api/request/search.recordWithCount', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
api: 'search.recordWithCount',
|
||||
params: {
|
||||
...searchObj,
|
||||
responseParameters: {
|
||||
...searchObj.responseParameters,
|
||||
start: recordId - 1,
|
||||
rows: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
return recordWithCount.results.result.doc[0].UID;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -344,7 +289,7 @@ function cleanTitle(title) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/2004-16644-010",
|
||||
"url": "http://psycnet.apa.org/record/2004-16644-010",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -368,18 +313,17 @@ var testCases = [
|
|||
],
|
||||
"date": "2004",
|
||||
"DOI": "10.1037/0894-4105.18.3.485",
|
||||
"ISSN": "1931-1559",
|
||||
"abstractNote": "A comprehensive, empirically based review of the published studies addressing neuropsychological performance in adults diagnosed with attention-deficit/hyperactivity disorder (ADHD) was conducted to identify patterns of performance deficits. Findings from 33 published studies were submitted to a meta-analytic procedure producing sample-size-weighted mean effect sizes across test measures. Results suggest that neuropsychological deficits are expressed in adults with ADHD across multiple domains of functioning, with notable impairments in attention, behavioral inhibition, and memory, whereas normal performance is noted in simple reaction time. Theoretical and developmental considerations are discussed, including the role of behavioral inhibition and working memory impairment. Future directions for research based on these findings are highlighted, including further exploration of specific impairments and an emphasis on particular tests and testing conditions. (PsycInfo Database Record (c) 2022 APA, all rights reserved)",
|
||||
"ISSN": "1931-1559(Electronic),0894-4105(Print)",
|
||||
"abstractNote": "A comprehensive, empirically based review of the published studies addressing neuropsychological performance in adults diagnosed with attention-deficit/hyperactivity disorder (ADHD) was conducted to identify patterns of performance deficits. Findings from 33 published studies were submitted to a meta-analytic procedure producing sample-size-weighted mean effect sizes across test measures. Results suggest that neuropsychological deficits are expressed in adults with ADHD across multiple domains of functioning, with notable impairments in attention, behavioral inhibition, and memory, whereas normal performance is noted in simple reaction time. Theoretical and developmental considerations are discussed, including the role of behavioral inhibition and working memory impairment. Future directions for research based on these findings are highlighted, including further exploration of specific impairments and an emphasis on particular tests and testing conditions. (PsycINFO Database Record (c) 2016 APA, all rights reserved)",
|
||||
"issue": "3",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"pages": "485-503",
|
||||
"publicationTitle": "Neuropsychology",
|
||||
"shortTitle": "Neuropsychology of Adults With Attention-Deficit/Hyperactivity Disorder",
|
||||
"volume": "18",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -396,7 +340,7 @@ var testCases = [
|
|||
"tag": "Experimentation"
|
||||
},
|
||||
{
|
||||
"tag": "Hyperactivity"
|
||||
"tag": "Hyperkinesis"
|
||||
},
|
||||
{
|
||||
"tag": "Inhibition (Personality)"
|
||||
|
|
@ -418,7 +362,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/1956-05944-001",
|
||||
"url": "http://psycnet.apa.org/record/1956-05944-001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -437,17 +381,16 @@ var testCases = [
|
|||
],
|
||||
"date": "1955",
|
||||
"DOI": "10.1037/h0043965",
|
||||
"ISSN": "0022-1015",
|
||||
"ISSN": "0022-1015(Print)",
|
||||
"abstractNote": "Two factor analytic studies of meaningful judgments based upon the same sample of 50 bipolar descriptive scales are reported. Both analyses reveal three major connotative factors: evaluation, potency, and activity. These factors appear to be independent dimensions of the semantic space within which the meanings of concepts may be specified. (PsycINFO Database Record (c) 2016 APA, all rights reserved)",
|
||||
"issue": "5",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"pages": "325-338",
|
||||
"publicationTitle": "Journal of Experimental Psychology",
|
||||
"volume": "50",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -474,8 +417,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/1992-98221-010",
|
||||
"defer": true,
|
||||
"url": "http://psycnet.apa.org/record/1992-98221-010",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -494,9 +436,9 @@ var testCases = [
|
|||
],
|
||||
"date": "1977",
|
||||
"ISBN": "9780716703686 9780716703679",
|
||||
"abstractNote": "tonic immobility [animal hypnosis] might be a useful laboratory analog or research model for catatonia / we have been collaborating on an interdisciplinary program of research in an effort to pinpoint the behavioral antecedents and biological bases for tonic immobility / attempt to briefly summarize our findings, and . . . discuss the implications of these data in terms of the model characteristics of tonic immobility / hypnosis / catatonia, catalepsy, and cataplexy / tonic immobility as a model for catatonia / fear potentiation / fear alleviation / fear or arousal / learned helplessness / neurological correlates / pharmacology and neurochemistry / genetic underpinnings / evolutionary considerations / implications for human psychopathology (PsycInfo Database Record (c) 2022 APA, all rights reserved)",
|
||||
"abstractNote": "tonic immobility [animal hypnosis] might be a useful laboratory analog or research model for catatonia / we have been collaborating on an interdisciplinary program of research in an effort to pinpoint the behavioral antecedents and biological bases for tonic immobility / attempt to briefly summarize our findings, and . . . discuss the implications of these data in terms of the model characteristics of tonic immobility / hypnosis / catatonia, catalepsy, and cataplexy / tonic immobility as a model for catatonia / fear potentiation / fear alleviation / fear or arousal / learned helplessness / neurological correlates / pharmacology and neurochemistry / genetic underpinnings / evolutionary considerations / implications for human psychopathology (PsycINFO Database Record (c) 2016 APA, all rights reserved)",
|
||||
"bookTitle": "Psychopathology: Experimental models",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"pages": "334-357",
|
||||
"place": "New York, NY, US",
|
||||
"publisher": "W H Freeman/Times Books/ Henry Holt & Co",
|
||||
|
|
@ -504,8 +446,7 @@ var testCases = [
|
|||
"shortTitle": "Catatonia",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -541,8 +482,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/2004-16329-000?doi=1",
|
||||
"defer": true,
|
||||
"url": "http://psycnet.apa.org/record/2004-16329-000?doi=1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -555,9 +495,9 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "1948",
|
||||
"abstractNote": "The author's intent is to write about abnormal people in a way that will be valuable and interesting to students new to the subject. A first course in abnormal psychology is not intended to train specialists. Its goal is more general: it should provide the student with the opportunity to whet his interest, expand his horizons, register a certain body of new facts, and relate this to the rest of his knowledge about mankind. I have tried to present the subject in such a way as to emphasize its usefulness to all students of human nature. I have tried the experiment of writing two introductory chapters, one historical and the other clinical. This reflects my desire to set the subject-matter in a broad perspective and at the same time to anchor it in concrete fact. Next comes a block of six chapters designed to set forth the topics of maladjustment and neurosis. The two chapters on psychotherapy complete the more purely psychological or developmental part of the work. In the final chapter the problem of disordered personalities is allowed to expand to its full social dimensions. Treatment, care, and prevention call for social effort and social organization. I have sought to show some of the lines, both professional and nonprofessional, along which this effort can be expended. (PsycInfo Database Record (c) 2022 APA, all rights reserved)",
|
||||
"abstractNote": "The author's intent is to write about abnormal people in a way that will be valuable and interesting to students new to the subject. A first course in abnormal psychology is not intended to train specialists. Its goal is more general: it should provide the student with the opportunity to whet his interest, expand his horizons, register a certain body of new facts, and relate this to the rest of his knowledge about mankind. I have tried to present the subject in such a way as to emphasize its usefulness to all students of human nature. I have tried the experiment of writing two introductory chapters, one historical and the other clinical. This reflects my desire to set the subject-matter in a broad perspective and at the same time to anchor it in concrete fact. Next comes a block of six chapters designed to set forth the topics of maladjustment and neurosis. The two chapters on psychotherapy complete the more purely psychological or developmental part of the work. In the final chapter the problem of disordered personalities is allowed to expand to its full social dimensions. Treatment, care, and prevention call for social effort and social organization. I have sought to show some of the lines, both professional and nonprofessional, along which this effort can be expended. (PsycINFO Database Record (c) 2016 APA, all rights reserved)",
|
||||
"extra": "DOI: 10.1037/10023-000",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"numPages": "x, 617",
|
||||
"place": "New York, NY, US",
|
||||
"publisher": "Ronald Press Company",
|
||||
|
|
@ -565,8 +505,7 @@ var testCases = [
|
|||
"shortTitle": "The abnormal personality",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -579,99 +518,9 @@ var testCases = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/fulltext/2022-40433-002.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Expertise in emotion: A scoping review and unifying framework for individual differences in the mental representation of emotional experience",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Hoemann",
|
||||
"firstName": "Katie",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Nielson",
|
||||
"firstName": "Catie",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Yuen",
|
||||
"firstName": "Ashley",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Gurera",
|
||||
"firstName": "J. W.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Quigley",
|
||||
"firstName": "Karen S.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Barrett",
|
||||
"firstName": "Lisa Feldman",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021",
|
||||
"DOI": "10.1037/bul0000327",
|
||||
"ISSN": "1939-1455",
|
||||
"abstractNote": "Expertise refers to outstanding skill or ability in a particular domain. In the domain of emotion, expertise refers to the observation that some people are better at a range of competencies related to understanding and experiencing emotions, and these competencies may help them lead healthier lives. These individual differences are represented by multiple constructs including emotional awareness, emotional clarity, emotional complexity, emotional granularity, and emotional intelligence. These constructs derive from different theoretical perspectives, highlight different competencies, and are operationalized and measured in different ways. The full set of relationships between these constructs has not yet been considered, hindering scientific progress and the translation of findings to aid mental and physical well-being. In this article, we use a scoping review procedure to integrate these constructs within a shared conceptual space. Scoping reviews provide a principled means of synthesizing large and diverse literature in a transparent fashion, enabling the identification of similarities as well as gaps and inconsistencies across constructs. Using domain-general accounts of expertise as a guide, we build a unifying framework for expertise in emotion and apply this to constructs that describe how people understand and experience their own emotions. Our approach offers opportunities to identify potential mechanisms of expertise in emotion, encouraging future research on those mechanisms and on educational or clinical interventions. (PsycInfo Database Record (c) 2023 APA, all rights reserved)",
|
||||
"issue": "11",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"pages": "1159-1183",
|
||||
"publicationTitle": "Psychological Bulletin",
|
||||
"shortTitle": "Expertise in emotion",
|
||||
"volume": "147",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Alexithymia"
|
||||
},
|
||||
{
|
||||
"tag": "Awareness"
|
||||
},
|
||||
{
|
||||
"tag": "Conceptual Imagery"
|
||||
},
|
||||
{
|
||||
"tag": "Creativity"
|
||||
},
|
||||
{
|
||||
"tag": "Emotional Intelligence"
|
||||
},
|
||||
{
|
||||
"tag": "Emotions"
|
||||
},
|
||||
{
|
||||
"tag": "Experience Level"
|
||||
},
|
||||
{
|
||||
"tag": "Experiences (Events)"
|
||||
},
|
||||
{
|
||||
"tag": "Individual Differences"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/buy/2004-16329-002",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -712,7 +561,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/2010-19350-001",
|
||||
"url": "http://psycnet.apa.org/buy/2010-19350-001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -746,17 +595,16 @@ var testCases = [
|
|||
],
|
||||
"date": "2010",
|
||||
"DOI": "10.1037/a0020280",
|
||||
"ISSN": "1939-2222",
|
||||
"ISSN": "1939-2222(Electronic),0096-3445(Print)",
|
||||
"abstractNote": "Social scientists often rely on economic experiments such as ultimatum and dictator games to understand human cooperation. Systematic deviations from economic predictions have inspired broader conceptions of self-interest that incorporate concerns for fairness. Yet no framework can describe all of the major results. We take a different approach by asking players directly about their self-interest—defined as what they want to do (pleasure-maximizing options). We also ask players directly about their sense of fairness—defined as what they think they ought to do (fairness-maximizing options). Player-defined measures of self-interest and fairness predict (a) the majority of ultimatum-game and dictator-game offers, (b) ultimatum-game rejections, (c) exiting behavior (i.e., escaping social expectations to cooperate) in the dictator game, and (d) who cooperates more after a positive mood induction. Adopting the players' perspectives of self-interest and fairness permits better predictions about who cooperates, why they cooperate, and when they punish noncooperators. (PsycINFO Database Record (c) 2016 APA, all rights reserved)",
|
||||
"issue": "4",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"pages": "743-755",
|
||||
"publicationTitle": "Journal of Experimental Psychology: General",
|
||||
"volume": "139",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -786,8 +634,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/2010-09295-002",
|
||||
"defer": true,
|
||||
"url": "http://psycnet.apa.org/record/2010-09295-002",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -801,18 +648,17 @@ var testCases = [
|
|||
],
|
||||
"date": "2011",
|
||||
"ISBN": "9781433808616 9781433808623",
|
||||
"abstractNote": "In this chapter, I seek to redress vocational psychology’s inattention to the self and address the ambiguity of the meaning of self. To begin, I offer a chronological survey of vocational psychology’s three main views of human singularity. During succeeding historical eras, different aspects of human singularity interested vocational psychologists, so they developed a new set of terms and concepts to deal with shifts in the meaning of individuality. Over time, vocational psychology developed what Kuhn (2000) referred to as language communities, each with its own paradigm for understanding the self and vocational behavior. Because the self is fundamentally ambiguous, adherents to each paradigm describe it with an agreed on language and metaphors. Thus, each paradigm has a textual tradition, or way of talking about the self. As readers shall see, when they talk about individuals, differentialists use the language of personality, developmentalists use the language of personhood, and constructionists use the language of identity. (PsycInfo Database Record (c) 2024 APA, all rights reserved)",
|
||||
"abstractNote": "In this chapter, I seek to redress vocational psychology’s inattention to the self and address the ambiguity of the meaning of self. To begin, I offer a chronological survey of vocational psychology’s three main views of human singularity. During succeeding historical eras, different aspects of human singularity interested vocational psychologists, so they developed a new set of terms and concepts to deal with shifts in the meaning of individuality. Over time, vocational psychology developed what Kuhn (2000) referred to as language communities, each with its own paradigm for understanding the self and vocational behavior. Because the self is fundamentally ambiguous, adherents to each paradigm describe it with an agreed on language and metaphors. Thus, each paradigm has a textual tradition, or way of talking about the self. As readers shall see, when they talk about individuals, differentialists use the language of personality, developmentalists use the language of personhood, and constructionists use the language of identity. (PsycINFO Database Record (c) 2017 APA, all rights reserved)",
|
||||
"bookTitle": "Developing self in work and career: Concepts, cases, and contexts",
|
||||
"extra": "DOI: 10.1037/12348-002",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"libraryCatalog": "APA PsycNET",
|
||||
"pages": "17-33",
|
||||
"place": "Washington, DC, US",
|
||||
"publisher": "American Psychological Association",
|
||||
"shortTitle": "The self in vocational psychology",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -830,86 +676,6 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://psycnet.apa.org/record/2025-80032-001?doi=1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Linking adolescent bullying perpetration with adult fertility: Two preliminary studies",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Volk",
|
||||
"firstName": "Anthony A.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Brazil",
|
||||
"firstName": "Kristopher J.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Dane",
|
||||
"firstName": "Andrew V.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Vaillancourt",
|
||||
"firstName": "Tracy",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Al-Jbouri",
|
||||
"firstName": "Elizabeth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Farrell",
|
||||
"firstName": "Ann H.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2025",
|
||||
"DOI": "10.1037/ebs0000374",
|
||||
"ISSN": "2330-2933",
|
||||
"abstractNote": "Researchers have suggested that bullying perpetration is, at least in part, an evolved adaptation. A key prediction of this evolutionary perspective is that bullying facilitates the transmission of genes from one generation to the next. To date, only one study (using a limited measure of bullying) has examined the link between adolescent bullying and adult fertility, showing a positive association between adolescent bullying and number of children in adulthood. We sought to replicate and expand this unique finding using a more robust measure of adolescent bullying and young adults’ parental status in a prospective longitudinal study of Canadians (Study 1), along with an MTurk study of retrospective adolescent bullying and current adult fertility (Study 2). In support of an evolutionary theory of bullying, we found that higher bullying was associated with having children in young adulthood (ages 23 and/or 24 years, Study 1) and that retrospective reports of adolescent bullying were associated with having more children in adulthood (Study 2). Overall, our studies offer additional support for the idea that adolescent bullying is, at least in part, an evolutionary adaptation that may help individuals to later pass on their genes to future generations through enhanced reproductive and perhaps parental effort. Although needing replication, our data highlight the importance of considering reproductive outcomes when designing future bullying research or interventions. (PsycInfo Database Record (c) 2025 APA, all rights reserved)",
|
||||
"libraryCatalog": "APA PsycNet",
|
||||
"publicationTitle": "Evolutionary Behavioral Sciences",
|
||||
"shortTitle": "Linking adolescent bullying perpetration with adult fertility",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Adaptation"
|
||||
},
|
||||
{
|
||||
"tag": "Adolescent Characteristics"
|
||||
},
|
||||
{
|
||||
"tag": "Bullying"
|
||||
},
|
||||
{
|
||||
"tag": "Fertility"
|
||||
},
|
||||
{
|
||||
"tag": "Genes"
|
||||
},
|
||||
{
|
||||
"tag": "Parenthood Status"
|
||||
},
|
||||
{
|
||||
"tag": "Theory of Evolution"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
241
APS-Physics.js
241
APS-Physics.js
|
|
@ -1,204 +1,165 @@
|
|||
{
|
||||
"translatorID": "f318ab1e-71c6-4f67-8ac3-4b1144e5bf4e",
|
||||
"label": "APS-Physics",
|
||||
"creator": "Will Shanks and Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?(physics)\\.aps\\.org/",
|
||||
"creator": "Will Shanks",
|
||||
"target": "^https?://(www\\.)?(physics)\\.aps\\.org([^/]*/(articles|story)/?|/browse(\\?|$))",
|
||||
"minVersion": "2.1.9",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-31 22:13:29"
|
||||
"lastUpdated": "2013-12-06 17:44:20"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
// Works for APS Physics Viewpoints and Focus articles: http://physics.aps.org/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (doc.querySelector('meta[name="citation_title"]')) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h3.feed-item-title > a[href*="/articles/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
if (url.indexOf("/browse")!=-1) return "multiple";
|
||||
else return "journalArticle";
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
if (!item.DOI) {
|
||||
item.DOI = ZU.cleanDOI(attr(doc, 'a[href*="link.aps.org/doi"]', 'href'));
|
||||
if (detectWeb(doc, url)=="multiple"){
|
||||
var items = {};
|
||||
var articles = [];
|
||||
var links = ZU.xpath(doc, '//div[@class="result-title"]/h2/a[contains(@href, "/story/") or contains(@href, "/articles/")]')
|
||||
for (var i in links){
|
||||
items[ZU.xpathText(links[i], './@href')] = ZU.xpathText(links[i], './text()')
|
||||
}
|
||||
|
||||
// both snapshot and PDF: HTML is commentary, PDF is article
|
||||
item.attachments = [];
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
for (var itemurl in items) {
|
||||
articles.push(itemurl);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape)
|
||||
});
|
||||
item.attachments.push({
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf',
|
||||
url: `https://physics.aps.org/articles/pdf/${item.DOI}`
|
||||
});
|
||||
|
||||
item.libraryCatalog = 'APS Physics';
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.addCustomFields({
|
||||
'citation_pages': 'pages'
|
||||
});
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
else scrape(doc, url);
|
||||
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
function scrape(doc, url){
|
||||
Zotero.debug(doc.title);
|
||||
|
||||
//Get abstract (called 'byline' on page)
|
||||
var abs = ZU.xpathText(doc, '//article/header/p[contains(@class, "byline")]');
|
||||
|
||||
//Check if page is a Viewpoint. Only Viewpoints have PDFs
|
||||
var title = ZU.xpathText(doc, '//article/header/h1[contains(@class, "title")]');
|
||||
var hasPDF = (title.indexOf('Viewpoint:') != -1);
|
||||
|
||||
//Get DOI
|
||||
var doi = ZU.xpathText(doc, '//article/header/div[contains(@class, "pubinfo")]/text()');
|
||||
doi = doi.match(/10\.[^\s]+/)[0]
|
||||
|
||||
//Set up urls
|
||||
var pdfurl = 'http://physics.aps.org/articles/pdf/' + doi;
|
||||
var urlRIS = 'http://physics.aps.org/articles/export/' + doi + '/ris';
|
||||
|
||||
Zotero.Utilities.HTTP.doGet(urlRIS, function(text) {
|
||||
//DOI is stored in ID field. Fix it.
|
||||
text = text.replace(/^ID\s\s?-\s/mg, 'DO - ');
|
||||
// load translator for RIS
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
translator.setHandler("itemDone", function(obj, item) {
|
||||
item.attachments = [
|
||||
{document:doc, title:"APS Snapshot"}];
|
||||
if (hasPDF) {
|
||||
item.attachments.push({url:pdfurl, title:"APS Full Text PDF", mimeType:"application/pdf"});
|
||||
}
|
||||
|
||||
if (abs) item.abstractNote = abs;
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://physics.aps.org/articles/v5/100",
|
||||
"url": "http://physics.aps.org/articles/v5/100",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Surface Folds Make Tears and Chips",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sissi de",
|
||||
"lastName": "Beer",
|
||||
"lastName": "de Beer",
|
||||
"firstName": "Sissi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Martin H.",
|
||||
"lastName": "Müser",
|
||||
"firstName": "Martin H.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2012/09/04",
|
||||
"DOI": "10.1103/PhysRevLett.109.106001",
|
||||
"abstractNote": "Fluidlike folding instabilities of solid surfaces complicate the machining of metals to perfection",
|
||||
"language": "en",
|
||||
"libraryCatalog": "APS Physics",
|
||||
"pages": "100",
|
||||
"publicationTitle": "Physics",
|
||||
"rights": "©2012 by the American Physical Society. All rights reserved.",
|
||||
"url": "https://physics.aps.org/articles/v5/100",
|
||||
"volume": "5",
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
},
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"title": "APS Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"publisher": "American Physical Society",
|
||||
"DOI": "10.1103/Physics.5.100",
|
||||
"title": "Surface Folds Make Tears and Chips",
|
||||
"publicationTitle": "Physics",
|
||||
"journalAbbreviation": "Physics",
|
||||
"volume": "5",
|
||||
"pages": "100",
|
||||
"date": "September 4, 2012",
|
||||
"url": "http://link.aps.org/doi/10.1103/Physics.5.100",
|
||||
"abstractNote": "Fluidlike folding instabilities of solid surfaces complicate the machining of metals to perfection",
|
||||
"libraryCatalog": "APS-Physics",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://physics.aps.org/articles/v5/101",
|
||||
"url": "http://physics.aps.org/articles/v5/101",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Measuring the Smallest Trickle",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Michael",
|
||||
"lastName": "Schirber",
|
||||
"firstName": "Michael",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2012/09/10",
|
||||
"DOI": "10.1103/PhysRevLett.109.118302",
|
||||
"abstractNote": "Researchers used a nanoscale tunnel in a silicon chip to measure a flow rate of a few picoliters per minute, which is smaller than any previous observation.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "APS Physics",
|
||||
"pages": "101",
|
||||
"publicationTitle": "Physics",
|
||||
"rights": "©2012 by the American Physical Society. All rights reserved.",
|
||||
"url": "https://physics.aps.org/articles/v5/101",
|
||||
"volume": "5",
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"publisher": "American Physical Society",
|
||||
"DOI": "10.1103/Physics.5.101",
|
||||
"title": "Measuring the Smallest Trickle",
|
||||
"publicationTitle": "Physics",
|
||||
"journalAbbreviation": "Physics",
|
||||
"volume": "5",
|
||||
"pages": "101",
|
||||
"date": "September 10, 2012",
|
||||
"url": "http://link.aps.org/doi/10.1103/Physics.5.101",
|
||||
"abstractNote": "Researchers used a nanoscale tunnel in a silicon chip to measure a flow rate of a few picoliters per minute, which is smaller than any previous observation.",
|
||||
"libraryCatalog": "APS-Physics",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://physics.aps.org/browse/?page=1&per_page=10&sort=relevance&q=test",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
228
APS.js
228
APS.js
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"translatorID": "2c310a37-a4dd-48d2-82c9-bd29c53c1c76",
|
||||
"label": "APS",
|
||||
"creator": "Aurimas Vinckevicius and Abe Jellinek",
|
||||
"creator": "Aurimas Vinckevicius",
|
||||
"target": "^https?://journals\\.aps\\.org/([^/]+/(abstract|supplemental|references|cited-by|issues)/|search(\\?|/))",
|
||||
"minVersion": "3.0.12",
|
||||
"maxVersion": "",
|
||||
|
|
@ -9,52 +9,24 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-11-21 18:50:09"
|
||||
"lastUpdated": "2017-01-14 21:44:41"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Aurimas Vinckevicius and Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (doc.querySelector('#article-body #export-article-dialog')
|
||||
|| doc.querySelector('main#main') && /^\/[^/]+\/(abstract|supplemental|references|cited-by)\//.test(new URL(url).pathname)) {
|
||||
var title = doc.getElementById('title');
|
||||
if (title && ZU.xpath(title, './/a[@id="export-article-link"]').length) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
} else if (getSearchResults(doc, true)){
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('#issue-body .headline .title > a');
|
||||
if (!rows.length) {
|
||||
rows = doc.querySelectorAll('#search-main h3 > a');
|
||||
}
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var rows = ZU.xpath(doc, '//div[contains(@class, "search-results")]//div[contains(@class, "row")]//h5/a');
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(cleanMath(rows[i].textContent));
|
||||
if (!href || !title) continue;
|
||||
|
|
@ -70,7 +42,7 @@ function doWeb(doc, url) {
|
|||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
|
|
@ -78,8 +50,7 @@ function doWeb(doc, url) {
|
|||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
|
@ -87,13 +58,13 @@ function doWeb(doc, url) {
|
|||
|
||||
// Extension to mimeType mapping
|
||||
var suppTypeMap = {
|
||||
pdf: 'application/pdf',
|
||||
zip: 'application/zip',
|
||||
doc: 'application/msword',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
xls: 'application/vnd.ms-excel',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
mov: 'video/quicktime'
|
||||
'pdf': 'application/pdf',
|
||||
'zip': 'application/zip',
|
||||
'doc': 'application/msword',
|
||||
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'xls': 'application/vnd.ms-excel',
|
||||
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'mov': 'video/quicktime'
|
||||
};
|
||||
|
||||
var dontDownload = [
|
||||
|
|
@ -104,20 +75,20 @@ var dontDownload = [
|
|||
function scrape(doc, url) {
|
||||
url = url.replace(/[?#].*/, '');
|
||||
|
||||
if (!url.includes('/abstract/')) {
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
// Go to Abstract page first so we can scrape the abstract
|
||||
url = url.replace(/\/(?:supplemental|references|cited-by)\//, '/abstract/');
|
||||
if (!url.includes('/abstract/')) {
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
Zotero.debug('Unrecognized URL ' + url);
|
||||
return;
|
||||
}
|
||||
|
||||
ZU.processDocuments(url, function (doc, url) {
|
||||
if (!url.includes('/abstract/')) {
|
||||
ZU.processDocuments(url, function(doc, url) {
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
Zotero.debug('Redirected when trying to go to abstract page. ' + url);
|
||||
return;
|
||||
}
|
||||
scrape(doc, url);
|
||||
scrape(doc, url)
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -126,23 +97,26 @@ function scrape(doc, url) {
|
|||
|
||||
// fetch RIS
|
||||
var risUrl = url.replace('{REPLACE}', 'export')
|
||||
+ '?type=ris&download=true';
|
||||
ZU.doGet(risUrl, function (risText) {
|
||||
risText = risText.replace(/^ID\s+-\s+/mg, 'DO - ');
|
||||
+ '?type=ris&download=true';
|
||||
ZU.doGet(risUrl, function(text) {
|
||||
text = text.replace(/^ID\s+-\s+/mg, 'DO - ');
|
||||
var trans = Zotero.loadTranslator('import');
|
||||
trans.setTranslator('32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7'); //RIS
|
||||
trans.setString(risText);
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
trans.setString(text);
|
||||
trans.setHandler('itemDone', function(obj, item) {
|
||||
// scrape abstract from page
|
||||
item.abstractNote = ZU.trimInternal(cleanMath(
|
||||
text(doc, '#abstract-section-content p')
|
||||
ZU.xpathText(doc, '//section[contains(@class,"abstract")]/div[@class="content"]/p[1]')
|
||||
));
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Full Text PDF',
|
||||
url: url.replace('{REPLACE}', 'pdf'),
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
// attach PDF
|
||||
if (ZU.xpath(doc, '//div[@class="article-nav-actions"]/a[contains(text(), "PDF")]').length) {
|
||||
item.attachments.push({
|
||||
title: 'Full Text PDF',
|
||||
url: url.replace('{REPLACE}', 'pdf'),
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
title: "APS Snapshot",
|
||||
|
|
@ -150,37 +124,38 @@ function scrape(doc, url) {
|
|||
});
|
||||
|
||||
if (Z.getHiddenPref && Z.getHiddenPref('attachSupplementary')) {
|
||||
try {
|
||||
var asLink = Z.getHiddenPref('supplementaryAsLink');
|
||||
var suppFiles = doc.querySelectorAll('.supplemental-file');
|
||||
for (let suppFile of suppFiles) {
|
||||
let link = suppFile.querySelector('a');
|
||||
if (!link || !link.href) continue;
|
||||
var title = link.getAttribute('data-id') || 'Supplementary Data';
|
||||
var type = suppTypeMap[link.href.split('.').pop()];
|
||||
if (asLink || dontDownload.includes(type)) {
|
||||
item.attachments.push({
|
||||
title: title,
|
||||
url: link.href,
|
||||
mimeType: type || 'text/html',
|
||||
snapshot: false
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: title,
|
||||
url: link.href,
|
||||
mimeType: type
|
||||
});
|
||||
ZU.processDocuments(url.replace('{REPLACE}', 'supplemental'), function(doc) {
|
||||
try {
|
||||
var asLink = Z.getHiddenPref('supplementaryAsLink');
|
||||
var suppFiles = doc.getElementsByClassName('supplemental-file');
|
||||
for (var i=0; i<suppFiles.length; i++) {
|
||||
var link = suppFiles[i].getElementsByTagName('a')[0];
|
||||
if (!link || !link.href) continue;
|
||||
var title = link.getAttribute('data-id') || 'Supplementary Data';
|
||||
var type = suppTypeMap[link.href.split('.').pop()];
|
||||
if (asLink || dontDownload.indexOf(type) != -1) {
|
||||
item.attachments.push({
|
||||
title: title,
|
||||
url: link.href,
|
||||
mimeType: type || 'text/html',
|
||||
snapshot: false
|
||||
});
|
||||
} else {
|
||||
item.attachments.push({
|
||||
title: title,
|
||||
url: link.href,
|
||||
mimeType: type
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Z.debug('Could not attach supplemental data');
|
||||
Z.debug(e);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Z.debug('Could not attach supplemental data');
|
||||
Z.debug(e);
|
||||
}
|
||||
}, function() { item.complete() });
|
||||
} else {
|
||||
item.complete();
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
|
|
@ -190,7 +165,6 @@ function cleanMath(str) {
|
|||
//math tags appear to have duplicate content and are somehow left in even after textContent
|
||||
return str.replace(/<(math|mi)[^<>]*>.*?<\/\1>/g, '');
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -212,7 +186,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011-10-21",
|
||||
"date": "October 21, 2011",
|
||||
"DOI": "10.1103/PhysRevD.84.077701",
|
||||
"abstractNote": "We reconsider Higgs boson invisible decays into Dark Matter in the light of recent Higgs searches at the LHC. Present hints in the Compact Muon Solenoid and ATLAS data favor a nonstandard Higgs boson with approximately 50% invisible branching ratio, and mass around 143 GeV. This situation can be realized within the simplest thermal scalar singlet Dark Matter model, predicting a Dark Matter mass around 50 GeV and direct detection cross section just below present bound. The present runs of the Xenon100 and LHC experiments can test this possibility.",
|
||||
"issue": "7",
|
||||
|
|
@ -228,8 +202,7 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -287,9 +260,9 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-03-04",
|
||||
"date": "March 4, 2015",
|
||||
"DOI": "10.1103/PhysRevLett.114.098105",
|
||||
"abstractNote": "Cellular aggregates (spheroids) are widely used in biophysics and tissue engineering as model systems for biological tissues. In this Letter we propose novel methods for molding stem-cell spheroids, deforming them, and measuring their interfacial and elastic properties with a single method based on cell tagging with magnetic nanoparticles and application of a magnetic field gradient. Magnetic molding yields spheroids of unprecedented sizes (up to a few mm in diameter) and preserves tissue integrity. On subjecting these spheroids to magnetic flattening (over ), we observed a size-dependent elastocapillary transition with two modes of deformation: liquid-drop-like behavior for small spheroids, and elastic-sphere-like behavior for larger spheroids, followed by relaxation to a liquidlike drop.",
|
||||
"abstractNote": "Cellular aggregates (spheroids) are widely used in biophysics and tissue engineering as model systems for biological tissues. In this Letter we propose novel methods for molding stem-cell spheroids, deforming them, and measuring their interfacial and elastic properties with a single method based on cell tagging with magnetic nanoparticles and application of a magnetic field gradient. Magnetic molding yields spheroids of unprecedented sizes (up to a few mm in diameter) and preserves tissue integrity. On subjecting these spheroids to magnetic flattening (over 150g), we observed a size-dependent elastocapillary transition with two modes of deformation: liquid-drop-like behavior for small spheroids, and elastic-sphere-like behavior for larger spheroids, followed by relaxation to a liquidlike drop.",
|
||||
"issue": "9",
|
||||
"journalAbbreviation": "Phys. Rev. Lett.",
|
||||
"libraryCatalog": "APS",
|
||||
|
|
@ -303,8 +276,7 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -347,7 +319,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-03-17",
|
||||
"date": "March 17, 2015",
|
||||
"DOI": "10.1103/PhysRevX.5.011029",
|
||||
"abstractNote": "Based on first-principle calculations, we show that a family of nonmagnetic materials including TaAs, TaP, NbAs, and NbP are Weyl semimetals (WSM) without inversion centers. We find twelve pairs of Weyl points in the whole Brillouin zone (BZ) for each of them. In the absence of spin-orbit coupling (SOC), band inversions in mirror-invariant planes lead to gapless nodal rings in the energy-momentum dispersion. The strong SOC in these materials then opens full gaps in the mirror planes, generating nonzero mirror Chern numbers and Weyl points off the mirror planes. The resulting surface-state Fermi arc structures on both (001) and (100) surfaces are also obtained, and they show interesting shapes, pointing to fascinating playgrounds for future experimental studies.",
|
||||
"issue": "1",
|
||||
|
|
@ -363,8 +335,7 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -407,7 +378,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-03-17",
|
||||
"date": "March 17, 2015",
|
||||
"DOI": "10.1103/PhysRevX.5.011029",
|
||||
"abstractNote": "Based on first-principle calculations, we show that a family of nonmagnetic materials including TaAs, TaP, NbAs, and NbP are Weyl semimetals (WSM) without inversion centers. We find twelve pairs of Weyl points in the whole Brillouin zone (BZ) for each of them. In the absence of spin-orbit coupling (SOC), band inversions in mirror-invariant planes lead to gapless nodal rings in the energy-momentum dispersion. The strong SOC in these materials then opens full gaps in the mirror planes, generating nonzero mirror Chern numbers and Weyl points off the mirror planes. The resulting surface-state Fermi arc structures on both (001) and (100) surfaces are also obtained, and they show interesting shapes, pointing to fascinating playgrounds for future experimental studies.",
|
||||
"issue": "1",
|
||||
|
|
@ -423,8 +394,7 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -467,7 +437,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-01-20",
|
||||
"date": "January 20, 2015",
|
||||
"DOI": "10.1103/PhysRevX.5.011003",
|
||||
"abstractNote": "We report on a stringent test of the nonclassicality of the motion of a massive quantum particle, which propagates on a discrete lattice. Measuring temporal correlations of the position of single atoms performing a quantum walk, we observe a 6σ violation of the Leggett-Garg inequality. Our results rigorously excludes (i.e., falsifies) any explanation of quantum transport based on classical, well-defined trajectories. We use so-called ideal negative measurements—an essential requisite for any genuine Leggett-Garg test—to acquire information about the atom’s position, yet avoiding any direct interaction with it. The interaction-free measurement is based on a novel atom transport system, which allows us to directly probe the absence rather than the presence of atoms at a chosen lattice site. Beyond the fundamental aspect of this test, we demonstrate the application of the Leggett-Garg correlation function as a witness of quantum superposition. Here, we employ the witness to discriminate different types of walks spanning from merely classical to wholly quantum dynamics.",
|
||||
"issue": "1",
|
||||
|
|
@ -483,53 +453,7 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://journals.aps.org/pra/abstract/10.1103/PhysRevA.65.032314",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Computable measure of entanglement",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Vidal",
|
||||
"firstName": "G.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Werner",
|
||||
"firstName": "R. F.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2002-02-22",
|
||||
"DOI": "10.1103/PhysRevA.65.032314",
|
||||
"abstractNote": "We present a measure of entanglement that can be computed effectively for any mixed state of an arbitrary bipartite system. We show that it does not increase under local manipulations of the system, and use it to obtain a bound on the teleportation capacity and on the distillable entanglement of mixed states.",
|
||||
"issue": "3",
|
||||
"journalAbbreviation": "Phys. Rev. A",
|
||||
"libraryCatalog": "APS",
|
||||
"pages": "032314",
|
||||
"publicationTitle": "Physical Review A",
|
||||
"url": "https://link.aps.org/doi/10.1103/PhysRevA.65.032314",
|
||||
"volume": "65",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "APS Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -539,4 +463,4 @@ var testCases = [
|
|||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,186 +1,150 @@
|
|||
{
|
||||
"translatorID": "72cb2536-3211-41e0-ae8b-974c0385e085",
|
||||
"label": "ARTFL Encyclopedie",
|
||||
"creator": "Sean Takats, Sebastian Karcher, and Abe Jellinek",
|
||||
"target": "^https?://artflsrv\\d+\\.uchicago\\.edu/philologic4/encyclopedie\\d+/(navigate/|query)",
|
||||
"creator": "Sean Takats, Sebastian Karcher",
|
||||
"target": "^https?://artflsrv\\d+\\.uchicago\\.edu/cgi-bin/philologic/(getobject\\.pl\\?[cp]\\.[0-9]+:[0-9]+(:[0-9]+)?\\.encyclopedie|navigate\\.pl\\?encyclopedie|search3t\\?dbname=encyclopedie)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-06-30 19:55:06"
|
||||
"browserSupport": "gcv",
|
||||
"lastUpdated": "2017-01-01 16:50:31"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/navigate/')) {
|
||||
if (url.indexOf("getobject.pl") != -1){
|
||||
return "encyclopediaArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
} else if (url.indexOf("navigate.pl")!=-1){//browsing
|
||||
return "multiple";
|
||||
} else if (url.indexOf("search3t?")!=-1){//search results
|
||||
return "multiple"
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.philologic_cite .citation:first-child a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
function reconcileAuthor(author){
|
||||
var authorMap = {
|
||||
"Venel":"Venel, Gabriel-François",
|
||||
"d'Aumont":"d'Aumont, Arnulphe",
|
||||
"de La Chapelle":"de La Chapelle, Jean-Baptiste",
|
||||
"Bourgelat":"Bourgelat, Claude",
|
||||
"Dumarsais":"Du Marsais, César Chesneau",
|
||||
"Mallet":"Mallet, Edme-François",
|
||||
"Toussaint":"Toussaint, François-Vincent",
|
||||
"Daubenton":"Daubenton, Louis-Jean-Marie",
|
||||
"d'Argenville": "d'Argenville, Antoine-Joseph Desallier",
|
||||
"Tarin":"Tarin, Pierre",
|
||||
"Vandenesse":"de Vandenesse, Urbain",
|
||||
"Blondel": "Blondel, Jacques-François",
|
||||
"Le Blond":"Le Blond, Guillaume",
|
||||
"Rousseau":"Rousseau, Jean-Jacques",
|
||||
"Eidous":"Eidous, Marc-Antoine",
|
||||
"d'Alembert":"d'Alembert, Jean le Rond",
|
||||
"Louis":"Louis, Antoine",
|
||||
"Bellin":"Bellin, Jacques-Nicolas",
|
||||
"Diderot":"Diderot, Denis",
|
||||
"Diderot1":"Diderot, Denis",
|
||||
"Diderot2":"Diderot, Denis",
|
||||
"de Jaucourt":"de Jaucourt, Chevalier Louis",
|
||||
"Jaucourt":"de Jaucourt, Chevalier Louis",
|
||||
"d'Holbach":"d'Holbach, Baron"
|
||||
/* not yet mapped
|
||||
Yvon
|
||||
Forbonnais
|
||||
Douchet and Beauzée
|
||||
Boucher d'Argis
|
||||
Lenglet Du Fresnoy
|
||||
Cahusac
|
||||
Pestré
|
||||
Daubenton, le Subdélégué
|
||||
Goussier
|
||||
de Villiers
|
||||
Barthès
|
||||
Morellet
|
||||
Malouin
|
||||
Ménuret de Chambaud
|
||||
Landois
|
||||
Le Roy
|
||||
*/
|
||||
}
|
||||
return found ? items : false;
|
||||
if (authorMap[author]) {
|
||||
author = authorMap[author];
|
||||
}
|
||||
// remove ARTFL's trailing 5 for odd contributors (e.g. Turgot5)
|
||||
if (author.substr(author.length-1, 1)=="5"){
|
||||
author = author.substr(0, author.length-1);
|
||||
}
|
||||
return author;
|
||||
}
|
||||
|
||||
function scrape (doc, url){
|
||||
var newItem = new Zotero.Item("encyclopediaArticle");
|
||||
newItem.title = ZU.xpathText(doc, '(//index[@type="headword"])[1]/@value')
|
||||
newItem.encyclopediaTitle = "Encyclopédie, ou Dictionnaire raisonné des sciences, des arts et des métiers";
|
||||
newItem.shortTitle = "Encyclopédie";
|
||||
newItem.date = "1751-1772";
|
||||
newItem.publisher = "Briasson";
|
||||
newItem.place = "Paris";
|
||||
newItem.numberOfVolumes = "17";
|
||||
newItem.creators.push({firstName:"Denis", lastName:"Diderot", creatorType:"editor"});
|
||||
newItem.creators.push({firstName:"Jean le Rond", lastName:"d'Alembert", creatorType:"editor"});
|
||||
newItem.url = url;
|
||||
newItem.attachments.push({title:"ARTFL Snapshot", mimeType:"text/html", document:doc});
|
||||
|
||||
var volpage = ZU.xpathText(doc, '(//index/a[contains(@href, "getobject.pl") and contains(text(), ":")])[1]');
|
||||
if (!volpage){//pageview
|
||||
var volpage = ZU.xpathText(doc, '//div[@id="content"]/center[contains(text(), ":")]/text()')
|
||||
}
|
||||
if (volpage){
|
||||
volpage = volpage.match(/(\d+):([A-Z\d]+)/); //page number can have letters
|
||||
newItem.volume = volpage[1];
|
||||
newItem.pages = volpage[2];
|
||||
}
|
||||
var authors = ZU.xpathText(doc, '(//index[@type="author"])[1]/@value');
|
||||
if (authors){
|
||||
author = authors.split(/\s*\|\s*/);
|
||||
for (var i =0; i<author.length; i++){
|
||||
newItem.creators.push(ZU.cleanAuthor(reconcileAuthor(author[i]), "author", true))
|
||||
}
|
||||
}
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
|
||||
if (url.indexOf("getobject.pl") != -1){
|
||||
// single article
|
||||
scrape(doc, url);
|
||||
} else {
|
||||
//search page
|
||||
var items = {};
|
||||
var urls = [];
|
||||
var xpath = '//a[contains(@href, "getobject.pl")]';
|
||||
var elmts = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var elmt;
|
||||
while (elmt = elmts.iterateNext()){
|
||||
var title = elmt.textContent;
|
||||
var link = elmt.href;
|
||||
if (title && link){
|
||||
items[link] = title;
|
||||
}
|
||||
}
|
||||
Z.selectItems(items, function(items) {
|
||||
if (items == null) return true;
|
||||
for (var j in items) {
|
||||
urls.push(j);
|
||||
}
|
||||
ZU.processDocuments(urls, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url) {
|
||||
let path = url.match(/(\/philologic4\/[^/]+\/)navigate((?:\/\d+)+)/);
|
||||
if (!path) {
|
||||
throw new Error('Unknown entry path format');
|
||||
}
|
||||
|
||||
let [, base, id] = path;
|
||||
id = id.replace(/\//g, ' ').trim();
|
||||
|
||||
ZU.doGet(
|
||||
`${base}reports/navigation.py?report=navigation&philo_id=${id}&byte=`,
|
||||
function (respText) {
|
||||
let json = JSON.parse(respText);
|
||||
scrapeFromJSON(doc, url, json);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function scrapeFromJSON(doc, url, json) {
|
||||
let item = new Zotero.Item('encyclopediaArticle');
|
||||
let meta = json.metadata_fields;
|
||||
|
||||
item.title = meta.head;
|
||||
item.encyclopediaTitle = meta.title.replace(/\.?\s*Tome \d+\.?/, '');
|
||||
item.volume = meta.vol;
|
||||
item.numberOfVolumes = '17';
|
||||
item.place = meta.pub_place;
|
||||
item.publisher = meta.publisher;
|
||||
item.date = meta.pub_date;
|
||||
|
||||
let firstPage;
|
||||
let lastPage;
|
||||
|
||||
let pageRe = /\[page \d+:([\da-zA-Z]+)\]/g;
|
||||
let matchArray;
|
||||
while ((matchArray = pageRe.exec(json.text)) !== null) {
|
||||
// iterate through page heading matches. if we haven't set the first
|
||||
// page yet, set it to the page in the heading we just found. always
|
||||
// set the last page to the heading we just found. when we're done,
|
||||
// the first page will correspond to the first heading and the last page
|
||||
// to the last.
|
||||
|
||||
if (!firstPage) {
|
||||
firstPage = matchArray[1];
|
||||
}
|
||||
lastPage = matchArray[1];
|
||||
}
|
||||
|
||||
if (firstPage && lastPage) {
|
||||
if (firstPage == lastPage) {
|
||||
item.pages = firstPage;
|
||||
}
|
||||
else {
|
||||
item.pages = `${firstPage}-${lastPage}`;
|
||||
}
|
||||
}
|
||||
|
||||
item.url = url;
|
||||
item.language = 'fr';
|
||||
item.archive = 'ARTFL Encyclopédie Project (Spring 2021 Edition)';
|
||||
item.libraryCatalog = '';
|
||||
|
||||
item.creators.push({
|
||||
firstName: "Denis",
|
||||
lastName: "Diderot",
|
||||
creatorType: "editor"
|
||||
});
|
||||
|
||||
item.creators.push({
|
||||
firstName: "Jean le Rond",
|
||||
lastName: "d'Alembert",
|
||||
creatorType: "editor"
|
||||
});
|
||||
|
||||
item.creators.push(
|
||||
ZU.cleanAuthor(
|
||||
meta.kafauth.replace(/\s*\(.*\)/, ''), 'author', true
|
||||
)
|
||||
);
|
||||
|
||||
if (doc) {
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
|
||||
if (json.imgs.current_obj_img && json.imgs.current_obj_img.length) {
|
||||
let url = json.imgs.current_obj_img[0];
|
||||
item.attachments.push({
|
||||
title: 'Page Scan',
|
||||
mimeType: `image/${url.split('.').pop()}`,
|
||||
url
|
||||
});
|
||||
}
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://artflsrv03.uchicago.edu/philologic4/encyclopedie0521/navigate/1/929/",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/getobject.pl?c.0:683:1.encyclopedie0513",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "ADULTERE",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Denis",
|
||||
|
|
@ -192,45 +156,51 @@ var testCases = [
|
|||
"lastName": "d'Alembert",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "Yvon",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "François-Vincent",
|
||||
"lastName": "Toussaint",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1751",
|
||||
"archive": "ARTFL Encyclopédie Project (Spring 2021 Edition)",
|
||||
"encyclopediaTitle": "Encyclopédie, Dictionnaire raisonné des sciences, des arts et des métiers, par une Société de Gens de lettres",
|
||||
"language": "fr",
|
||||
"numberOfVolumes": "17",
|
||||
"pages": "150",
|
||||
"place": "Paris",
|
||||
"publisher": "Le Breton",
|
||||
"url": "https://artflsrv03.uchicago.edu/philologic4/encyclopedie0521/navigate/1/929/",
|
||||
"volume": "1",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"title": "Page Scan",
|
||||
"mimeType": "image/jpeg"
|
||||
"firstName": "Denis",
|
||||
"lastName": "Diderot",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "ARTFL Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"title": "Adultere",
|
||||
"encyclopediaTitle": "Encyclopédie, ou Dictionnaire raisonné des sciences, des arts et des métiers",
|
||||
"shortTitle": "Encyclopédie",
|
||||
"date": "1751-1772",
|
||||
"publisher": "Briasson",
|
||||
"place": "Paris",
|
||||
"numberOfVolumes": "17",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/getobject.pl?c.0:683:1.encyclopedie0513",
|
||||
"volume": "1",
|
||||
"pages": "150",
|
||||
"libraryCatalog": "ARTFL Encyclopedie",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://artflsrv03.uchicago.edu/philologic4/encyclopedie0521/navigate/1/925/",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/getobject.pl?p.0:203.encyclopedie0513",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "ADULTE",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Denis",
|
||||
|
|
@ -248,36 +218,39 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1751",
|
||||
"archive": "ARTFL Encyclopédie Project (Spring 2021 Edition)",
|
||||
"encyclopediaTitle": "Encyclopédie, Dictionnaire raisonné des sciences, des arts et des métiers, par une Société de Gens de lettres",
|
||||
"language": "fr",
|
||||
"numberOfVolumes": "17",
|
||||
"pages": "150",
|
||||
"place": "Paris",
|
||||
"publisher": "Le Breton",
|
||||
"url": "https://artflsrv03.uchicago.edu/philologic4/encyclopedie0521/navigate/1/925/",
|
||||
"volume": "1",
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"title": "ARTFL Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"title": "Page Scan",
|
||||
"mimeType": "image/jpeg"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"title": "ADULTE",
|
||||
"encyclopediaTitle": "Encyclopédie, ou Dictionnaire raisonné des sciences, des arts et des métiers",
|
||||
"shortTitle": "Encyclopédie",
|
||||
"date": "1751-1772",
|
||||
"publisher": "Briasson",
|
||||
"place": "Paris",
|
||||
"numberOfVolumes": "17",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/getobject.pl?p.0:203.encyclopedie0513",
|
||||
"volume": "1",
|
||||
"pages": "150",
|
||||
"libraryCatalog": "ARTFL Encyclopedie",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://artflsrv03.uchicago.edu/philologic4/encyclopedie0521/query?report=concordance&method=proxy&attribution=&objecttype=&q=amour&start=0&end=0",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/search3t?dbname=encyclopedie0513&word=amour&CONJUNCT=PHRASE&dgdivhead=&dgdivocauthor=&ExcludeDiderot3=on&dgdivocsalutation=&OUTPUT=conc&POLESPAN=5",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://artflsrv02.uchicago.edu/cgi-bin/philologic/search3t?dbname=encyclopedie0513&dgdivhead=EAU",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
1039
ARTstor.js
1039
ARTstor.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
337
ASTIS.js
337
ASTIS.js
|
|
@ -1,337 +0,0 @@
|
|||
{
|
||||
"translatorID": "d4e227c0-cebb-425a-ac8d-a6625c4bfdd2",
|
||||
"label": "ASTIS",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?aina\\.ucalgary\\.ca/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-04 19:44:55"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.querySelector('a[href*="doi."]')) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('a[href*="?RECORD"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, _url) {
|
||||
let DOI = ZU.cleanDOI(attr(doc, 'a[href*="doi."]', 'href'));
|
||||
|
||||
let search = Zotero.loadTranslator('search');
|
||||
|
||||
search.setHandler('translators', function (_, translators) {
|
||||
search.setTranslator(translators);
|
||||
search.setHandler('itemDone', function (_, item) {
|
||||
item.complete();
|
||||
});
|
||||
search.translate();
|
||||
});
|
||||
|
||||
search.setSearch({ DOI });
|
||||
search.getTranslators();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aina.ucalgary.ca/scripts/mwimain.dll/415/4/1?RECLIST&DATABASE=ASTIS&TM=1628105772.604",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.aina.ucalgary.ca/scripts/mwimain.dll/415/4/4/85845?RECORD&DATABASE=ASTIS",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Parasitoids indicate major climate‐induced shifts in arctic communities",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Tuomas",
|
||||
"lastName": "Kankaanpää"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Eero",
|
||||
"lastName": "Vesterinen"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Bess",
|
||||
"lastName": "Hardwick"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Niels M.",
|
||||
"lastName": "Schmidt"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Tommi",
|
||||
"lastName": "Andersson"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Paul E.",
|
||||
"lastName": "Aspholm"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Isabel C.",
|
||||
"lastName": "Barrio"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Niklas",
|
||||
"lastName": "Beckers"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Joël",
|
||||
"lastName": "Bêty"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Tone",
|
||||
"lastName": "Birkemoe"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Melissa",
|
||||
"lastName": "DeSiervo"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Katherine H. I.",
|
||||
"lastName": "Drotos"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Dorothee",
|
||||
"lastName": "Ehrich"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Olivier",
|
||||
"lastName": "Gilg"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Vladimir",
|
||||
"lastName": "Gilg"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Nils",
|
||||
"lastName": "Hein"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Toke T.",
|
||||
"lastName": "Høye"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Kristian M.",
|
||||
"lastName": "Jakobsen"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Camille",
|
||||
"lastName": "Jodouin"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Jesse",
|
||||
"lastName": "Jorna"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Mikhail V.",
|
||||
"lastName": "Kozlov"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Jean‐Claude",
|
||||
"lastName": "Kresse"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Don‐Jean",
|
||||
"lastName": "Leandri‐Breton"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Nicolas",
|
||||
"lastName": "Lecomte"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Maarten",
|
||||
"lastName": "Loonen"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Philipp",
|
||||
"lastName": "Marr"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Spencer K.",
|
||||
"lastName": "Monckton"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Maia",
|
||||
"lastName": "Olsen"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Josée‐Anne",
|
||||
"lastName": "Otis"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Michelle",
|
||||
"lastName": "Pyle"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Ruben E.",
|
||||
"lastName": "Roos"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Katrine",
|
||||
"lastName": "Raundrup"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Daria",
|
||||
"lastName": "Rozhkova"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Brigitte",
|
||||
"lastName": "Sabard"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Aleksandr",
|
||||
"lastName": "Sokolov"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Natalia",
|
||||
"lastName": "Sokolova"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Anna M.",
|
||||
"lastName": "Solecki"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Christine",
|
||||
"lastName": "Urbanowicz"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Catherine",
|
||||
"lastName": "Villeneuve"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Evgenya",
|
||||
"lastName": "Vyguzova"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Vitali",
|
||||
"lastName": "Zverev"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Tomas",
|
||||
"lastName": "Roslin"
|
||||
}
|
||||
],
|
||||
"date": "11/2020",
|
||||
"DOI": "10.1111/gcb.15297",
|
||||
"ISSN": "1354-1013, 1365-2486",
|
||||
"issue": "11",
|
||||
"journalAbbreviation": "Glob Change Biol",
|
||||
"language": "en",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "6276-6295",
|
||||
"publicationTitle": "Global Change Biology",
|
||||
"url": "https://onlinelibrary.wiley.com/doi/10.1111/gcb.15297",
|
||||
"volume": "26",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,384 +0,0 @@
|
|||
{
|
||||
"translatorID": "d120a8a7-9d45-446e-8c18-ad9ef0a6bf47",
|
||||
"label": "Access Engineering",
|
||||
"creator": "Vinoth K - highwirepress.com",
|
||||
"target": "^https?://www\\.accessengineeringlibrary\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-09-09 09:42:36"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Copyright © 2020-2021 Vinoth K - highwirepress.com
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
let title = attr(doc, 'meta[name="citation_title"]', 'content');
|
||||
if (title) {
|
||||
if (doc.querySelector('meta[name="citation_isbn"]')) {
|
||||
let bookTitle = attr(doc, 'meta[name="citation_book_title"]', 'content');
|
||||
if (!bookTitle || title == bookTitle) {
|
||||
return "book";
|
||||
}
|
||||
else {
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
else if (url.includes('content/video/')) {
|
||||
return 'videoRecording';
|
||||
}
|
||||
else {
|
||||
return "journalArticle";
|
||||
}
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.results-item a[href]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
// Missing editions for books and books chapter page
|
||||
// Removed html element in abstract for video and tutorial page
|
||||
// Author not updating in metatag correctly from data and read
|
||||
// client advised to split and handled through custom data attr/obj
|
||||
// - so we'll fill those in manually.
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
// Edition
|
||||
let edition = ZU.xpathText(doc, '//meta[@name="citation_edition"]/@content');
|
||||
if (edition) item.edition = edition;
|
||||
|
||||
// Author
|
||||
// Some of old pages not having firstname, lastname seperation in markup and ignore if not
|
||||
let author = doc.querySelectorAll("ul.contributor-list > [data-firstnames]");
|
||||
item.creators = [];
|
||||
for (let i = 0; i < author.length; i++) {
|
||||
let creatorData = author[i].dataset;
|
||||
item.creators.push({
|
||||
firstName: creatorData.firstnames,
|
||||
lastName: creatorData.surname,
|
||||
creatorType: creatorData.authortype
|
||||
});
|
||||
}
|
||||
|
||||
// Abstract
|
||||
let abstractNote = ZU.xpathText(doc, '//meta[@name="citation_abstract"]/@content');
|
||||
if (abstractNote) item.abstractNote = ZU.cleanTags(abstractNote);
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
// Detect web not get trigger for scape EM translator
|
||||
// - so wll fill those in manually.
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Handbook of Environmental Engineering",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Rao Y.",
|
||||
"lastName": "Surampalli",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Tian C.",
|
||||
"lastName": "Zhang",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Satinder Kaur",
|
||||
"lastName": "Brar",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Krishnamoorthy",
|
||||
"lastName": "Hegde",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Rama",
|
||||
"lastName": "Pulicharla",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Mausam",
|
||||
"lastName": "Verma",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2018",
|
||||
"ISBN": "9781259860225",
|
||||
"abstractNote": "A complete guide to environmental regulations and remediation.This practical resource offers thorough coverage of current environmental issues and policies along with step-by-step remediation procedures. With contributions from dozens of industry-recognized experts, Handbook of Environmental Engineering features information on all segments of the market—including water and air quality and hazardous waste—and enables you to ensure compliance with all applicable regulations. You will get details about sensors, monitoring, and toxicity treatment and controls as well as waste management and safe disposal. Real-world examples demonstrate how to apply techniques and achieve compliance, while environmental impact assessments and measurement data enhance the book9s utility.Coverage includes:• Environmental legislation• Environmental impact assessments• Air pollution control and management• Potable water treatment• Wastewater treatment and reuse• Solid waste management• Hazardous waste management• Emerging wastes in the environment• Environmental monitoring and measurements",
|
||||
"edition": "1st Edition",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"publisher": "McGraw-Hill Education",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225/toc-chapter/chapter3/section/section1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "CHAPTER PRELIMINARIES",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ashok",
|
||||
"lastName": "Kumar",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Hamid",
|
||||
"lastName": "Omidvarborna",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Rao Y.",
|
||||
"lastName": "Surampalli",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Tian C.",
|
||||
"lastName": "Zhang",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Satinder Kaur",
|
||||
"lastName": "Brar",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Krishnamoorthy",
|
||||
"lastName": "Hegde",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Rama",
|
||||
"lastName": "Pulicharla",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Mausam",
|
||||
"lastName": "Verma",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2018",
|
||||
"ISBN": "9781259860225",
|
||||
"abstractNote": "A complete guide to environmental regulations and remediation.This practical resource offers thorough coverage of current environmental issues and policies along with step-by-step remediation procedures. With contributions from dozens of industry-recognized experts, Handbook of Environmental Engineering features information on all segments of the market—including water and air quality and hazardous waste—and enables you to ensure compliance with all applicable regulations. You will get details about sensors, monitoring, and toxicity treatment and controls as well as waste management and safe disposal. Real-world examples demonstrate how to apply techniques and achieve compliance, while environmental impact assessments and measurement data enhance the book's utility.Coverage includes:• Environmental legislation• Environmental impact assessments• Air pollution control and management• Potable water treatment• Wastewater treatment and reuse• Solid waste management• Hazardous waste management• Emerging wastes in the environment• Environmental monitoring and measurements",
|
||||
"bookTitle": "Handbook of Environmental Engineering",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"publisher": "McGraw-Hill Education",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225/toc-chapter/chapter3/section/section1",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/video/V4005352521001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "123D Design: Cut Text Through a Plane",
|
||||
"creators": [],
|
||||
"date": "2014",
|
||||
"abstractNote": "This video shows how to cut text through a plane with Combine/Subtract.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"shortTitle": "123D Design",
|
||||
"studio": "McGraw-Hill Education",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/video/V4005352521001",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/calculator/S0071_Basic_Transformer_Calculations",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Basic Transformer Calculations",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Bhagyalakshmi",
|
||||
"lastName": "Kerekare",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022/06/25/",
|
||||
"abstractNote": "This Excel workbook contains four worksheets. The first worksheet covers the basic concepts of single phase transformer such as turns ratio, primary current, secondary current, primary voltage, secondary voltage, and transformer ratio calculations. The second worksheet covers the basic concepts of power, efficiency, primary/secondary EMF and transformer rating calculations. The third worksheet covers the basic concepts of three phase transformers, highlighting the star and delta connections. Calculations are done for phase voltage, phase current, line voltage, and line current for star and delta connections. The fourth worksheet covers the basic concepts kVA Ratings, 3-phase primary, and secondary full load current 3-phase voltage calculations.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/calculator/S0071_Basic_Transformer_Calculations",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/case-study/CS0004_Atrial_Fibrillation",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Atrial Fibrillation: Improving Therapy via Engineering Advancements",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Michael J.",
|
||||
"lastName": "Rust",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-04-23",
|
||||
"abstractNote": "This case will explore atrial fibrillation from several perspectives, including the underlying physiology, clinical relevance, and instrumentation used for diagnosis and therapy. Students will identify and investigate unmet clinical needs that led to recent developments in technologies to treat atrial fibrillation.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"shortTitle": "Atrial Fibrillation",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/case-study/CS0004_Atrial_Fibrillation",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/tutorial/T0004_Partially_Full_Pipe_Flow_Calculations_Using_Excel_Spreadsheets",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Partially Full Pipe Flow Calculations Using Excel Spreadsheets",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Harlan H.",
|
||||
"lastName": "Bengtson",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2014/02/01/",
|
||||
"abstractNote": "This tutorial provides discussion of, and illustration by, examples for use of an Excel spreadsheet for making a variety of calculations for the flow of water in a partially full circular pipe using the Manning Equation. Equations for calculating area, wetted perimeter, and hydraulic radius for partially full pipe flow are included in this tutorial along with a brief review of the Manning Equation and discussion of its use to calculate a) the flow rate in a given pipe (given diameter, slope, & Manning roughness) at a specified depth of flow, b) the required diameter for a specified flow rate at a target percent full in a given pipe, and c) the normal depth (depth of flow) for a specified flow rate in a given pipe. This includes presentation and discussion of the equations for the calculations, example calculations, and screenshots of spreadsheets to facilitate the calculations.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessengineeringlibrary.com",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/tutorial/T0004_Partially_Full_Pipe_Flow_Calculations_Using_Excel_Spreadsheets",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/search?query=&f%5B0%5D=content_type%3ABooks&f%5B1%5D=book_component%3ATitles",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,391 +0,0 @@
|
|||
{
|
||||
"translatorID": "558330ca-3531-467a-8003-86cd9602cc48",
|
||||
"label": "Access Science",
|
||||
"creator": "Vinoth K - highwirepress.com",
|
||||
"target": "^https?://www\\.accessscience\\.com/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-10-17 20:19:39"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Vinoth K - highwirepress.com
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
let title = attr(doc, 'meta[name="citation_title"]', 'content');
|
||||
if (title) {
|
||||
if (doc.querySelector('meta[name="citation_isbn"]')) {
|
||||
let bookTitle = attr(doc, 'meta[name="citation_book_title"]', 'content');
|
||||
if (!bookTitle || title == bookTitle) {
|
||||
return "book";
|
||||
}
|
||||
else {
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
else if (url.includes('content/video/') || url.includes('content/video-biography')) {
|
||||
return 'videoRecording';
|
||||
}
|
||||
else if (url.includes('content/article/')) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (url.includes('news') || url.includes('briefing')) {
|
||||
return "magazineArticle";
|
||||
}
|
||||
else {
|
||||
return "webpage";
|
||||
}
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.search-middle-right a[href]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
// Author
|
||||
// Some of video pages having old content which does not contain the
|
||||
// firstname and lastname. which is binding in a single string in
|
||||
// metadata tags, So those cases we were split and mapped accordingly
|
||||
if (item.itemType == 'videoRecording') {
|
||||
let authorName = attr(doc, 'meta[name="citation_author"]', 'content');
|
||||
if (authorName) {
|
||||
item.creators = [];
|
||||
if (authorName.includes(',') && authorName.split(',').length > 2) {
|
||||
authorName = authorName.split(',')[0];
|
||||
item.creators.push(ZU.cleanAuthor(authorName, "author", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let abstractNote = attr(doc, 'meta[name="citation_abstract"]', 'content');
|
||||
item.abstractNote = abstractNote && ZU.cleanTags(abstractNote);
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/book/9781260452297",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Casarett & Doull's Essentials of Toxicology",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Curtis D.",
|
||||
"lastName": "Klaassen",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "John B. Watkins",
|
||||
"lastName": "Iii",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2022",
|
||||
"ISBN": "9781260452297",
|
||||
"abstractNote": "Doody9s Core Titles for 2021!\n\nFor more than 25 years, Casarett & Doull9s Toxicology: The Basic Science of Poisons has set the standard for providing thorough, academic, and authoritative information in clear and engaging ways. Distilling the major principles and concepts from that renowned text, Casarett & Doull9s Essentials of Toxicology delivers an accessible and highly readable introduction to the science and clinical field of medical toxicology. The book reflects the expertise of more than 60 renowned contributors.\n\nPresented in full-color, this new edition builds on the wide success of previous editions, with extensive updates that make the book more clinically relevant to students and beginners in toxicology, pharmacology, pharmacy, and environmental sciences. Chapter-ending self-assessment Q&As and other features make the learning process more effective and efficient.\n\nCasarett and Doull9s Essentials of Toxicology is organized into seven units:\n\n• General Principles of Toxicology\n\n• Disposition of Toxicants\n\n• Nonorgan-directed Toxicity\n\n• Target Organ Toxicity\n\n• Toxic Agents\n\n• Environmental Toxicology\n\n• Applications of Toxicology\n\nSuccinct, yet comprehensive, the text covers essential principles, toxicokinetics, how toxic effects are passed on to succeeding generations, how each body system responds to poisons, and the specific effects of a wide range of toxic agents—from pesticides to radiation.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"publisher": "McGraw Hill",
|
||||
"url": "https://www.accessscience.com/content/book/9781260452297",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/book/9781260452297/chapter/chapter2",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Principles of Toxicology",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Lauren M.",
|
||||
"lastName": "Aleksunes",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "David L.",
|
||||
"lastName": "Eaton",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Curtis D.",
|
||||
"lastName": "Klaassen",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "John B. Watkins",
|
||||
"lastName": "Iii",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2022",
|
||||
"ISBN": "9781260452297",
|
||||
"bookTitle": "Casarett & Doull's Essentials of Toxicology",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"publisher": "McGraw Hill",
|
||||
"url": "https://www.accessscience.com/content/book/9781260452297/chapter/chapter2",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/video/V2537194263001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "Supplementary Problem 10.12",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Rebecca B.",
|
||||
"lastName": "DeVasher",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2013",
|
||||
"abstractNote": "This video details a problem involving unit cells and the calculation of the mass of a cell, length of a cell and radius of an atom in the unit cell based on the density of a solid.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"studio": "McGraw Hill",
|
||||
"url": "https://www.accessscience.com/content/video/V2537194263001",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/video-biography/VB0014",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "Anderson, John R.",
|
||||
"creators": [],
|
||||
"date": "2011",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"studio": "McGraw Hill",
|
||||
"url": "https://www.accessscience.com/content/video-biography/VB0014",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/article/a694300?implicit-login=true",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "3D printing",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Wenchao",
|
||||
"lastName": "Zhou",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023",
|
||||
"DOI": "10.1036/1097-8542.694300",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"url": "https://www.accessscience.com/content/article/a694300",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/news/aSN2301171?implicit-login=true",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "These chemists cracked the code to long-lasting Roman concrete",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Carolyn",
|
||||
"lastName": "Gramling",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023",
|
||||
"extra": "DOI: 10.1036/1097-8542.SN0000000",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"url": "https://www.accessscience.com/content/news/aSN2301171",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/video/an600010",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "Henrietta Leavitt: The Woman Who Measured the Universe",
|
||||
"creators": [],
|
||||
"abstractNote": "Born in 1868, Henrietta Leavitt was an astronomer ahead of her time, whose work helped to revolutionize our understanding of the universe. While working at Harvard Observatory, Leavitt began to study stars of fluctuating brightness. This video describes her crucial observation about variable stars, which gave astronomers a new way to measure distances, ultimately leading to such impactful discoveries as the expansion of the universe.\n\nCredit: ESA Hubble Videos; Hubblecast 116: Henrietta Leavitt — ahead of her time; Directed by: Mathias Jäger; Visual design and editing: Martin Kornmesser; Written by: Sara Rigby; Narration: Sara Mendes da Costa; Images: ESA/Hubble and NASA, ESO, Hubble Heritage Team (STScI/AURA), Library of Congress Prints and Photographs Division Washington, Harvard College Observatory, Huntington Library, California Institute of Technology, Digitized Sky Survey 2, M. Kornmesser, R. Gendler, Arnold Reinhold, Davide De Martin; Videos: NASA, ESA, M. Kornmesser, Luis Calcada; Music: Johan B. Monell; Web and technical support: Mathias André and Raquel Yumi Shida; Executive producer: Lars Lindberg Christensen",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.accessscience.com",
|
||||
"shortTitle": "Henrietta Leavitt",
|
||||
"studio": "McGraw Hill",
|
||||
"url": "https://www.accessscience.com/content/video/an600010",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/content/biography/m0073908",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "Abbe, Cleveland (1838–1916)",
|
||||
"creators": [],
|
||||
"language": "en",
|
||||
"url": "https://www.accessscience.com/content/biography/m0073908",
|
||||
"websiteTitle": "McGraw Hill's AccessScience",
|
||||
"websiteType": "text",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessscience.com/search?query=&items_per_page=10",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,405 +0,0 @@
|
|||
{
|
||||
"translatorID": "0701696c-3523-47ba-9617-b04eee03b6ba",
|
||||
"label": "Adam Matthew Digital",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://www\\.([^.]+)\\.amdigital\\.co\\.uk/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-10-21 05:00:48"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/DocumentDetails.aspx') // older collections
|
||||
|| url.includes('/DocumentDetailsSearch.aspx')) {
|
||||
return 'manuscript';
|
||||
}
|
||||
if (url.includes('/Documents/Details/') // newer collections
|
||||
|| url.includes('/Documents/SearchDetails')) {
|
||||
return getTypeNew(doc);
|
||||
}
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
else if (doc.querySelector('.DocumentsList')) {
|
||||
Z.monitorDOMChanges(doc.querySelector('.DocumentsList'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTypeNew(doc) {
|
||||
let type = text(doc, 'tr[data-field-name="Document Type"] td[data-field-role="value"]');
|
||||
if (!type) {
|
||||
if (doc.body.classList.contains('cinema')) {
|
||||
return 'videoRecording';
|
||||
}
|
||||
else {
|
||||
return 'document';
|
||||
}
|
||||
}
|
||||
|
||||
type = ZU.trimInternal(type).toLowerCase();
|
||||
|
||||
if (type.includes('book')) {
|
||||
return 'book';
|
||||
}
|
||||
if (type.includes('manuscript')) {
|
||||
return 'manuscript';
|
||||
}
|
||||
if (type.includes('drawing') || type.includes('illustration')
|
||||
|| type.includes('photograph')) {
|
||||
return 'artwork';
|
||||
}
|
||||
if (type.includes('map')) {
|
||||
return 'map';
|
||||
}
|
||||
if (type.includes('correspondence')) {
|
||||
return 'letter';
|
||||
}
|
||||
return 'document';
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
const items = {};
|
||||
let found = false;
|
||||
const rows = doc.querySelectorAll(
|
||||
'.contentsList .tableRow .descriptionCell a, .SearchList tbody .title a, .DocumentsList tbody .title a');
|
||||
for (const row of rows) {
|
||||
const href = row.href;
|
||||
const title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
if (url.includes('/Documents/')) {
|
||||
// newer collections (served with HTTPS, no .aspx pages) have a
|
||||
// completely different, and much easier to parse, structure
|
||||
scrapeNew(doc, url);
|
||||
}
|
||||
else {
|
||||
scrapeOld(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrapeNew(doc, url) {
|
||||
function fromTable(fieldName) {
|
||||
return text(doc, `tr[data-field-name="${fieldName}"] td[data-field-role="value"]`);
|
||||
}
|
||||
|
||||
let item = new Zotero.Item(getTypeNew(doc));
|
||||
|
||||
item.title = fromTable('Title');
|
||||
item.abstractNote = fromTable('Abstract') || fromTable('Additional Information');
|
||||
item.date = ZU.strToISO(fromTable('Date'));
|
||||
item.place = fromTable('Places');
|
||||
item.rights = fromTable('Copyright');
|
||||
item.publisher = fromTable('Publisher');
|
||||
item.language = fromTable('Language');
|
||||
|
||||
item.creators = fromTable('Names')
|
||||
.split('; ')
|
||||
.map(name => ZU.cleanAuthor(name, 'author', true));
|
||||
|
||||
let director = fromTable('Director');
|
||||
if (director) {
|
||||
item.creators.push(ZU.cleanAuthor(director, 'director', true));
|
||||
}
|
||||
|
||||
let pageSelect = doc.querySelector('#DownloadPageFrom');
|
||||
if (pageSelect) {
|
||||
item.numPages = pageSelect.childElementCount;
|
||||
}
|
||||
item.archive = fromTable('Library/Archive') || fromTable('Collection');
|
||||
item.archiveLocation = fromTable('Reference');
|
||||
item.libraryCatalog = extractCatalogName(doc.title);
|
||||
item.url = url.replace('/SearchDetails/', '/Details/')
|
||||
.replace('?SessionExpired=True', '');
|
||||
|
||||
if (item.itemType != 'videoRecording') {
|
||||
item.attachments.push({
|
||||
title: "Full Text PDF",
|
||||
mimeType: 'application/pdf',
|
||||
url: attr(doc, 'a[href*="/FullDownload"]', 'href')
|
||||
});
|
||||
}
|
||||
|
||||
item.tags = [...doc.querySelectorAll('tr[data-field-name="Subjects"] td[data-field-role="value"] a')]
|
||||
.map(el => ({ tag: el.textContent }));
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
function scrapeOld(doc, url) {
|
||||
function fromTable(selector) {
|
||||
return text(doc, selector + ' > .detCol2') || text(doc, selector);
|
||||
}
|
||||
|
||||
let item = new Zotero.Item('manuscript');
|
||||
|
||||
item.title = fromTable('#Body_DocumentDetailsMeta_descSpan')
|
||||
|| fromTable('#Body_descriptionElement');
|
||||
let abstract = doc.querySelector('#Body_DocumentDetailsMeta_notesElement>.detCol2, #Body_notesElement>.detCol2');
|
||||
item.abstractNote = abstract ? abstract.innerText : "";
|
||||
item.date = ZU.strToISO(fromTable('#Body_DocumentDetailsMeta_dateElement'));
|
||||
|
||||
let pageSelect = doc.querySelector('.pageRangeSelect'); // either will do
|
||||
if (pageSelect) {
|
||||
item.numPages = pageSelect.childElementCount;
|
||||
}
|
||||
item.archive = fromTable('#Body_DocumentDetailsMeta_sourceElement');
|
||||
|
||||
let box = fromTable('#Body_DocumentDetailsMeta_boxElement')
|
||||
|| fromTable('#Body_boxElement');
|
||||
let folder = fromTable('#Body_DocumentDetailsMeta_folderElement')
|
||||
|| fromTable('#Body_folderElement');
|
||||
item.archiveLocation = `Box ${box}, folder ${folder}`;
|
||||
item.libraryCatalog = extractCatalogName(doc.title);
|
||||
item.attachments.push({
|
||||
title: "Full Text PDF",
|
||||
mimeType: 'application/pdf',
|
||||
url: attr(doc, '.downloadPDFLink > a', 'href')
|
||||
});
|
||||
// we want a URL without any search strings, navigation data, etc
|
||||
item.url = url.replace(/\?.*(documentid=[^&]+).*/, '?$1');
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the site's name by taking everything after the first segment of the title:
|
||||
* "Search Results - Jewish Life in America - Adam Matthew Digital"
|
||||
* becomes "Jewish Life in America - Adam Matthew Digital"
|
||||
*/
|
||||
function extractCatalogName(title) {
|
||||
return title.substring(title.indexOf('-') + 2);
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.jewishlife.amdigital.co.uk/Contents/DocumentDetailsSearch.aspx?documentid=289906&prevPos=289906&vpath=SearchResults&searchmode=true&pi=1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "manuscript",
|
||||
"title": "Manuscript notebook of poems",
|
||||
"creators": [],
|
||||
"abstractNote": "Page\n\n1 'The New Colossus'\n\n2 'Progress and Poverty'\n\n3 'Venus of the Louvre'\n\n4 'Destiny I'\n\n5 'Destiny II'\n\n6 'Influence'\n\n7 'Success'\n\n8-11 'Chopin I, II, III, IV'\n\n12 'With a Copy of Don Quixote'\n\n13 'To F.P.'\n\n14 'One Augur to Another'\n\n15 'Cranes of Ibicus'\n\n16 'Reconciliation'\n\n17 'Incident at Sea' 18 'Will O' the Wisp'\n\n19 'Assurance'\n\n20 'Echoes'\n\n21 'St. Michael's Chapel'\n\n22-23 'Under the Sea. I, II'\n\n24 'Taming of the Falcon'\n\n25 'Supreme Sacrifice'\n\n26 'Life and Art'\n\n27 'Sympathy'\n\n28 'Dreaming Castle'\n\n29 'To R.W.E.'\n\n30-37 'Symphonic Studies (after Robert Schumann). Prelude, I, II, III, IV, V, VI Epilogue'\n\n38 'City Visions'\n\n40 'Long Island Sound'\n\n41-49 Translated Sonnets:\n\nPage 41 'Art the Redeemer'\n\nPage 42 'From the French of Fran<61>ois Copp<70>'\n\nPages 44-49 'Six Sonnets from the Studies of Petrarch, a. 'In Vita LXVII', b. 'In Vita LXXVI', c. 'In Morte XLIII', d. 'In Morte II. On the Death of Cardinal Colonna and Laura', e. 'In Vita CIX', f. 'In Vita, CV'\n\n50 '1492'\n\n51 'Restlessness'\n\n52 'Child at the Bath. R. de K. G.'\n\n54 'Autumn Sadness'\n\n56 'Song. Venus'\n\n57 'From the Arabian Nights'\n\n58 'Reed Song'\n\n59 'Moonlight, from German of Eichendorff'\n\n60 'Songs from Eichendroff'\n\n61 'Lida and the Swan. Faust. Part II. Act II. Scene 2'\n\n62-72 'Phaon'\n\n73 'To the Moon after Sunrise'\n\n75-79 'Fragments from Petrarch'\n\nPage 75 'Canzone XII. 5'\n\nPage 76 'Trionfo Della Morte'\n\nPage 77 'Trionfo D'Amore'\n\nPage 78 'Triumph of Death'\n\n80 'Sunrise'\n\n85 'To Nelly [?] Sleeping'\n\n89-97 'The Creation of Man. Miwk [Mohawk] Fable'\n\n98-105 'The New Cupid. From the German of Goethe'\n\n106-111 'August Moon'\n\n112-115 'My Goddess. From the German of Goethe'\n\n116-119 'The Old Year-1883. Affectionately dedicated to W.S.P. & W.A.P.'\n\n120 'Ariel and Euphorion' [clippings pasted into notebook, unknown journal]\n\n122 'Don Rafael' [clippings pasted into notebook, unknown journal]\n\n122 'Two Sonnets' [clippings pasted into notebook, unknown journal]: 'Sonnet I. Petrarch: To a Friend', 'Sonnet II. Art, the Redeemer'\n\n123 'The New Ezekiel' [clippings pasted into notebook, unknown journal]\n\n123 'The Choice' [clippings pasted into notebook, for The American Hebrew]\n\n123 'The Supreme Sacrifice' [clippings pasted into notebook, for The American Hebrew]\n\n123 'Zulieka. Translated from Goethe's 'West Gestliche Divan' [clippings pasted into notebook, unknown journal, most possibly in Jewish Messenger]\n\n124 'The World's Justice' [clippings pasted into notebook, unknown journal]\n\n124 'The Feast of Lights' [clippings pasted into notebook, for The American Hebrew]\n\n126-130 'Grotesque'\n\n131-136 'Translations from Copp<70>'\n\n137-149 ['By the Waters of Babylon'] 'Little Poems in Prose:\n\nPage 137 'I. The Exodus'\n\nPage 140 'II. Treasures'\n\nPage 141 'III. The Sower'\n\nPage 143 'IV. The Test'\n\nPage 144 'V. The Prophet'\n\nPage 146-147 Pages are blank in the original\n\nPage 148 'VI. Currents'\n\nPage 149 'VII. Chrysalis'\n\n150 'Gifts'\n\n152 'A Masque of Venice'\n\n156 'To Carmen Sylva'\n\n[Page 156 is followed by 159, with no gaps in poetry]\n\n161-163 'In a Gothic Church' (never completed).",
|
||||
"archive": "American Jewish Historical Society",
|
||||
"archiveLocation": "Box 1, folder 2",
|
||||
"libraryCatalog": "Jewish Life in America - Adam Matthew Digital",
|
||||
"numPages": 165,
|
||||
"url": "http://www.jewishlife.amdigital.co.uk/Contents/DocumentDetailsSearch.aspx?documentid=289906",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.jewishlife.amdigital.co.uk/Contents/DocumentDetails.aspx?documentid=288444&prevPos=288444&filter=0%7c1%7c2&vpath=contents&pi=1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "manuscript",
|
||||
"title": "Baron de Hirsch Fund colonies and schools",
|
||||
"creators": [],
|
||||
"abstractNote": "See also P19/OS1/2",
|
||||
"archiveLocation": "Box 3, folder 2",
|
||||
"libraryCatalog": "Jewish Life in America - Adam Matthew Digital",
|
||||
"numPages": 38,
|
||||
"url": "http://www.jewishlife.amdigital.co.uk/Contents/DocumentDetails.aspx?documentid=288444",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.jewishlife.amdigital.co.uk/Contents/Default.aspx?filter=1%7c0",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.gender.amdigital.co.uk/Documents/Details/Etiquette%20for%20Ladies%20and%20Gentlemen%20London%201876?SessionExpired=True",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Etiquette for Ladies and Gentlemen",
|
||||
"creators": [],
|
||||
"date": "1876",
|
||||
"archive": "Bodleian Library, University of Oxford",
|
||||
"archiveLocation": "268 c.457",
|
||||
"libraryCatalog": "Defining Gender - Adam Matthew Digital",
|
||||
"numPages": 65,
|
||||
"publisher": "Frederick Warne and Co.",
|
||||
"url": "https://www.gender.amdigital.co.uk/Documents/Details/Etiquette%20for%20Ladies%20and%20Gentlemen%20London%201876",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.americanwest.amdigital.co.uk/Documents/Details/Graff_2445",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "document",
|
||||
"title": "$150 reward. Whereas a robbery was committed in the vicinity of the town of Fort Madison, on the 22d Inst….",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jacob",
|
||||
"lastName": "Guy",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Jacob",
|
||||
"lastName": "Bowers",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "W. Braxton",
|
||||
"lastName": "Gillock",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1840",
|
||||
"archive": "Everett D. Graff Collection of Western Americana",
|
||||
"archiveLocation": "Graff 2445",
|
||||
"libraryCatalog": "American West - Adam Matthew Digital",
|
||||
"url": "https://www.americanwest.amdigital.co.uk/Documents/Details/Graff_2445",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.socialismonfilm.amdigital.co.uk/Documents/Details/BFI_ETV_Advance_Democracy_25SD_Prores-4?SessionExpired=True#MediaSummary",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "Advance Democracy",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ralph",
|
||||
"lastName": "Bond",
|
||||
"creatorType": "director"
|
||||
}
|
||||
],
|
||||
"abstractNote": "Starts with a discussion of inequality in London contrasting the rich with the lives of the poor. Features the hard lives of dock workers and a semi-dramatization of them complaining about taxes and their uses to fight wars. A wife talks to her husband about the merits of the Co-operative, and the husband later listens to a speech about democracy and the co-operative movement which mentions the sacrifices of the Tolpuddle Martyrs, the Chartists and the Rochdale Equitable Pioneers. Warns of the dangers of Nazis (with archive footage of Hitler and war). The protagonist of the film is won over and mobilises his colleagues to march on May Day. Features a medley of labour movement songs.",
|
||||
"language": "English (Dialogue)",
|
||||
"libraryCatalog": "Socialism on Film: The Cold War and International Propaganda - Adam Matthew Digital",
|
||||
"place": "United Kingdom London",
|
||||
"rights": "The British Film Institute",
|
||||
"url": "https://www.socialismonfilm.amdigital.co.uk/Documents/Details/BFI_ETV_Advance_Democracy_25SD_Prores-4#MediaSummary",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Co-operatives"
|
||||
},
|
||||
{
|
||||
"tag": "Family"
|
||||
},
|
||||
{
|
||||
"tag": "Industry"
|
||||
},
|
||||
{
|
||||
"tag": "Music"
|
||||
},
|
||||
{
|
||||
"tag": "Politics"
|
||||
},
|
||||
{
|
||||
"tag": "Ships and shipping"
|
||||
},
|
||||
{
|
||||
"tag": "Shopping"
|
||||
},
|
||||
{
|
||||
"tag": "Social class"
|
||||
},
|
||||
{
|
||||
"tag": "Trade unions"
|
||||
},
|
||||
{
|
||||
"tag": "Women"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
309
Ahval News.js
309
Ahval News.js
|
|
@ -1,309 +0,0 @@
|
|||
{
|
||||
"translatorID": "64f4a2b8-33d8-4303-834a-3b71065cf6c6",
|
||||
"label": "Ahval News",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://ahvalnews\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-12 20:49:38"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (getJSONLD(doc)) {
|
||||
return "newspaperArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h2.field-title > a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, _url) {
|
||||
let item = new Zotero.Item('newspaperArticle');
|
||||
let json = getJSONLD(doc);
|
||||
|
||||
item.title = json.headline;
|
||||
item.abstractNote = json.description;
|
||||
item.publicationTitle = 'Ahval';
|
||||
item.date = ZU.strToISO(json.dateModified || json.datePublished);
|
||||
item.section = json.articleSection;
|
||||
item.language = doc.documentElement.lang;
|
||||
item.url = json.url;
|
||||
|
||||
if (json.author && json.author.name != 'Ahval') {
|
||||
// usually no authors, sometimes one
|
||||
item.creators.push(ZU.cleanAuthor(json.author.name, 'author'));
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
function getJSONLD(doc) {
|
||||
let jsonLDText = text(doc, 'script[type="application/ld+json"]');
|
||||
if (!jsonLDText.trim()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let json = JSON.parse(jsonLDText);
|
||||
if (!json['@graph']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (let graphObj of json['@graph']) {
|
||||
if (graphObj['@type'] == 'NewsArticle') {
|
||||
return graphObj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/turkish-lira/turkey-signs-2-billion-currency-swap-deal-south-korea",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Turkey signs $2 billion currency swap deal with South Korea",
|
||||
"creators": [],
|
||||
"date": "2021-08-12",
|
||||
"abstractNote": "Turkey’s central bank and the Bank of Korea signed a currency swap agreement in lira and won worth as much as $2 billion.\r\n\r\nThe deal, effective for three years from Thursday, is designed to promote bilateral trade and financial cooperation for the economic development of both countries, the Bank of Korea said in a statement on its website.\r\n\r\nTurkey has sought to obtain currency swaps with central banks around the world to help bolster its foreign exchange reserves, which have fallen into negative territory when accounting for liabilities. The agreements, which have included arrangements worth about $10 billion with Turkey’s regional ally Qatar, have failed to halt a slide in the lira’s value to successive record lows since a 2018 currency crisis.\r\n\r\nIt is interesting that “another G20 central bank seems willing to support and prolong the continuation of really questionable monetary policy settings in Turkey”, said Tim Ash, a senior emerging markets strategist at BlueBay Asset Management in London. The deal \"does not really touch the sides\" in terms of defending the lira, he said.\r\n\r\nTurkey’s central bank kept interest rates at below inflation for much of last year to help the government engineer a borrowing boom. That led to an exodus of capital from the lira as deposit holders saw returns from their investments, net of inflation, disappear.\r\n\r\nThe lira rose 0.3 percent to 8.6 per dollar after the swap deal was announced after trading up 0.1 percent earlier in the day.\r\n\r\nThe agreement with the Bank of Korea was announced hours before the Turkish central bank was due to publish a monthly decision on interest rates. The benchmark rate in Turkey stands at 19 percent, marginally above annual consumer price inflation of 18.95 percent.\r\n\r\nPresident Recep Tayyip Erdoğan is calling for rate cuts and has sacked three central bank governors in just over two years due to disagreements over monetary policy. Erdoğan holds the unorthodox view that higher interest rates are inflationary. The latest governor, appointed in March, has kept rates unchanged even as inflation accelerated from 15.6 percent in February.\r\n\r\nSouth Korean companies make substantial investments in Turkey’s economy, particularly in the construction, energy and technology industries. The investments have included a 2017 contract for the building of the world’s longest suspension bridge over the Dardanelles straits worth around $2.7 billion.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "News",
|
||||
"url": "https://ahvalnews.com/turkish-lira/turkey-signs-2-billion-currency-swap-deal-south-korea",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/northern-cyprus-turkey/former-turkish-cypriot-leader-akincis-adviser-banned-entering-turkey",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Former Turkish Cypriot leader Akıncı’s adviser banned from entering Turkey",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Tümay",
|
||||
"lastName": "Tuğyan",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-07-13",
|
||||
"abstractNote": "Ali Bizden, the press and communications coordinator of former Turkish Cypriot leader Mustafa Akıncı, was banned from entering Turkey for five years on charges of acting against the country’s national security.\r\n\r\nBizden was informed of the ban by immigration police in Turkey on Tuesday night after he sought to pass through passport control at Istanbul’s Sabiha Gökçen Airport. The ban had been ordered back in September last year, he said via social media on Wednesday.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "News",
|
||||
"url": "https://ahvalnews.com/northern-cyprus-turkey/former-turkish-cypriot-leader-akincis-adviser-banned-entering-turkey",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/turkish-lira/turkey-signs-2-billion-currency-swap-deal-south-korea",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Turkey signs $2 billion currency swap deal with South Korea",
|
||||
"creators": [],
|
||||
"date": "2021-08-12",
|
||||
"abstractNote": "Turkey’s central bank and the Bank of Korea signed a currency swap agreement in lira and won worth as much as $2 billion.\r\n\r\nThe deal, effective for three years from Thursday, is designed to promote bilateral trade and financial cooperation for the economic development of both countries, the Bank of Korea said in a statement on its website.\r\n\r\nTurkey has sought to obtain currency swaps with central banks around the world to help bolster its foreign exchange reserves, which have fallen into negative territory when accounting for liabilities. The agreements, which have included arrangements worth about $10 billion with Turkey’s regional ally Qatar, have failed to halt a slide in the lira’s value to successive record lows since a 2018 currency crisis.\r\n\r\nIt is interesting that “another G20 central bank seems willing to support and prolong the continuation of really questionable monetary policy settings in Turkey”, said Tim Ash, a senior emerging markets strategist at BlueBay Asset Management in London. The deal \"does not really touch the sides\" in terms of defending the lira, he said.\r\n\r\nTurkey’s central bank kept interest rates at below inflation for much of last year to help the government engineer a borrowing boom. That led to an exodus of capital from the lira as deposit holders saw returns from their investments, net of inflation, disappear.\r\n\r\nThe lira rose 0.3 percent to 8.6 per dollar after the swap deal was announced after trading up 0.1 percent earlier in the day.\r\n\r\nThe agreement with the Bank of Korea was announced hours before the Turkish central bank was due to publish a monthly decision on interest rates. The benchmark rate in Turkey stands at 19 percent, marginally above annual consumer price inflation of 18.95 percent.\r\n\r\nPresident Recep Tayyip Erdoğan is calling for rate cuts and has sacked three central bank governors in just over two years due to disagreements over monetary policy. Erdoğan holds the unorthodox view that higher interest rates are inflationary. The latest governor, appointed in March, has kept rates unchanged even as inflation accelerated from 15.6 percent in February.\r\n\r\nSouth Korean companies make substantial investments in Turkey’s economy, particularly in the construction, energy and technology industries. The investments have included a 2017 contract for the building of the world’s longest suspension bridge over the Dardanelles straits worth around $2.7 billion.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "News",
|
||||
"url": "https://ahvalnews.com/turkish-lira/turkey-signs-2-billion-currency-swap-deal-south-korea",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/tr/din/secme-sacmalar-hukuk-islam-allah-kelami-vs",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Seçme saçmalar: Hukuk, İslam, Allah kelamı vs.",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sevan",
|
||||
"lastName": "Nişanyan",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-08-11",
|
||||
"abstractNote": "“Laik toplumlarda kanunlar kutsal değildir. Zaman içinde insanların gelişen ihtiyaçlarına göre hukukta iyileştirme yapılabilir. Laik toplumlarda insanlar kendi yasalarını yapar, tanrı onların dünyada yaptıklarına karışmaz.”\r\n\r\nKanunları alelumum ‘insanlar’ yapmaz. ‘Birileri’ yapar. \r\n\r\n“Kanunlar zaman ve zemine göre değiştirilebilir” dediğiniz zaman kimin ne zaman ve hangi koşullarda değiştirebileceğini de belirtmeniz gerekir. \r\n\r\nYoksa birileri çıkar “arkadaşlar yarın beni padişah ilan edeceğiz” der, yahut gece yarısı torba yasa çıkarır, gık diyemezsin.\r\n\r\nKarşı taraf haklı mıdır, haksız mıdır ayrı mevzu. Ama laiklik hayranlarının yüz senedir halâ karşı tarafın gerekçesini fark etmemiş görünmeleri hayreti muciptir. \r\n\r\nKarşı taraf diyor ki, kanunlar kutsaldır. Yani kafana esti diye zırt pırt değiştiremezsin. O yetkiyi sana verirsek sonucu kaçınılmaz bir kesinlikle zorbalıktır, hukukun paçavra edilmesidir. Hukuku zamana uydurmak gerekiyor ise nasıl uydurulacağına devlet sopasını elinde tutanlar değil, ak sakallı alimler karar versin.\r\n\r\nAyrıca, müsterih olun, tanrı bir şeye karışmaz. \r\n\r\nÇünkü tanrı hayaldir. \r\n\r\nSadece yasa yapmanın farklı yöntemleri vardır.\r\n\r\n“Roma imparatorluğunda kanunlarla toplumda kutsal olan ve olmayan net bir şekilde ayrılmıştır. Laiklik esas alınmıştır.”\r\n\r\nBiraz Roma tarihi bilen bilir ki Roma hukuku ve siyasi kurumları iliğine kadar dini inanç ve törelerle yoğrulmuştur; dinsizliğin, dine zarar vermenin cezası ölümdür. \r\n\r\nMerak ediyorsanız Mommsen yahut Fustel de Coulanges okuyun. \r\n\r\nEski Roma dini geniş meşrepli olduğundan insanları çok üzmemiştir. \r\n\r\nHıristiyanlık resmi din olduğunda ise muhtemelen insanlık tarihinin en feci yobazlık sahneleri yaşandı. Yanlış inanç sahipleri acımasızca kovuşturuldu, tapınakları yakıldı, dini zulümden kaçanlar yüzünden koca vilayetler ıssız kaldı.\r\n\r\nKutsal olanla dünyevinin ayrışması Batı Avrupa Ortaçağının eseridir. Roma devleti Batıda yıkılınca kilise uzun süre tek medeni otorite mercii olarak kaldı. Sonra devletler yeniden güçlenince gücünü onlarla paylaşmamak için çatır çatır direndi. \r\n\r\nSonunda otoriteyi paylaşmaktan ve birbirinin alanına fazla bulaşmamayı kabul etmekten başka çare bulamadılar.\r\n\r\nDoğu Roma’da devlet çökmediği için böyle bir şey olmadı. Ne Bizans’ta, ne Rusya’da, ne Osmanlı’da o yüzden din ve devletin ayrılması diye bir şey duyulmamıştır.\r\n\r\n“Kuranın tanrıdan geldiğine inanıldığından değiştirilemez özelliği vardır. Bu durumda Kurandaki toplum yönetim yasalarını, hukuku değiştirebilir misiniz? Değiştiremezsiniz.”\r\n\r\nKuran’da birtakım şiirsel imgeler, muğlak deklarasyonlar, ne manaya geldiği belirsiz meseller ve bolca öfke krizi vardır. Hemen her ayetin zıddını söyleyen bir ayet illa ki bulunur. \r\n\r\nBu tuhaf metinden (ve onu tamamlamak için uydurulan on binlerce hadisten) bir hukuk sistemi kendiliğinden üremedi. Üretmek için çağın en parlak alimleri canhıraş bir gayretle 200 sene uğraştılar. Ürettikleri sistemi yorumlamak için, eskisi kadar parlak olmayan varisleri bin küsur senedir hala uğraşıyor. Siz orada değiştirilmez bir tanrı yasası bulduğunuzu iddia ediyorsanız yolunuz açık olsun.\r\n\r\nİslam hukukunun iki ana yolu ve dört tali mezhebi (ve tabii bugün terk edilmiş olan onlarca alternatifi) Abbasi devletinin ilk yüzyıllarında oluşturuldu. \r\n\r\nYani Kuran’ın telifinden kaba hesap 100 ila 200 yıl sonra. \r\n\r\nAllah’ı referans göstermeleri politik bir tercihti. Aşırı güçlenen ve meşruiyet zemini sarsak olan halife devletine karşı hukuk mesleği sırtını “Allah kelamına” dayama ihtiyacını hissetti. Buyur askeriye senin, vergi senin, ama hukuk senin tasarrufunda değil, ilmiye sınıfının tekelidir, dediler. \r\n\r\nSenin kılıcın varsa bizim de Allahımız ve kitabımız var diye kendi kendilerini teselli ettiler.\r\n\r\nSon derece akıllıca bir hamleydi. Sonuçta ilim mesleğinin yüzyıllar içinde aşırı derecede muhafazakarlaşmasına, kılıç sahibinin tasallutuna karşı istiridye gibi içine kapanmasına yol açtı, o ayrı mevzu.\r\n\r\nBugün “İslam değişir mi? Değişmez!” diyerek kendi sorup kendi cevaplayanların bu hakikatleri aklında tutmasında yarar vardır. \r\n\r\nİslam hukuku konusunda ahkam kesmeyi toplumun en cahil ve ezik sınıflarına terk edip sonra onların kalın kafalılığından şikayet etmek pek de rasyonel bir tavır olmasa gerek.\r\n\r\n\r\n* Bu yazı, Sevan Nişanyan’ın blogundan alınmıştır.",
|
||||
"language": "tr",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "Yazarlar",
|
||||
"shortTitle": "Seçme saçmalar",
|
||||
"url": "https://ahvalnews.com/tr/din/secme-sacmalar-hukuk-islam-allah-kelami-vs",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/ar/70-mn-alatrak-ydwn-laghlaq-alhdwd-fy-wjh-allajyyn/alnsryt-altrkyt",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "70% من الأتراك يدعون لإغلاق الحدود في وجه اللاجئين",
|
||||
"creators": [],
|
||||
"date": "2021-08-12",
|
||||
"abstractNote": "اعتقلت السلطات التركية الخميس نحو ثمانين شخصا يشتبه بأنهم شجعوا أو شاركوا في الهجوم على محلات تجارية لسوريين في أنقرة على أثر مشاجرة سقط فيها قتيل في أجواء تصاعد خطاب كراهية الأجانب في تركيا.",
|
||||
"language": "ar",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "أخبار",
|
||||
"url": "https://ahvalnews.com/ar/70-mn-alatrak-ydwn-laghlaq-alhdwd-fy-wjh-allajyyn/alnsryt-altrkyt",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/ar/hl-ymkn-ltrkya-walhnd-ttqabla-wjhaan-lwjh-fy-afghanstan/alhnd",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "هل يمكن لتركيا والهند أن تتقابلا وجهاً لوجه في أفغانستان؟",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "نيكولاس",
|
||||
"lastName": "مورغان",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-08-10",
|
||||
"abstractNote": "لماذا ترحب #الهند بدور #تركيا في #أفغانستان بعد خروج الولايات المتحدة رغم خلافات البلدين العميقة؟",
|
||||
"language": "ar",
|
||||
"libraryCatalog": "Ahval News",
|
||||
"publicationTitle": "Ahval",
|
||||
"section": "رأي",
|
||||
"url": "https://ahvalnews.com/ar/hl-ymkn-ltrkya-walhnd-ttqabla-wjhaan-lwjh-fy-afghanstan/alhnd",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ahvalnews.com/special-feature",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "e317b4d4-03cf-4356-aa3c-defadc6fd10e",
|
||||
"label": "Air University Journals",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "https?://www\\.airuniversity\\.af\\.edu/(ASPJ|SSQ)",
|
||||
"target": "https?://www\\.airuniversity\\.af\\.mil/(ASPJ|SSQ)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-10-14 19:04:37"
|
||||
"lastUpdated": "2017-12-11 22:06:13"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -35,12 +35,15 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
// attr()/text() v2
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (text(doc, 'a[title="View Article"], h2>a[href*="documents"]', 1)) {
|
||||
if (text(doc, 'a[title="View Article"]', 1)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -50,46 +53,39 @@ function doWeb(doc, url) {
|
|||
if (rows.length < 3) {
|
||||
rows = ZU.xpath(doc, '//div[@class="da_black"]//p[span//a[@title="View Article"]]');
|
||||
}
|
||||
if (!rows.length) {
|
||||
// New layout, e.g. https://www.airuniversity.af.edu/SSQ/Display/Article/2748342/volume-15-issue-3-fall-2021/
|
||||
rows = ZU.xpath(doc, '//div[@class="da_black"]//li//div[h2/a or h2/em/a]');
|
||||
}
|
||||
|
||||
// Z.debug(rows.length);
|
||||
var items = {};
|
||||
var journal, abbr, ISSN;
|
||||
if (url.includes("/ASPJ/")) {
|
||||
journal = "Air & Space Power Journal";
|
||||
abbr = "ASPJ";
|
||||
ISSN = "1554-2505";
|
||||
var journal = "Air & Space Power Journal";
|
||||
var abbr = "ASPJ";
|
||||
var ISSN = "1554-2505";
|
||||
}
|
||||
else if (url.includes("/SSQ/")) {
|
||||
journal = "Strategic Studies Quarterly";
|
||||
abbr = "SSQ";
|
||||
ISSN = "1936-1815";
|
||||
var journal = "Strategic Studies Quarterly";
|
||||
var abbr = "SSQ";
|
||||
var ISSN = "1936-1815";
|
||||
}
|
||||
var voliss = text(doc, 'h1.title');
|
||||
var date = text(doc, 'p.da_story_info');
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
var infoArray = [];
|
||||
|
||||
var title = text(rows[i], 'span > a[title="View Article"]');
|
||||
var id = attr(rows[i], 'span > a[title="View Article"]', "href");
|
||||
var id = attr(rows[i], 'span > a[title="View Article"]', "id");
|
||||
if (!title) {
|
||||
title = text(rows[i], 'strong > a[title="View Article"]');
|
||||
id = attr(rows[i], 'strong > a[title="View Article"]', "href");
|
||||
}
|
||||
|
||||
if (!title) {
|
||||
title = text(rows[i], 'h2 > a, h2>em>a');
|
||||
id = attr(rows[i], 'h2 > a, h2>em>a', "href");
|
||||
id = attr(rows[i], 'strong > a[title="View Article"]', "id");
|
||||
}
|
||||
|
||||
if (title !== null) {
|
||||
items[id] = title;
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.selectItems(items, function (items) {
|
||||
Zotero.selectItems(items, function(items) {
|
||||
// Z.debug(items);
|
||||
if (!items) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
for (let id in items) {
|
||||
scrapeMultiples(doc, id, date, voliss, journal, abbr, ISSN);
|
||||
|
|
@ -100,82 +96,39 @@ function doWeb(doc, url) {
|
|||
|
||||
|
||||
function scrapeMultiples(doc, id, date, voliss, journal, abbr, ISSN) {
|
||||
// Z.debug(id)
|
||||
var item = new Z.Item('journalArticle');
|
||||
|
||||
var titleXpath = '//span/a[contains(@href, "' + id + '")]';
|
||||
var title = ZU.xpathText(doc, titleXpath);
|
||||
var link = id;
|
||||
|
||||
var title = text(doc, 'span > a#' + id);
|
||||
var link = attr(doc, 'span > a#' + id, "href");
|
||||
if (!title) {
|
||||
titleXpath = '//strong/a[contains(@href, "' + id + '")]';
|
||||
title = ZU.xpathText(doc, titleXpath);
|
||||
link = id;
|
||||
}
|
||||
|
||||
// Newer issues
|
||||
if (!title) {
|
||||
titleXpath = '//h2//a[contains(@href, "' + id + '")]';
|
||||
title = ZU.xpathText(doc, titleXpath);
|
||||
link = id;
|
||||
title = text(doc, 'strong > a#' + id);
|
||||
link = attr(doc, 'strong > a#' + id, "href");
|
||||
}
|
||||
item.title = ZU.trimInternal(title.trim());
|
||||
|
||||
var sectionXpath = '//div[@class="da_black"]/table[tbody//a[@href="' + id + '"]]';
|
||||
var section = ZU.xpath(doc, sectionXpath);
|
||||
var section = ZU.xpath(doc, '//div[@class="da_black"]/table[tbody//a[@id="' + id + '"]]');
|
||||
if (!section.length) {
|
||||
sectionXpath = '//div[@class="da_black"]/p[span//a[@href="' + id + '"]]';
|
||||
section = ZU.xpath(doc, sectionXpath);
|
||||
section = ZU.xpath(doc, '//div[@class="da_black"]/p[span//a[@id="' + id + '"]]');
|
||||
}
|
||||
|
||||
// Newer issues
|
||||
if (!section.length) {
|
||||
sectionXpath = '//div[@class="da_black"]//div[h2//a[@href="' + id + '"]]';
|
||||
section = ZU.xpath(doc, sectionXpath);
|
||||
}
|
||||
|
||||
if (section.length) {
|
||||
var authors = text(section[0], 'p>span>strong');
|
||||
if (!authors) authors = text(section[0], 'p>strong>span');
|
||||
|
||||
// Newer issues
|
||||
if (!authors) authors = text(section[0], 'strong');
|
||||
|
||||
if (authors) {
|
||||
if (authors.includes("Reviewed by")) {
|
||||
var reviewedAuthor = authors.match(/^by\s(.+)/);
|
||||
var reviewer = authors.match(/Reviewed by\s(.+)/);
|
||||
|
||||
if (reviewedAuthor) {
|
||||
reviewedAuthor = parseAuthors(reviewedAuthor[1], "reviewedAuthor");
|
||||
}
|
||||
if (reviewer) {
|
||||
reviewer = parseAuthors(reviewer[1], "author");
|
||||
}
|
||||
authors = ZU.trimInternal(authors.trim());
|
||||
// delete name suffixes
|
||||
authors = authors.replace(/, (USAF|USN|Retired|PE|LMFT)\b/g, "");
|
||||
authorsList = authors.split(/\/|,?\sand\s|,\s/);
|
||||
var rank = /^(By:|Adm|Rear Adm|Col|Lt Col|Brig Gen|Gen|Maj Gen \(sel\)|Maj|Capt|Maj Gen|2nd Lt|W(in)?g Cdr|Mr?s\.|Mr\.|Dr\.)\s/;
|
||||
|
||||
if (reviewedAuthor && reviewer) {
|
||||
item.creators = reviewer.concat(reviewedAuthor);
|
||||
}
|
||||
|
||||
else {
|
||||
item.creators = reviewer || reviewedAuthor;
|
||||
}
|
||||
}
|
||||
else {
|
||||
authors = ZU.trimInternal(authors.trim());
|
||||
// delete name suffixes
|
||||
item.creators = parseAuthors(authors, "author");
|
||||
for (i = 0; i < authorsList.length; i++) {
|
||||
// Z.debug(authorsList[i]);
|
||||
var author = authorsList[i].trim().replace(rank, "");
|
||||
item.creators.push(ZU.cleanAuthor(author, "author"));
|
||||
}
|
||||
}
|
||||
// ASPJ
|
||||
var abstract = text(section[0], 'p > span', 1);
|
||||
|
||||
// SSQ
|
||||
if (!abstract) abstract = ZU.xpathText(section[0], './/p/span[1]/text()');
|
||||
|
||||
// Newer issues
|
||||
if (!abstract) abstract = ZU.xpathText(section[0], './/p/text()');
|
||||
var abstract = text(section[0], 'p > span', 2);
|
||||
if (!abstract) abstract = text(section[0], 'p > span', 1);
|
||||
if (abstract) {
|
||||
item.abstractNote = ZU.trimInternal(abstract.trim().replace(/^,\s/, ""));
|
||||
item.abstractNote = ZU.trimInternal(abstract.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,33 +156,16 @@ function scrapeMultiples(doc, id, date, voliss, journal, abbr, ISSN) {
|
|||
item.complete();
|
||||
}
|
||||
|
||||
function parseAuthors(creators, type) {
|
||||
creators = ZU.trimInternal(creators.trim());
|
||||
// delete name suffixes
|
||||
creators = creators.replace(/, (USAF|USN|Retired|PE|LMFT|USA|[^,]+Air Force)\b/g, "");
|
||||
let creatorsList = creators.split(/\/|,?\sand\s|,\s/);
|
||||
var rank = /^(By:|Adm|Rear Adm|Col|Lt Col|LTC|Brig Gen|Gen|Maj Gen \(sel\)|Maj|Capt|CAPT|Maj Gen|2nd Lt|W(in)?g Cdr|Mr?s\.|Mr\.|Dr\.)\s/;
|
||||
var creatorsArray = [];
|
||||
for (let creator of creatorsList) {
|
||||
creator = creator.trim().replace(rank, "");
|
||||
creatorsArray.push(ZU.cleanAuthor(creator, type));
|
||||
}
|
||||
return creatorsArray;
|
||||
}/** BEGIN TEST CASES **/
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.airuniversity.af.edu/SSQ/Display/Article/1261066/volume-11-issue-3-fall-2017/",
|
||||
"url": "http://www.airuniversity.af.mil/SSQ/Display/Article/1261066/volume-11-issue-3-fall-2017/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.airuniversity.af.edu/ASPJ/Display/Article/1151902/volume-30-issue-2-summer-2016/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.airuniversity.af.edu/SSQ/Display/Article/2748342/volume-15-issue-3-fall-2021/",
|
||||
"url": "http://www.airuniversity.af.mil/ASPJ/Display/Article/1151902/volume-30-issue-2-summer-2016/",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"translatorID": "0a84a653-79ea-4c6a-8a68-da933e3b504a",
|
||||
"translatorType": 4,
|
||||
"label": "Alexander Street Press",
|
||||
"creator": "John West and Michael Berkowitz",
|
||||
"target": "^https?://(www\\.)alexanderstreet",
|
||||
|
|
@ -7,47 +8,45 @@
|
|||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-12-28 04:42:00"
|
||||
"lastUpdated": "2009-01-08 08:19:07"
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if ( url.indexOf("object.details.aspx") != -1 ) {
|
||||
var zitemtype = doc.getElementById("ctl00_ctl00_MasterContentBody_ContentPlaceHolder1_txtZType").value;
|
||||
switch (zitemtype.toLowerCase()) {
|
||||
case "book":
|
||||
return "book";
|
||||
break;
|
||||
case "chapter":
|
||||
return "bookSection";
|
||||
break;
|
||||
case "journal":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "manuscript":
|
||||
return "manuscript";
|
||||
break;
|
||||
case "audio":
|
||||
return "audioRecording";
|
||||
break;
|
||||
case "video":
|
||||
return "videoRecording";
|
||||
break;
|
||||
case "issue":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "article":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "series":
|
||||
return "interview";
|
||||
break;
|
||||
case "session":
|
||||
return "interview";
|
||||
break;
|
||||
default:
|
||||
return "document";
|
||||
case "book":
|
||||
return "book";
|
||||
break;
|
||||
case "chapter":
|
||||
return "bookSection";
|
||||
break;
|
||||
case "journal":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "manuscript":
|
||||
return "manuscript";
|
||||
break;
|
||||
case "audio":
|
||||
return "audioRecording";
|
||||
break;
|
||||
case "video":
|
||||
return "videoRecording";
|
||||
break;
|
||||
case "issue":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "article":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "series":
|
||||
return "interview";
|
||||
break;
|
||||
case "session":
|
||||
return "interview";
|
||||
break;
|
||||
default:
|
||||
return "document";
|
||||
}
|
||||
} else if (url.indexOf("results.aspx") != -1) {
|
||||
return "multiple";
|
||||
|
|
@ -141,39 +140,39 @@ function scrape(doc, url) {
|
|||
|
||||
function GetItemType(zitemtype) {
|
||||
switch (zitemtype.toLowerCase()) {
|
||||
case "book":
|
||||
return "book";
|
||||
break;
|
||||
case "chapter":
|
||||
return "bookSection";
|
||||
break;
|
||||
case "journal":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "manuscript":
|
||||
return "manuscript";
|
||||
break;
|
||||
case "audio":
|
||||
return "audioRecording";
|
||||
break;
|
||||
case "video":
|
||||
return "videoRecording";
|
||||
break;
|
||||
case "issue":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "article":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "series":
|
||||
return "interview";
|
||||
break;
|
||||
case "session":
|
||||
return "interview";
|
||||
break;
|
||||
default:
|
||||
return "document";
|
||||
}
|
||||
case "book":
|
||||
return "book";
|
||||
break;
|
||||
case "chapter":
|
||||
return "bookSection";
|
||||
break;
|
||||
case "journal":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "manuscript":
|
||||
return "manuscript";
|
||||
break;
|
||||
case "audio":
|
||||
return "audioRecording";
|
||||
break;
|
||||
case "video":
|
||||
return "videoRecording";
|
||||
break;
|
||||
case "issue":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "article":
|
||||
return "journalArticle";
|
||||
break;
|
||||
case "series":
|
||||
return "interview";
|
||||
break;
|
||||
case "session":
|
||||
return "interview";
|
||||
break;
|
||||
default:
|
||||
return "document";
|
||||
}
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
|
|
@ -186,13 +185,13 @@ function doWeb(doc, url) {
|
|||
while (next_title = titles.iterateNext()) {
|
||||
items[next_title.href] = next_title.textContent;
|
||||
}
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) return;
|
||||
ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
items = Zotero.selectItems(items);
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
articles = [url];
|
||||
}
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = []
|
||||
/** END TEST CASES **/
|
||||
|
||||
Zotero.Utilities.processDocuments(articles, scrape, function() {Zotero.done();});
|
||||
}
|
||||
269
AllAfrica.js
269
AllAfrica.js
File diff suppressed because one or more lines are too long
242
Alsharekh.js
242
Alsharekh.js
|
|
@ -1,242 +0,0 @@
|
|||
{
|
||||
"translatorID": "70fbaf2f-ba02-426c-8beb-4ddfbbefd14b",
|
||||
"label": "Alsharekh",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https://archive\\.alsharekh\\.org/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-07-24 02:21:59"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
let apiBase = 'https://archiveapi.alsharekh.org';
|
||||
let urlRe = /\/Articles\/([^/]+)\/([^/]+)\/([^/?#]+)/;
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (urlRe.test(url)) {
|
||||
return "magazineArticle";
|
||||
}
|
||||
let appElem = doc.querySelector("app-root");
|
||||
if (appElem) {
|
||||
Z.monitorDOMChanges(appElem);
|
||||
}
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('td > a[href^="/Articles/"], th > a[href^="/Articles/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
let items = await Z.selectItems(getSearchResults(doc));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(null, url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(doc, url) {
|
||||
let item = new Zotero.Item('magazineArticle');
|
||||
|
||||
let [, MID, IID, AID] = url.match(urlRe);
|
||||
let issue = await requestJSON(`${apiBase}/Search/IssueHInfo?MID=${MID}&IID=${IID}`);
|
||||
let article = await requestJSON(`${apiBase}/Search/ArticleHInfo?AID=${AID}`);
|
||||
|
||||
item.title = article.articleTitle.replace(' : ', ": ");
|
||||
item.pages = article.pageNo;
|
||||
item.creators.push(ZU.cleanAuthor(article.articleAuthor, 'author'));
|
||||
|
||||
item.publicationTitle = issue.magazineArabicName;
|
||||
item.place = issue.countryName;
|
||||
item.issue = issue.issuenumber || issue.issueName;
|
||||
item.date = ZU.strToISO(arabicToEnglishDate(issue.newIssueDate));
|
||||
|
||||
item.url = url;
|
||||
|
||||
let attachment = { title: "Snapshot" };
|
||||
if (doc) {
|
||||
attachment.document = doc;
|
||||
}
|
||||
else {
|
||||
attachment.url = url;
|
||||
}
|
||||
item.attachments.push(attachment);
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
// just so we get months on non-Arabic locales
|
||||
function arabicToEnglishDate(date) {
|
||||
return date
|
||||
.replace('يناير', 'January')
|
||||
.replace('فبراير', 'February')
|
||||
.replace('مارس', 'March')
|
||||
.replace('أبريل', 'April')
|
||||
.replace('إبريل', 'April')
|
||||
.replace('مايو', 'May')
|
||||
.replace('يونيو', 'June')
|
||||
.replace('يونية', 'June')
|
||||
.replace('يوليو', 'July')
|
||||
.replace('يوليو', 'July')
|
||||
.replace('أغسطس', 'August')
|
||||
.replace('سبتمبر', 'September')
|
||||
.replace('أكتوبر', 'October')
|
||||
.replace('نوفمبر', 'November')
|
||||
.replace('ديسمبر', 'December');
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://archive.alsharekh.org/Articles/290/20647/469598",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "الخط العربي: فلسفة التأصيل الجمالي والتفريع الفني",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "بركات محمد",
|
||||
"lastName": "مراد",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2004-04-01",
|
||||
"issue": "11",
|
||||
"libraryCatalog": "Alsharekh",
|
||||
"publicationTitle": "حروف عربية",
|
||||
"shortTitle": "الخط العربي",
|
||||
"url": "https://archive.alsharekh.org/Articles/290/20647/469598",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://archive.alsharekh.org/Articles/312/21129/479105",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "الرحالة والباحثون الروس في تاريخ الجزيرة العربية وآثارها \"دراسة تقويمية\"",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "عبد الرحمن الطيب",
|
||||
"lastName": "الأنصاري",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2005-01-01",
|
||||
"issue": "11",
|
||||
"libraryCatalog": "Alsharekh",
|
||||
"publicationTitle": "أدوماتو",
|
||||
"url": "https://archive.alsharekh.org/Articles/312/21129/479105",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://archive.alsharekh.org/Articles/174/16356/368236",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "أسلوب النقض في كتابات الرحالة الأوربيين",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "حسن",
|
||||
"lastName": "غزالة",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2005-06-01",
|
||||
"issue": "20",
|
||||
"libraryCatalog": "Alsharekh",
|
||||
"publicationTitle": "جذور",
|
||||
"url": "https://archive.alsharekh.org/Articles/174/16356/368236",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://archive.alsharekh.org/contents/174/19785",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://archive.alsharekh.org/AuthorArticles/124",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
144
Amazon.js
144
Amazon.js
|
|
@ -8,10 +8,15 @@
|
|||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-03-20 15:38:12"
|
||||
"browserSupport": "gcsbv",
|
||||
"lastUpdated": "2020-09-04 21:40:05"
|
||||
}
|
||||
|
||||
// attr()/text() v2
|
||||
// eslint-disable-next-line
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (getSearchResults(doc, true)) {
|
||||
return (Zotero.isBookmarklet ? "server" : "multiple");
|
||||
|
|
@ -279,10 +284,8 @@ function scrape(doc, url) {
|
|||
)];
|
||||
}
|
||||
if (!role) role = 'author';
|
||||
name = ZU.trimInternal(
|
||||
ZU.xpathText(authors[i], './span/a[contains(@class, "a-link-normal")]|./a[contains(@class, "a-link-normal")]')
|
||||
|| text(authors[i], ':scope > span > a[data-a-component="text-link"]')
|
||||
).replace(/\s*\([^)]+\)/, '').replace(/,\s*$/, '');
|
||||
name = ZU.trimInternal(ZU.xpathText(authors[i], './span/a[contains(@class, "a-link-normal")]|./a[contains(@class, "a-link-normal")]'))
|
||||
.replace(/\s*\([^)]+\)/, '').replace(/,\s*$/, '');
|
||||
if (item.itemType == 'audioRecording') {
|
||||
item.creators.push({
|
||||
lastName: name,
|
||||
|
|
@ -314,10 +317,8 @@ function scrape(doc, url) {
|
|||
item.abstractNote = abstractNode.textContent.trim();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item.abstractNote = text(doc, '#bookDescription_feature_div .a-expander-content');
|
||||
}
|
||||
|
||||
|
||||
// Extract info into an array
|
||||
var info = {},
|
||||
els = ZU.xpath(doc, '//div[@class="content"]/ul/li[b]');
|
||||
|
|
@ -330,26 +331,6 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!els.length) {
|
||||
// New design encountered 08/31/2020
|
||||
els = doc.querySelectorAll('ul.detail-bullet-list li');
|
||||
if (!els.length) {
|
||||
// New design encountered 2022-11-20
|
||||
els = doc.querySelectorAll('#detailBullets_feature_div ul > li span');
|
||||
}
|
||||
for (let el of els) {
|
||||
let key = text(el, '.a-list-item span:first-child');
|
||||
let value = text(el, '.a-list-item span:nth-child(2)');
|
||||
if (key && value) {
|
||||
key = key.replace(/\s*:\s*$/, "");
|
||||
// Extra colon in Language field as of 9/4/2020
|
||||
key = key.replace(/\s*:$/, '');
|
||||
// The colon is surrounded by RTL/LTR marks as of 6/24/2021
|
||||
key = key.replace(/[\s\u200e\u200f]*:[\s\u200e\u200f]*$/, '');
|
||||
info[key.toLowerCase()] = value.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!els.length) {
|
||||
// New design encountered 06/30/2013
|
||||
els = ZU.xpath(doc, '//tr[td[@class="a-span3"]][td[@class="a-span9"]]');
|
||||
|
|
@ -362,11 +343,26 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!els.length) {
|
||||
// New design encountered 08/31/2020
|
||||
els = doc.querySelectorAll('ul.detail-bullet-list li');
|
||||
for (let el of els) {
|
||||
let key = text(el, '.a-list-item span:first-child');
|
||||
let value = text(el, '.a-list-item span:nth-child(2)');
|
||||
if (key && value) {
|
||||
key = key.replace(/\s*:\s*$/, "");
|
||||
// Extra colon in Language field as of 9/4/2020
|
||||
key = key.replace(/\s*:$/, '');
|
||||
info[key.toLowerCase()] = value.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.ISBN = getField(info, 'ISBN');
|
||||
if (item.ISBN) {
|
||||
item.ISBN = ZU.cleanISBN(item.ISBN);
|
||||
}
|
||||
|
||||
|
||||
// Date
|
||||
for (let i = 0; i < DATE.length; i++) {
|
||||
item.date = info[DATE[i]];
|
||||
|
|
@ -388,10 +384,9 @@ function scrape(doc, url) {
|
|||
item.edition = m[2].trim()
|
||||
.replace(/^(Auflage|Édition)\s?:/, '')
|
||||
// "FISCHER Taschenbuch; 15. Auflage (1. Mai 1992)""
|
||||
.replace(/\. (Auflage|[EÉ]dition)\s*/, '');
|
||||
.replace(/\. (Auflage|Édition)\s*/, '');
|
||||
}
|
||||
// Looks like a date
|
||||
if (m[3] && m[3].search(/\b\d{4}\b/) != -1) item.date = ZU.strToISO(m[3].trim());
|
||||
if (m[3] && m[3].search(/\b\d{4}\b/) != -1) item.date = m[3].trim(); // Looks like a date
|
||||
}
|
||||
var pages = getField(info, 'Hardcover') || getField(info, 'Paperback') || getField(info, 'Print Length');
|
||||
if (pages) item.numPages = parseInt(pages);
|
||||
|
|
@ -466,6 +461,7 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -482,13 +478,14 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2010-04-01",
|
||||
"date": "April 1, 2010",
|
||||
"ISBN": "9780810989894",
|
||||
"abstractNote": "Now in paperback! Pass, and have it made. Fail, and suffer the consequences. A master of teen thrillers tests readers’ courage in an edge-of-your-seat novel that echoes the fears of exam-takers everywhere. Ann, a teenage girl living in the security-obsessed, elitist United States of the very near future, is threatened on her way home from school by a mysterious man on a black motorcycle. Soon she and a new friend are caught up in a vast conspiracy of greed involving the mega-wealthy owner of a school testing company. Students who pass his test have it made; those who don’t, disappear . . . or worse. Will Ann be next? For all those who suspect standardized tests are an evil conspiracy, here’s a thriller that really satisfies! Praise for Test “Fast-paced with short chapters that end in cliff-hangers . . . good read for moderately reluctant readers. Teens will be able to draw comparisons to contemporary society’s shift toward standardized testing and ecological concerns, and are sure to appreciate the spoofs on NCLB.” ―School Library Journal “Part mystery, part action thriller, part romance . . . environmental and political overtones . . . fast pace and unique blend of genres holds attraction for younger teen readers.” ―Booklist",
|
||||
"edition": "Reprint edition",
|
||||
"edition": "Reprint Edition",
|
||||
"language": "English",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 320,
|
||||
"place": "New York",
|
||||
"publisher": "Amulet Paperbacks",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -505,7 +502,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.amazon.com/s?k=foot&i=stripbooks&x=0&y=0&ref=nb_sb_noss",
|
||||
"url": "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dstripbooks&field-keywords=foot&x=0&y=0",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
|
|
@ -541,7 +538,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.amazon.com/s?k=The+Harvard+Concise+Dictionary+of+Music+and+Musicians&Go=o",
|
||||
"url": "http://www.amazon.com/s?ie=UTF8&keywords=The%20Harvard%20Concise%20Dictionary%20of%20Music%20and%20Musicians&index=blended&Go=o",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
|
|
@ -599,7 +596,7 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "May 20, 2003",
|
||||
"language": "English (Dolby Digital 2.0 Surround), English (Dolby Digital 5.1), English (DTS 5.1), French (Dolby Digital 5.1), Unqualified (DTS ES 6.1)",
|
||||
"language": "English (Dolby Digital 5.1), English (DTS 5.1), French (Dolby Digital 5.1), Unqualified (DTS ES 6.1), English (Dolby Digital 2.0 Surround)",
|
||||
"libraryCatalog": "Amazon",
|
||||
"runningTime": "1 hour and 55 minutes",
|
||||
"studio": "Sony Pictures Home Entertainment",
|
||||
|
|
@ -616,6 +613,11 @@ var testCases = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.amazon.com/gp/registry/registry.html?ie=UTF8&id=1Q7ELHV59D7N&type=wishlist",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.amazon.fr/Candide-Fran%C3%A7ois-Marie-Voltaire-Arouet-dit/dp/2035866014/ref=sr_1_2?s=books&ie=UTF8&qid=1362329827&sr=1-2",
|
||||
|
|
@ -630,13 +632,13 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"date": "17 août 2011",
|
||||
"ISBN": "9782035866011",
|
||||
"abstractNote": "Que signifie ce nom \"Candide\" : innocence de celui qui ne connaît pas le mal ou illusion du naïf qui n'a pas fait l'expérience du monde ? Voltaire joue en 1759, après le tremblement de terre de Lisbonne, sur ce double sens. Il nous fait partager les épreuves fictives d'un jeune homme simple, confronté aux leurres de l'optimisme, mais qui n'entend pas désespérer et qui en vient à une sagesse finale, mesurée et mystérieuse. Candide n'en a pas fini de nous inviter au gai savoir et à la réflexion.",
|
||||
"edition": "Larousse édition",
|
||||
"language": "Français",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 176,
|
||||
"place": "Paris",
|
||||
"publisher": "Larousse",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -653,7 +655,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.amazon.de/Fiktionen-Erz%C3%A4hlungen-Jorge-Luis-Borges/dp/3596105811/ref=sr_1_1?ie=UTF8&qid=1362329791&sr=8-1&lang=de-de&language=de_DE",
|
||||
"url": "https://www.amazon.de/Fiktionen-Erz%C3%A4hlungen-Jorge-Luis-Borges/dp/3596105811/ref=sr_1_1?ie=UTF8&qid=1362329791&sr=8-1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -665,10 +667,10 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1992",
|
||||
"date": "1. Mai 1992",
|
||||
"ISBN": "9783596105816",
|
||||
"abstractNote": "Gleich bei seinem Erscheinen in den 40er Jahren löste Jorge Luis Borges’ erster Erzählband »Fiktionen« eine literarische Revolution aus. Erfundene Biographien, fiktive Bücher, irreale Zeitläufe und künstliche Realitäten verflocht Borges zu einem geheimnisvollen Labyrinth, das den Leser mit seinen Rätseln stets auf neue herausfordert. Zugleich begründete er mit seinen berühmten Erzählungen wie»›Die Bibliothek zu Babel«, «Die kreisförmigen Ruinen« oder»›Der Süden« den modernen »Magischen Realismus«.\n\n»Obwohl sie sich im Stil derart unterscheiden, zeigen zwei Autoren uns ein Bild des nächsten Jahrtausends: Joyce und Borges.« Umberto Eco",
|
||||
"edition": "16",
|
||||
"abstractNote": "Gleich bei seinem Erscheinen in den 40er Jahren löste Jorge Luis Borges’ erster Erzählband »Fiktionen« eine literarische Revolution aus. Erfundene Biographien, fiktive Bücher, irreale Zeitläufe und künstliche Realitäten verflocht Borges zu einem geheimnisvollen Labyrinth, das den Leser mit seinen Rätseln stets auf neue herausfordert. Zugleich begründete er mit seinen berühmten Erzählungen wie»›Die Bibliothek zu Babel«, «Die kreisförmigen Ruinen« oder»›Der Süden« den modernen »Magischen Realismus«. »Obwohl sie sich im Stil derart unterscheiden, zeigen zwei Autoren uns ein Bild des nächsten Jahrtausends: Joyce und Borges.« Umberto Eco",
|
||||
"edition": "15",
|
||||
"language": "Deutsch",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 192,
|
||||
|
|
@ -702,11 +704,11 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2010-12-01",
|
||||
"date": "1 Dec. 2010",
|
||||
"abstractNote": "Novel by Charles Dickens, published both serially and in book form in 1859. The story is set in the late 18th century against the background of the French Revolution. Although Dickens borrowed from Thomas Carlyle's history, The French Revolution, for his sprawling tale of London and revolutionary Paris, the novel offers more drama than accuracy. The scenes of large-scale mob violence are especially vivid, if superficial in historical understanding. The complex plot involves Sydney Carton's sacrifice of his own life on behalf of his friends Charles Darnay and Lucie Manette. While political events drive the story, Dickens takes a decidedly antipolitical tone, lambasting both aristocratic tyranny and revolutionary excess--the latter memorably caricatured in Madame Defarge, who knits beside the guillotine. The book is perhaps best known for its opening lines, \"It was the best of times, it was the worst of times,\" and for Carton's last speech, in which he says of his replacing Darnay in a prison cell, \"It is a far, far better thing that I do, than I have ever done; it is a far, far better rest that I go to, than I have ever known.\" -- The Merriam-Webster Encyclopedia of Literature",
|
||||
"language": "English",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 290,
|
||||
"numPages": 264,
|
||||
"publisher": "Public Domain Books",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -735,23 +737,23 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Björn",
|
||||
"firstName": "B.",
|
||||
"lastName": "Berg",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Annuska Palme Larussa",
|
||||
"firstName": "A. Palme Larussa",
|
||||
"lastName": "Sanavio",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"date": "2008",
|
||||
"date": "26 giugno 2008",
|
||||
"ISBN": "9788882038670",
|
||||
"abstractNote": "Si pensa che soprattutto in una casa moderna, con prese elettriche, gas, balconi altissimi un bambino possa mettersi in pericolo: Emil vive in una tranquilla casa di campagna, ma riesce a ficcare la testa in una zuppiera e a rimanervi incastrato, a issare la sorellina Ida in cima all'asta di una bandiera, e a fare una tale baldoria alla fiera del paese che i contadini decideranno di organizzare una colletta per spedirlo in America e liberare così la sua povera famiglia. Ma questo succederà nel prossimo libro di Emil, perché ce ne sarà un altro, anzi due, tante sono le sue monellerie. Età di lettura: da 7 anni.",
|
||||
"edition": "3° edizione",
|
||||
"language": "Italiano",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 72,
|
||||
"place": "Milano",
|
||||
"publisher": "Nord-Sud",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -789,6 +791,16 @@ var testCases = [
|
|||
"lastName": "Nagai",
|
||||
"creatorType": "castMember"
|
||||
},
|
||||
{
|
||||
"firstName": "Ed",
|
||||
"lastName": "Asner",
|
||||
"creatorType": "castMember"
|
||||
},
|
||||
{
|
||||
"firstName": "Christopher",
|
||||
"lastName": "Plummer",
|
||||
"creatorType": "castMember"
|
||||
},
|
||||
{
|
||||
"firstName": "Pete",
|
||||
"lastName": "Docter",
|
||||
|
|
@ -833,7 +845,7 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"libraryCatalog": "Amazon",
|
||||
"runningTime": "1:09:16",
|
||||
"runningTime": "1:08:58",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Amazon.com Link",
|
||||
|
|
@ -861,16 +873,14 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2012-08-02",
|
||||
"date": "2012/8/2",
|
||||
"ISBN": "9780099578079",
|
||||
"abstractNote": "The year is 1Q84. This is the real world, there is no doubt about that. But in this world, there are two moons in the sky. In this world, the fates of two people, Tengo and Aomame, are closely intertwined. They are each, in their own way, doing something very dangerous. And in this world, there seems no way to save them both. Something extraordinary is starting.",
|
||||
"edition": "Combined edition",
|
||||
"language": "English",
|
||||
"abstractNote": "The year is 1Q84. This is the real world, there is no doubt about that. But in this world, there are two moons in the sky. In this world, the fates of two people, Tengo and Aomame, are closely intertwined. They are each, in their own way, doing something very dangerous. And in this world, there seems no way to save them both. Something extraordinary is starting.",
|
||||
"language": "英語",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 1328,
|
||||
"publisher": "Vintage",
|
||||
"shortTitle": "1Q84",
|
||||
"place": "London",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Amazon.com Link",
|
||||
|
|
@ -886,7 +896,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.amazon.com/Mark-LeBar/e/B00BU8L2DK",
|
||||
"url": "http://www.amazon.com/Mark-LeBar/e/B00BU8L2DK",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
|
|
@ -908,7 +918,7 @@ var testCases = [
|
|||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "1998-04-28",
|
||||
"date": "April 28, 1998",
|
||||
"ISBN": "9780521418195",
|
||||
"abstractNote": "The first printed text of Shakespeare's Hamlet is about half the length of the more familiar second quarto and Folio versions. It reorders and combines key plot elements to present its own workable alternatives. This is the only modernized critical edition of the 1603 quarto in print. Kathleen Irace explains its possible origins, special features and surprisingly rich performance history, and while describing textual differences between it and other versions, offers alternatives that actors or directors might choose for specific productions.",
|
||||
"edition": "First Edition",
|
||||
|
|
@ -944,12 +954,12 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1977-09-16",
|
||||
"date": "1977/9/16",
|
||||
"ISBN": "9784003314210",
|
||||
"language": "Japanese",
|
||||
"abstractNote": "帯ありません。若干のスレはありますがほぼ普通です。小口、天辺に少しヤケがあります。中身は少しヤケはありますがきれいです。",
|
||||
"language": "日本語",
|
||||
"libraryCatalog": "Amazon",
|
||||
"publisher": "岩波書店",
|
||||
"abstractNote": "帯ありません。若干のスレはありますがほぼ普通です。小口、天辺に少しヤケがあります。中身は少しヤケはありますがきれいです。",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Amazon.com Link",
|
||||
|
|
@ -977,12 +987,13 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018-08-24",
|
||||
"date": "April 24, 2018",
|
||||
"ISBN": "9781333821388",
|
||||
"abstractNote": "Excerpt from Studies in Saiva-SiddhantaEuropean Sanskritist, unaware perhaps of the bearings of the expression, rendered the collocation Parama-hamsa' into 'great goose'. The strictly pedagogic purist may endeavour to justify such puerile versions on etymological grounds, but they stand Self-condemned as mal-interpretations re?ecting anything but the sense and soul of the original. Such lapses into unwitting ignorance, need never be expected in any of the essays contained in the present collection, as our author is not only a sturdy and indefatigable researcher in Tamil philosophic literature illuminative Of the Agamic religion, but has also, in his quest after Truth, freely utilised the services of those Indigenous savam's, who represent the highest water-mark of Hindu traditional learning and spiritual associations at the present-day.",
|
||||
"abstractNote": "Excerpt from Studies in Saiva-SiddhantaEuropean Sanskritist, unaware perhaps of the bearings of the expression, rendered the collocation Parama-hamsa' into 'great goose'. The strictly pedagogic purist may endeavour to justify such puerile versions on etymological grounds, but they stand Self-condemned as mal-interpretations reflecting anything but the sense and soul of the original. Such lapses into unwitting ignorance, need never be expected in any of the essays contained in the present collection, as our author is not only a sturdy and indefatigable researcher in Tamil philosophic literature illuminative Of the Agamic religion, but has also, in his quest after Truth, freely utilised the services of those Indigenous savam's, who represent the highest water-mark of Hindu traditional learning and spiritual associations at the present-day.About the PublisherForgotten Books publishes hundreds of thousands of rare and classic books. Find more at www.forgottenbooks.comThis book is a reproduction of an important historical work. Forgotten Books uses state-of-the-art technology to digitally reconstruct the work, preserving the original format whilst repairing imperfections present in the aged copy. In rare cases, an imperfection in the original, such as a blemish or missing page, may be replicated in our edition. We do, however, repair the vast majority of imperfections successfully; any imperfections that remain are intentionally left to preserve the state of such historical works.",
|
||||
"language": "English",
|
||||
"libraryCatalog": "Amazon",
|
||||
"numPages": 396,
|
||||
"numPages": 398,
|
||||
"place": "Place of publication not identified",
|
||||
"publisher": "Forgotten Books",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -1021,11 +1032,10 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-05-01",
|
||||
"edition": "第 1st 版",
|
||||
"date": "2015年5月1日",
|
||||
"abstractNote": "《中国之翼》是一本书写了一段未被透露的航空编年史的篇章,它讲述了二战时期亚洲战场动荡的背景下的航空冒险的扣人心弦的故事。故事的主体是激动人心的真实的“空中兄弟连”的冒险事迹。正是这些人在二战期间帮助打开了被封锁的中国的天空,并勇敢的在各种冲突中勇敢守卫着它。这是一段值得被更多的中国人和美国人知晓并铭记的航空史和中美关系史。",
|
||||
"libraryCatalog": "Amazon",
|
||||
"publisher": "社会科学文献出版社",
|
||||
"abstractNote": "《中国之翼》是一本书写了一段未被透露的航空编年史的篇章,它讲述了二战时期亚洲战场动荡的背景下的航空冒险的扣人心弦的故事。故事的主体是激动人心的真实的“空中兄弟连”的冒险事迹。正是这些人在二战期间帮助打开了被封锁的中国的天空,并勇敢的在各种冲突中勇敢守卫着它。这是一段值得被更多的中国人和美国人知晓并铭记的航空史和中美关系史。",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Amazon.com Link",
|
||||
|
|
|
|||
|
|
@ -1,592 +0,0 @@
|
|||
{
|
||||
"translatorID": "d13eb92e-fb16-41e0-9a24-73bad50f9bb7",
|
||||
"label": "American Archive of Public Broadcasting",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?americanarchive\\.org/catalog",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-28 19:23:21"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.querySelector('meta[property="og:video"]')) {
|
||||
return "tvBroadcast";
|
||||
}
|
||||
else if (doc.querySelector('meta[property="og:audio"]')) {
|
||||
return "radioBroadcast";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h2 > a[href*="/catalog/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
if (item.abstractNote) {
|
||||
item.abstractNote = item.abstractNote.replace(/\n+/g, ' ');
|
||||
}
|
||||
|
||||
for (let entry of doc.querySelectorAll('.contributors dl')) {
|
||||
for (let b of entry.querySelectorAll('b')) {
|
||||
let label = b.textContent;
|
||||
let name = b.nextSibling.textContent.trim().replace(/^Dr\b/, '');
|
||||
let type = 'contributor';
|
||||
let institution = false;
|
||||
|
||||
if (label.includes('Reporter') || label.includes('Host')) {
|
||||
type = 'castMember';
|
||||
}
|
||||
else if (label.includes('Director')) {
|
||||
type = 'director';
|
||||
}
|
||||
else if (label.includes('Writer')) {
|
||||
type = 'scriptwriter';
|
||||
}
|
||||
else if (label.includes('Produc')) {
|
||||
type = 'producer';
|
||||
}
|
||||
else if (label.includes('Copyright Holder')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (label.includes('Organization')) {
|
||||
institution = true;
|
||||
}
|
||||
|
||||
if (institution) {
|
||||
item.creators.push({
|
||||
lastName: name,
|
||||
creatorType: type,
|
||||
fieldMode: 1
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.creators.push(ZU.cleanAuthor(name, type, name.includes(', ')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let dt of doc.querySelectorAll('dt')) {
|
||||
let key = ZU.trimInternal(dt.textContent);
|
||||
|
||||
let dd = dt.nextElementSibling;
|
||||
while (dd && dd.tagName == 'DD') {
|
||||
let value = ZU.trimInternal(dd.textContent);
|
||||
|
||||
switch (key) {
|
||||
case 'Contributing Organization':
|
||||
case 'Producing Organization': {
|
||||
if (item.network) break;
|
||||
|
||||
if (!item.creators.length) {
|
||||
item.creators.push({
|
||||
lastName: value.replace(/\s*\(.*\)/, ''),
|
||||
creatorType: 'contributor',
|
||||
fieldMode: 1
|
||||
});
|
||||
}
|
||||
|
||||
let [, broadcaster, place] = value.match(/^([^(]*)(?:\((.+)\))?/);
|
||||
|
||||
if (/([WK][A-Z]{2,3}|PBS|NPR|Broadcast|Network)/.test(broadcaster)) {
|
||||
item.network = broadcaster;
|
||||
}
|
||||
|
||||
if (place) item.place = place;
|
||||
|
||||
break;
|
||||
}
|
||||
case 'Date':
|
||||
case 'Created':
|
||||
if (!item.date) {
|
||||
item.date = ZU.strToISO(value);
|
||||
}
|
||||
break;
|
||||
case 'Genres':
|
||||
case 'Topics':
|
||||
item.tags.push({ tag: value });
|
||||
break;
|
||||
case 'Duration':
|
||||
item.runningTime = value;
|
||||
break;
|
||||
case 'Series':
|
||||
item.programTitle = value;
|
||||
break;
|
||||
case 'Episode':
|
||||
item.title = value;
|
||||
break;
|
||||
case 'Episode Number':
|
||||
item.episodeNumber = value;
|
||||
break;
|
||||
case 'Rights':
|
||||
item.rights = value;
|
||||
break;
|
||||
}
|
||||
|
||||
dd = dd.nextElementSibling;
|
||||
}
|
||||
}
|
||||
|
||||
// from the suggested citation on item pages
|
||||
item.archive = 'American Archive of Public Broadcasting (GBH and the Library of Congress)';
|
||||
|
||||
// would like to grab the video file and attach it here, but they do a
|
||||
// referer check that precludes that.
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip_83-407wmf7g",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "tvBroadcast",
|
||||
"title": "One More Harvest",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "PBS Utah",
|
||||
"creatorType": "contributor",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "1984",
|
||||
"abstractNote": "This program profiles Utah farmer Melvin Good and his family. During the program, Melvin reminisces about his life and growing up on the farm; his grandchildren discuss the decision to becoming farmers or pursue another vocation; family members describe Melvin's and their passion for farming; and Melvin describes the process of harvesting a crop.",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "PBS Utah",
|
||||
"place": "Salt Lake City, Utah",
|
||||
"rights": "KUED",
|
||||
"runningTime": "00:28:27",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-83-407wmf7g",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Agriculture"
|
||||
},
|
||||
{
|
||||
"tag": "Documentary"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip_223-225b07vs",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "radioBroadcast",
|
||||
"title": "Art and Violence",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Amy",
|
||||
"lastName": "Tardiff",
|
||||
"creatorType": "castMember"
|
||||
}
|
||||
],
|
||||
"date": "1995-06-17",
|
||||
"abstractNote": "This segment reports on an artist who discusses the importance of art in response to the violence of contemporary society.",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "WGCU Public Media",
|
||||
"place": "Fort Myers, Florida",
|
||||
"rights": "No copyright statement in content.",
|
||||
"runningTime": "00:04:33",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-223-225b07vs",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Fine Arts"
|
||||
},
|
||||
{
|
||||
"tag": "Local Communities"
|
||||
},
|
||||
{
|
||||
"tag": "News"
|
||||
},
|
||||
{
|
||||
"tag": "News Report"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip-526-cv4bn9z59z",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "tvBroadcast",
|
||||
"title": "The Test",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "WTVI",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
},
|
||||
{
|
||||
"lastName": "Charlotte-Mecklenburg Board of Education",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"abstractNote": "\"'THE TEST' contains practical suggestions on how to reduce a student's trauma when taking a standardized test.\"--1979 Peabody Awards entry form.",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "WTVI",
|
||||
"runningTime": "00:10:32.265",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-526-cv4bn9z59z",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip-153-956djvtx",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "tvBroadcast",
|
||||
"title": "Front Street Weekly",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Vivian",
|
||||
"lastName": "Condeni",
|
||||
"creatorType": "producer"
|
||||
},
|
||||
{
|
||||
"firstName": "Lyle",
|
||||
"lastName": "Graham",
|
||||
"creatorType": "director"
|
||||
},
|
||||
{
|
||||
"firstName": "Lyle",
|
||||
"lastName": "Graham",
|
||||
"creatorType": "producer"
|
||||
},
|
||||
{
|
||||
"firstName": "Gwyneth Gamble",
|
||||
"lastName": "Booth",
|
||||
"creatorType": "castMember"
|
||||
},
|
||||
{
|
||||
"lastName": "Oregon Public Broadcasting",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "1984-11-21",
|
||||
"abstractNote": "This episode contains the following segments. The first segment, \"Spiritual Epidemic?,\" features individuals whose search for enlightenment has become all-consuming. The second, \"Magic in the Night?,\" investigates fire-walking and whether it amounts to anything more than a financial scam. The third segment, \"Salem Art Fair '85,\" is a profile on the annual 3-day summer festival. Front Street Weekly is a news magazine featuring segments on current events and topics of interest to the local community.",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "Oregon Public Broadcasting",
|
||||
"programTitle": "Front Street Weekly",
|
||||
"rights": "Oregon Public Broadcasting c. 1985",
|
||||
"runningTime": "00:29:48",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-153-956djvtx",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Crafts"
|
||||
},
|
||||
{
|
||||
"tag": "Health"
|
||||
},
|
||||
{
|
||||
"tag": "Local Communities"
|
||||
},
|
||||
{
|
||||
"tag": "Magazine"
|
||||
},
|
||||
{
|
||||
"tag": "News"
|
||||
},
|
||||
{
|
||||
"tag": "News Report"
|
||||
},
|
||||
{
|
||||
"tag": "Religion"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip_260-2683bp5r",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "tvBroadcast",
|
||||
"title": "Gerry Spence",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Kyle",
|
||||
"lastName": "Nicholoff",
|
||||
"creatorType": "director"
|
||||
},
|
||||
{
|
||||
"firstName": "Ruby",
|
||||
"lastName": "Calvert",
|
||||
"creatorType": "producer"
|
||||
},
|
||||
{
|
||||
"firstName": "Gerry",
|
||||
"lastName": "Spence",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Deborah",
|
||||
"lastName": "Hammons",
|
||||
"creatorType": "castMember"
|
||||
},
|
||||
{
|
||||
"firstName": "Deborah",
|
||||
"lastName": "Hammons",
|
||||
"creatorType": "producer"
|
||||
},
|
||||
{
|
||||
"lastName": "Wyoming PBS",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"abstractNote": "The subject of this episode is Wyoming native Gerry Spence, a best-selling author considered by many to be America's greatest trial lawyer. He sits down with Deborah Hammons to talk about his past growing up in the city of Riverton. \"Main Street, Wyoming is a documentary series exploring aspects of Wyoming's local history and culture.\"",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"episodeNumber": "605",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "Wyoming PBS",
|
||||
"programTitle": "Main Street, Wyoming",
|
||||
"rights": "Main Street, Wyoming is a public affairs presentation of Wyoming Public Television 1995 KCWC-TV",
|
||||
"runningTime": "00:29:10",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-260-2683bp5r",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "History"
|
||||
},
|
||||
{
|
||||
"tag": "Interview"
|
||||
},
|
||||
{
|
||||
"tag": "Local Communities"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip-3d6c55fdb1b",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "radioBroadcast",
|
||||
"title": "Big Bird - America's Favorite Flightless Bird",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "BirdNote",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
},
|
||||
{
|
||||
"firstName": "Bob",
|
||||
"lastName": "Sundstrom",
|
||||
"creatorType": "scriptwriter"
|
||||
}
|
||||
],
|
||||
"date": "2018-11-20",
|
||||
"abstractNote": "There’s at least one bird that nearly everyone knows on sight: Big Bird. He’s been a Sesame Street celebrity since 1969, cutting a colorful figure for pre-school fans and their parents across the world. Big Bird is really a big kid with a kind heart, who makes friends everywhere he goes. He helps children feel okay about not knowing everything because, well, Big Bird is still figuring things out himself. Like the alphabet. When Big Bird first saw the alphabet, he thought it was one really, really long word. And Michael Stein knows how to pronounce it. Have a listen!",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"place": "Seattle, Washington",
|
||||
"programTitle": "BirdNote",
|
||||
"rights": "Sounds for BirdNote stories were provided by the Macaulay Library at the Cornell Lab of Ornithology, Xeno-Canto, Martyn Stewart, Chris Peterson, John Kessler, and others. Where music was used, fair use was taken into consideration. Individual credits are found at the bottom of each transcript.",
|
||||
"runningTime": "00:01:45.195",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-3d6c55fdb1b",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Science"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog/cpb-aacip-529-df6k06z734",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "radioBroadcast",
|
||||
"title": "An Examination of Testing",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "William",
|
||||
"lastName": "Koch",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Panchita",
|
||||
"lastName": "Garrett",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Kathy",
|
||||
"lastName": "Glover",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"lastName": "KUT Longhorn Radio Network",
|
||||
"creatorType": "producer",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "1982-04-02",
|
||||
"abstractNote": "Hosts Kathy Glover and Panchita Garrett talks with Dr. William Koch, Assoc. Dir. Of the Measurement and Evaluation Center at UT Austin. They discuss the nature of standardized testing, how, when and where it is used.",
|
||||
"archive": "American Archive of Public Broadcasting (GBH and the Library of Congress)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "americanarchive.org",
|
||||
"network": "KUT Longhorn Radio Network",
|
||||
"programTitle": "The Inquiring Mind",
|
||||
"rights": "KUT, COPIES OKAY",
|
||||
"runningTime": "00:24:32",
|
||||
"url": "http://americanarchive.org/catalog/cpb-aacip-529-df6k06z734",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Education"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://americanarchive.org/catalog?q=The+Inquiring+Mind&utf8=%E2%9C%93&f[access_types][]=online",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,382 +0,0 @@
|
|||
{
|
||||
"translatorID": "1a31e4c5-22ed-4b5b-a75f-55476db29a44",
|
||||
"label": "Anarchist Library",
|
||||
"creator": "Sister Baæ'l",
|
||||
"target": "https://theanarchistlibrary\\.org/(latest|library|stats/popular|category/topic|category/author|special/index|search)",
|
||||
"minVersion": "7.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-10-25 01:31:43"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2025 Dandelion Good and the righteous Anti Toil Theologians at Iliff
|
||||
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 *****
|
||||
*/
|
||||
|
||||
/*
|
||||
***** BEGIN ATTRIBUTION BLOCK *****
|
||||
This translator was developed by Dandelion Good.
|
||||
|
||||
If you do any work on this translator, please add yourself here <3.
|
||||
*/
|
||||
|
||||
var allAttachmentTypes = {
|
||||
"Plain PDF": { ext: ".pdf", mimeType: "application/pdf" },
|
||||
"A4 PDF": { ext: ".a4.pdf", mimeType: "application/pdf" },
|
||||
"Letter PDF": { ext: ".lt.pdf", mimeType: "application/pdf" },
|
||||
EPub: { ext: ".epub", mimeType: "application/epub+zip" },
|
||||
"Printer-friendly HTML": { ext: ".html", mimeType: "text/html" },
|
||||
LaTeX: { ext: ".tex", mimeType: "application/x-tex" },
|
||||
"Plain Text": { ext: ".muse", mimeType: "text/plain" },
|
||||
"Source Zip:": { ext: ".zip", mimeType: "application/zip" },
|
||||
Snapshot: { ext: "snapshot", mimeType: "text/html" }
|
||||
};
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll("a.list-group-item");
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(text(row, "strong"));
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
// ToDo: get fancier here, allow other types
|
||||
let item = new Zotero.Item('manuscript');
|
||||
|
||||
// These may be expanded on in the future
|
||||
let attachmentTypes = {
|
||||
PDF: allAttachmentTypes["Plain PDF"],
|
||||
};
|
||||
|
||||
item.url = url;
|
||||
item.language = attr(doc, "html", "lang");
|
||||
|
||||
let itemType = attr(doc, '[property~="og:type"]', 'content');
|
||||
let tagNodeList = doc.querySelectorAll(`[property~="og:${itemType}:tag"]`);
|
||||
let description = attr(doc, '[property~="og:description"]', 'content');
|
||||
let author = attr(doc, `[property~="og:${itemType}:author"]`, 'content');
|
||||
item.creators.push(ZU.cleanAuthor(author, "author"));
|
||||
|
||||
if (description) {
|
||||
item.description = description;
|
||||
// misses https://theanarchistlibrary.org/library/leo-tolstoy-the-complete-works-of-count-tolstoy-volume-12
|
||||
let re = /(?<=[Tt]ranslated(?: +to [Ee]nglish)? +by ).*$/u;
|
||||
let translatedMatch = description.match(re);
|
||||
if (translatedMatch) {
|
||||
item.creators.push(ZU.cleanAuthor(translatedMatch[0], "translator", translatedMatch[0].includes(",")));
|
||||
}
|
||||
}
|
||||
|
||||
let date = getPreambleVal(doc, "textdate");
|
||||
let notes = getPreambleVal(doc, "preamblenotes");
|
||||
// misses link here: https://theanarchistlibrary.org/library/margaret-killjoy-it-s-time-to-build-resilient-communities
|
||||
let source = getPreambleVal(doc, "preamblesrc");
|
||||
|
||||
for (let tagNode of tagNodeList) {
|
||||
item.tags.push({ tag: tagNode.content });
|
||||
}
|
||||
|
||||
let title = attr(doc.head, '[property~="og:title"][content]', 'content');
|
||||
item.title = title;
|
||||
item.date = date;
|
||||
if (notes) {
|
||||
item.notes.push({ note: ZU.trimInternal(notes) });
|
||||
}
|
||||
if (source) {
|
||||
item.notes.push({ note: `Source: ${ZU.trimInternal(source)}` });
|
||||
}
|
||||
|
||||
for (let [typeName, typeInfo] of Object.entries(attachmentTypes)) {
|
||||
let attachment = {
|
||||
title: typeName,
|
||||
url: `${doc.location.href}${typeInfo.ext}`,
|
||||
mimeType: typeInfo.mimeType
|
||||
};
|
||||
|
||||
if (typeInfo.ext == "snapshot") {
|
||||
attachment.document = doc;
|
||||
}
|
||||
|
||||
item.attachments.push(attachment);
|
||||
}
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
var libraryRe = /library\//;
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (libraryRe.test(url)) {
|
||||
return 'manuscript';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPreambleVal(doc, id) {
|
||||
let preamble = doc.body.querySelector("div#preamble");
|
||||
return text(preamble, `div#${id}`).slice(text(preamble, `span#${id}-label`).length);
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/library/abel-paz-durruti-in-the-spanish-revolution",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "manuscript",
|
||||
"title": "Durruti in the Spanish Revolution",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Abel",
|
||||
"lastName": "Paz"
|
||||
},
|
||||
{
|
||||
"creatorType": "translator",
|
||||
"firstName": "Chuck",
|
||||
"lastName": "Morse"
|
||||
}
|
||||
],
|
||||
"date": "1996",
|
||||
"url": "https://theanarchistlibrary.org/library/abel-paz-durruti-in-the-spanish-revolution",
|
||||
"language": "en",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Buenaventura Durruti"
|
||||
},
|
||||
{
|
||||
"tag": "Spanish Revolution"
|
||||
},
|
||||
{
|
||||
"tag": "biography"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "Translated to English by Chuck Morse"
|
||||
},
|
||||
{
|
||||
"note": "Source: Published by AK Press in 2006 (please support the publisher!). Retrieved on 19th September 2020 from https://libcom.org/library/durruti-spanish-revolution"
|
||||
}
|
||||
],
|
||||
"seeAlso": [],
|
||||
"libraryCatalog": "Anarchist Library"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/library/errico-malatesta-the-general-strike-and-the-insurrection-in-italy",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "manuscript",
|
||||
"title": "The General Strike and the Insurrection in Italy",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Errico",
|
||||
"lastName": "Malatesta"
|
||||
}
|
||||
],
|
||||
"date": "1914",
|
||||
"language": "en",
|
||||
"url": "https://theanarchistlibrary.org/library/errico-malatesta-the-general-strike-and-the-insurrection-in-italy",
|
||||
"libraryCatalog": "Anarchist Library",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "General Strike"
|
||||
},
|
||||
{
|
||||
"tag": "Italy"
|
||||
},
|
||||
{
|
||||
"tag": "history"
|
||||
},
|
||||
{
|
||||
"tag": "insurrection"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "Freedom (London) 28, no. 303 (July 1914). In the article, written shortly after his escape from Italy and return to London, Malatesta provides an account of the Red Week, which broke out on 7 June 1914 in Ancona, where Malatesta lived."
|
||||
},
|
||||
{
|
||||
"note": "Source: The Method of Freedom: An Errico Malatesta Reader, edited by Davide Turcato, translated by Paul Sharkey."
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/library/ulrika-holgersson-britta-grondahl",
|
||||
"items": [
|
||||
{
|
||||
"title": "Britta Gröndahl",
|
||||
"itemType": "manuscript",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ulrika",
|
||||
"lastName": "Holgersson",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Alexia",
|
||||
"lastName": "Grosjean",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "Translated by Alexia Grosjean."
|
||||
},
|
||||
{
|
||||
"note": "Source: Retrieved on 11th March 2025 from www.skbl.se"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Sweden"
|
||||
},
|
||||
{
|
||||
"tag": "biography"
|
||||
}
|
||||
],
|
||||
"date": "2018-03-08",
|
||||
"seeAlso": [],
|
||||
"libraryCatalog": "Anarchist Library",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"url": "https://theanarchistlibrary.org/library/ulrika-holgersson-britta-grondahl",
|
||||
"language": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/library/emile-armand-the-forerunners-of-anarchism",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "manuscript",
|
||||
"title": "The Forerunners of Anarchism",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Emile",
|
||||
"lastName": "Armand"
|
||||
},
|
||||
{
|
||||
"creatorType": "translator",
|
||||
"firstName": "",
|
||||
"lastName": "Reddebrek"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "Translated by Reddebrek."
|
||||
},
|
||||
{
|
||||
"note": "Source: Provided by the translator."
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "history"
|
||||
},
|
||||
{
|
||||
"tag": "individualism"
|
||||
},
|
||||
{
|
||||
"tag": "proto-anarchism"
|
||||
}
|
||||
],
|
||||
"date": "1933",
|
||||
"seeAlso": [],
|
||||
"libraryCatalog": "Anarchist Library",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"url": "https://theanarchistlibrary.org/library/emile-armand-the-forerunners-of-anarchism",
|
||||
"language": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/search?query=kropotkin",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://theanarchistlibrary.org/search?query=spirit",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,164 +1,237 @@
|
|||
{
|
||||
"translatorID": "0dda3f89-15de-4479-987f-cc13f1ba7999",
|
||||
"label": "Ancestry.com US Federal Census",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?ancestry\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"creator": "Elena Razlogova",
|
||||
"target": "^https?://search\\.ancestry\\.com/.*(usfedcen|1890orgcen|1910uscenindex)",
|
||||
"minVersion": "1.0.0b4.r1",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcibv",
|
||||
"lastUpdated": "2021-07-22 19:20:28"
|
||||
"browserSupport": "g",
|
||||
"lastUpdated": "2015-06-02 10:57:09"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (text(doc, '.pageTitle .pageIntro a').includes('United States Federal Census')) {
|
||||
return "bookSection";
|
||||
var namespace = doc.documentElement.namespaceURI;
|
||||
var nsResolver = namespace ? function(prefix) {
|
||||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
var result = doc.evaluate('//div[@class="g_container"]/div[@class="g_panelWrap"]/div[@class="g_panelCore"]/div[@class="s_container"]/div[@class="p_rsltList"]', doc, nsResolver,
|
||||
XPathResult.ANY_TYPE, null).iterateNext();
|
||||
|
||||
var rows = doc.evaluate('//div[@class="g_container"]/div[@class="g_panelWrap"]/div[@class="g_panelCore"]/div[@class="s_container"]/div[@class="p_rsltList"]/table/tbody/tr[@class="tblrow record"]',
|
||||
doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var row;
|
||||
while (row = rows.iterateNext()) {
|
||||
links = doc.evaluate('.//a', row, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var linkNo=0;
|
||||
while (link=links.iterateNext()) {
|
||||
linkNo=linkNo+1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (result && linkNo == 2) {
|
||||
return "multiple";
|
||||
} else {
|
||||
var indivRe = /indiv=1/;
|
||||
var m = indivRe.exec(doc.location.href);
|
||||
var indiv = 0;
|
||||
if (m) {
|
||||
indiv = 1;
|
||||
}
|
||||
|
||||
checkURL = doc.location.href.replace("pf=", "");
|
||||
if (doc.location.href == checkURL && indiv == 1) {
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this US Federal Census scraper is a hack - so far there is no proper item type in Zotero for this kind of data (added to trac as a low priority ticket)
|
||||
// this scraper creates proper citation for the census as a whole (should be cited as book)
|
||||
// but also adds name, city, and state for a particular individual to the citation to make scanning for names & places easier in the middle pane
|
||||
// (that's why the resulting item type is a book section)
|
||||
// it also adds all searchable text as a snapshot and a scan of the census record as an image
|
||||
|
||||
function scrape(doc) {
|
||||
var namespace = doc.documentElement.namespaceURI;
|
||||
var nsResolver = namespace ? function(prefix) {
|
||||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
// get initial census data; a proper census record item type should have separate fields for all of these except perhaps dbid
|
||||
var info = doc.evaluate('//div[@class="facets"][@id="connect"]/div[@class="g_box"]/p/a',
|
||||
doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext();
|
||||
|
||||
if (info) {
|
||||
|
||||
info = info.toString();
|
||||
var data = new Array();
|
||||
var parts = info.split(/[?&]/);
|
||||
for (var i=0; i<parts.length; i++) {
|
||||
var part = parts[i];
|
||||
var index = part.indexOf("=");
|
||||
if (index !== -1) {
|
||||
data[part.substr(0, index)] = part.substr(index+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.ln) {
|
||||
var lastName = data.ln.replace(/\+/g, " ");
|
||||
var firstName = data.fn.replace(/\+/g, " ");
|
||||
} else {
|
||||
var lastName = data.fn.replace(/\+/g, " ");
|
||||
var firstName = "";
|
||||
}
|
||||
var dOb = data.by; // this does not get saved yet because no field is available; the info is in the snapshot
|
||||
if (data.rfd) {
|
||||
var yearRe = /([0-9]{4})/;
|
||||
var m = yearRe.exec(data.rfd);
|
||||
if (m) {
|
||||
var year = m[1];
|
||||
}
|
||||
} else { var year = data.ry; }
|
||||
var state = data.rs.replace(/\+/g, " ");
|
||||
var county = data.rcnty.replace(/\+/g, " "); // this does not get saved yet because no field is available; the info is in the snapshot
|
||||
var city = data.rcty.replace(/\+/g, " ");
|
||||
var dbid = data.dbid;
|
||||
}
|
||||
|
||||
// set census number for citation - let me know if this can be done in a better way
|
||||
var censusYear = 0;
|
||||
var censusNo = "";
|
||||
var censusNos = new Array("1790", "First", "1800", "Second", "1810", "Third", "1820", "Fourth", "1830", "Fifth", "1840", "Sixth", "1850", "Seventh", "1860", "Eighth", "1870", "Ninth",
|
||||
"1880", "Tenth", "1890", "Eleventh", "1900", "Twelfth", "1910", "Thirteenth", "1920", "Fourteenth", "1930", "Fifteenth")
|
||||
for (var i in censusNos) {
|
||||
if (censusYear == 1) { censusNo = censusNos[i] };
|
||||
if (censusNos[i] == year) { censusYear = 1 } else {censusYear= 0 };
|
||||
}
|
||||
|
||||
//begin adding item
|
||||
var newItem = new Zotero.Item("bookSection");
|
||||
newItem.title = city+", "+state; // this is not proper citation but is needed to easily scan for placenames in middle pane
|
||||
newItem.publicationTitle = censusNo+" Census of the United States, "+year;
|
||||
newItem.publisher = "National Archives and Records Administration";
|
||||
newItem.place = "Washington, DC";
|
||||
newItem.date = year;
|
||||
|
||||
// get snapshot with all searchable text and a simplified link to the record for the URL field
|
||||
var dbRe = /db=([0-9a-z]+)/;
|
||||
var m = dbRe.exec(doc.location.href);
|
||||
if (m) {
|
||||
db = m[1];
|
||||
}
|
||||
var snapshotRe = /\&h=([0-9]+)/;
|
||||
var m = snapshotRe.exec(doc.location.href);
|
||||
if (m) {
|
||||
snapshotURL = "http://search.ancestry.com/cgi-bin/sse.dll?db="+db+"&indiv=1&pf=1&h="+m[1];
|
||||
newItem.attachments.push({title:"Ancestry.com Snapshot", mimeType:"text/html", url:snapshotURL, snapshot:true});
|
||||
cleanURL = "http://search.ancestry.com/cgi-bin/sse.dll?indiv=1&db="+db+"&fh=0&h="+m[1];
|
||||
newItem.url = cleanURL;
|
||||
}
|
||||
|
||||
// add particular individual being surveyed as contributor - this is not proper citation but is needed so one could easily scan for names in middle pane
|
||||
var creator = new Array();
|
||||
creator.firstName = firstName;
|
||||
creator.lastName = lastName;
|
||||
creator.creatorType = "author";
|
||||
newItem.creators.push(creator);
|
||||
|
||||
//add proper author for citation
|
||||
var creator = new Array();
|
||||
creator.lastName = "United States of America, Bureau of the Census";
|
||||
creator.creatorType = "contributor";
|
||||
newItem.creators.push(creator);
|
||||
|
||||
// get scan of the census image
|
||||
var scanInfo = doc.evaluate('//div[@id="record-main"]/table[@class="p_recTable"]/tbody/tr/td[2][@class="recordTN"]/a',
|
||||
doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext();
|
||||
|
||||
if (scanInfo) {
|
||||
var scanRe = /iid=([A-Z0-9_-]+)/;
|
||||
var m = scanRe.exec(scanInfo);
|
||||
if (m) {
|
||||
scanURL = "http://content.ancestry.com/Browse/print_u.aspx?dbid="+dbid+"&iid="+m[1];
|
||||
Zotero.debug("scan url: " + scanURL);
|
||||
}
|
||||
}
|
||||
|
||||
if (scanURL){
|
||||
Zotero.Utilities.HTTP.doGet(scanURL, function(text) {
|
||||
Zotero.debug("running doGet");
|
||||
Zotero.debug(text);
|
||||
var imageRe = /950 src="([^"]+)"/;
|
||||
var m = imageRe.exec(text);
|
||||
if (m) {
|
||||
imageURL = m[1];
|
||||
Zotero.debug("image url: " + imageURL);
|
||||
newItem.attachments.push({title:"Ancestry.com Image", mimeType:"image/jpeg", url:imageURL, snapshot:true});
|
||||
}
|
||||
|
||||
newItem.complete();
|
||||
Zotero.done();
|
||||
});
|
||||
} else {
|
||||
newItem.complete();
|
||||
Zotero.done();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
scrape(doc, url);
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
let item = new Zotero.Item('bookSection');
|
||||
|
||||
item.title = text(doc, '.pageTitle span');
|
||||
let [date, place, roll, page] = doc.querySelectorAll('.sourceText em'); // not ideal
|
||||
item.bookTitle = text(doc, '.pageTitle .pageIntro a').trim()
|
||||
+ ` [${place.textContent}]`;
|
||||
item.publisher = 'National Archives and Records Administration';
|
||||
// technically the Census is published 72 years after it's taken, but citing
|
||||
// that way doesn't seem to be the convention.
|
||||
item.date = date.textContent;
|
||||
item.pages = `${page.textContent} (roll ${roll.textContent})`;
|
||||
item.archive = 'Ancestry.com';
|
||||
item.url = url.replace(/[?#].*/, '');
|
||||
|
||||
let recordTable = doc.querySelector('#recordServiceData');
|
||||
if (recordTable) {
|
||||
recordTable = recordTable.cloneNode(true);
|
||||
var resultsRegexp = /&h=/;
|
||||
if (resultsRegexp.test(url)) {
|
||||
scrape(doc);
|
||||
} else {
|
||||
var namespace = doc.documentElement.namespaceURI;
|
||||
var nsResolver = namespace ? function(prefix) {
|
||||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
let familyMembers = recordTable.querySelector('.tableContainerRow');
|
||||
if (familyMembers) familyMembers.remove();
|
||||
|
||||
item.notes.push({
|
||||
note: ZU.trimInternal(recordTable.outerHTML)
|
||||
});
|
||||
}
|
||||
|
||||
let imageSrc = attr(doc, '.photo.clickable img', 'src');
|
||||
let dbId = imageSrc.match(/\/namespaces\/([^/]+)/)[1];
|
||||
let imageId = imageSrc.match(/([^/]+)\.jpg/)[1];
|
||||
ZU.doGet(
|
||||
`/imageviewer/api/media/token?dbId=${dbId}&imageId=${imageId}`,
|
||||
function (respText) {
|
||||
try {
|
||||
let json = JSON.parse(respText);
|
||||
item.attachments.push({
|
||||
title: 'Census Record',
|
||||
mimeType: 'image/jpeg',
|
||||
url: json.imageDownloadUrl
|
||||
});
|
||||
item.complete();
|
||||
}
|
||||
catch (_) {
|
||||
item.complete(); // whatever, this is fragile
|
||||
}
|
||||
// get census year for links to items
|
||||
var yearRe = /db=([0-9]+)/;
|
||||
var m = yearRe.exec(doc.location.href);
|
||||
if (m) {
|
||||
year = m[1];
|
||||
}
|
||||
|
||||
var dbRe = /db=([0-9a-z]+)/;
|
||||
var m = dbRe.exec(doc.location.href);
|
||||
if (m) {
|
||||
db = m[1];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ancestry.com/discoveryui-content/view/131479739:2442?tid=&pid=&queryId=2a5ea51171527460c8a3755eb4b3fc1e&_phsrc=BYN5&_phstart=successSource",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Albert Einstein",
|
||||
"creators": [],
|
||||
"date": "1940",
|
||||
"archive": "Ancestry.com",
|
||||
"bookTitle": "1940 United States Federal Census [Princeton, Mercer, New Jersey]",
|
||||
"libraryCatalog": "Ancestry.com US Federal Census",
|
||||
"pages": "10B (roll m-t0627-02357)",
|
||||
"publisher": "National Archives and Records Administration",
|
||||
"url": "https://www.ancestry.com/discoveryui-content/view/131479739:2442",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Census Record",
|
||||
"mimeType": "image/jpeg"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<table id=\"recordServiceData\" class=\"table tableHorizontal tableHorizontalRuled\"> <tbody> <tr> <th>Name:</th> <td> Albert Einstein </td> </tr> <tr> <th>Respondent:</th> <td> Yes </td> </tr> <tr> <th>Age:</th> <td> 61 </td> </tr> <tr> <th>Estimated Birth Year:</th> <td> <span class=\"srchHit\"> <span title=\"Alternate values for this record\" class=\"altValue\">[abt 1879]</span> </span> <span title=\"This value was member submitted. Click to see details.\" class=\"altValue\"> [<button class=\"link correction\" data-tracking-event=\"content : correction clicked\">14 Mar 1879</button>] </span> </td> </tr> <tr> <th>Gender:</th> <td> Male </td> </tr> <tr> <th>Race:</th> <td> White </td> </tr> <tr> <th>Birthplace:</th> <td> Germany </td> </tr> <tr> <th>Marital Status:</th> <td> Widowed </td> </tr> <tr> <th>Relation to Head of House:</th> <td> Head </td> </tr> <tr> <th>Home in 1940:</th> <td> Princeton, Mercer, New Jersey </td> </tr> <tr> <th>Map of Home in 1940:</th> <td> <button type=\"button\" title=\"View map\" class=\"link mapLink\" data-modal-title=\"Princeton, Mercer, New Jersey\" data-place-names=\"Princeton,Mercer,New Jersey\" data-tracking-event=\"content : map link clicked\">Princeton, Mercer, New Jersey</button> </td> </tr> <tr> <th>Street:</th> <td> Mercer - Street </td> </tr> <tr> <th>House Number:</th> <td> 112 </td> </tr> <tr> <th>Farm:</th> <td> No </td> </tr> <tr> <th>Inferred Residence in 1935:</th> <td> Princeton, Mercer, New Jersey </td> </tr> <tr> <th>Residence in 1935:</th> <td> Princeton </td> </tr> <tr> <th>Resident on farm in 1935:</th> <td> No </td> </tr> <tr> <th>Citizenship:</th> <td> Having first papers </td> </tr> <tr> <th>Sheet Number:</th> <td> 10B </td> </tr> <tr> <th>Number of Household in Order of Visitation:</th> <td> 267 </td> </tr> <tr> <th>Occupation:</th> <td> Pychies Professor </td> </tr> <tr> <th>Industry:</th> <td> Private School </td> </tr> <tr> <th>House Owned or Rented:</th> <td> Owned </td> </tr> <tr> <th>Value of Home or Monthly Rental if Rented:</th> <td> 22000 </td> </tr> <tr> <th>Attended School or College:</th> <td> No </td> </tr> <tr> <th>Highest Grade Completed:</th> <td> College, 5th or subsequent year </td> </tr> <tr> <th>Hours Worked Week Prior to Census:</th> <td> 44 </td> </tr> <tr> <th>Class of Worker:</th> <td> Wage or salary worker in private work </td> </tr> <tr> <th>Weeks Worked in 1939:</th> <td> 52 </td> </tr> <tr> <th>Income:</th> <td> 5000 </td> </tr> <tr> <th>Income Other Sources:</th> <td> Yes </td> </tr> <tr> <th>Neighbors:</th> <td> <button type=\"button\" title=\"View others on page\" class=\"link neighborsLink\" data-modal-title=\"View others on page\" data-image-gid=\"m-t0627-02357-00675:2442\" data-tracking-event=\"content : neighbors link clicked\">View others on page</button> </td> </tr> </tbody> </table>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
//select items
|
||||
var items = new Array();
|
||||
var listElts = doc.evaluate('//tr[@class="tblrow record keySelect"] | //tr[@class="tblrow record"] | //tr[@class="tblrowalt record"]',
|
||||
doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var recid;
|
||||
var link;
|
||||
var name;
|
||||
while (listElt = listElts.iterateNext()) {
|
||||
recInfo = doc.evaluate('.//a', listElt, nsResolver, XPathResult.ANY_TYPE, null).iterateNext();
|
||||
var recidRe = /recid=([0-9]+)/;
|
||||
var m = recidRe.exec(recInfo);
|
||||
if (m) {
|
||||
recid = m[1];
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ancestry.com/discoveryui-content/view/18443183:7884?tid=&pid=&queryId=283135001368664572d798e1a9012c06&_phsrc=oJW436&_phstart=successSource",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Pauline Rosenboom",
|
||||
"creators": [],
|
||||
"date": "1910",
|
||||
"archive": "Ancestry.com",
|
||||
"bookTitle": "1910 United States Federal Census [Bronx Assembly District 34, New York, New York]",
|
||||
"libraryCatalog": "Ancestry.com US Federal Census",
|
||||
"pages": "4A (roll T624_1001)",
|
||||
"publisher": "National Archives and Records Administration",
|
||||
"url": "https://www.ancestry.com/discoveryui-content/view/18443183:7884",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Census Record",
|
||||
"mimeType": "image/jpeg"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<table id=\"recordServiceData\" class=\"table tableHorizontal tableHorizontalRuled\"> <tbody> <tr> <th>Name:</th> <td> <span class=\"srchHit\">Pauline Rosenboom <span title=\"Alternate name for this record\" class=\"altValue\">[Pauline Rosenbaum]</span> </span> </td> </tr> <tr> <th>Age in 1910:</th> <td> 51 </td> </tr> <tr> <th>Birth Date:</th> <td> <span class=\"srchHit\">1859 <span title=\"Alternate date for this record\" class=\"altValue\">[1859]</span> </span> </td> </tr> <tr> <th>Birthplace:</th> <td> Austria </td> </tr> <tr> <th>Home in 1910:</th> <td> Bronx Assembly District 34, New York, New York, USA </td> </tr> <tr> <th>Street:</th> <td> est Clenton Ave </td> </tr> <tr> <th>Race:</th> <td> White </td> </tr> <tr> <th>Gender:</th> <td> Female </td> </tr> <tr> <th>Immigration Year:</th> <td> 1887 </td> </tr> <tr> <th>Relation to Head of House:</th> <td> Mother-in-law </td> </tr> <tr> <th>Marital Status:</th> <td> Widowed </td> </tr> <tr> <th>Father's Birthplace:</th> <td> Austria </td> </tr> <tr> <th>Mother's Birthplace:</th> <td> Austria </td> </tr> <tr> <th>Native Tongue:</th> <td> English </td> </tr> <tr> <th>Attended School:</th> <td> No </td> </tr> <tr> <th>Able to read:</th> <td> Yes </td> </tr> <tr> <th>Able to Write:</th> <td> Yes </td> </tr> <tr> <th>Number of Children Born:</th> <td> 7 </td> </tr> <tr> <th>Number of Children Living:</th> <td> 5 </td> </tr> <tr> <th>Neighbors:</th> <td> <button type=\"button\" title=\"View others on page\" class=\"link neighborsLink\" data-modal-title=\"View others on page\" data-image-gid=\"4450082_00484:7884\" data-tracking-event=\"content : neighbors link clicked\">View others on page</button> </td> </tr> </tbody> </table>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
link = "http://search.ancestry.com/cgi-bin/sse.dll?indiv=1&db="+db+"&fh=0&h="+recid;
|
||||
name = doc.evaluate('.//span[@class="srchHit"]', listElt, nsResolver, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
items[link] = Zotero.Utilities.trimInternal(name);
|
||||
}
|
||||
|
||||
items = Zotero.selectItems(items);
|
||||
if (!items) return true;
|
||||
|
||||
var urls = new Array();
|
||||
for (var i in items) {
|
||||
urls.push(i);
|
||||
}
|
||||
|
||||
Zotero.Utilities.processDocuments(urls, scrape, function() { Zotero.done(); });
|
||||
Zotero.wait();
|
||||
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"translatorID": "5f22bd25-5b70-11e1-bb1d-c4f24aa18c1e",
|
||||
"label": "Annual Reviews",
|
||||
"creator": "Aurimas Vinckevicius and Abe Jellinek",
|
||||
"creator": "Aurimas Vinckevicius",
|
||||
"target": "^https?://[^/]*annualreviews\\.org(:[\\d]+)?(?=/)[^?]*(/(toc|journal|doi)/|showMost(Read|Cited)Articles|doSearch)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
|
|
@ -9,11 +9,11 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-08-02 12:48:22"
|
||||
"lastUpdated": "2017-01-01 15:19:19"
|
||||
}
|
||||
|
||||
/**
|
||||
Copyright (c) 2012-2021 Aurimas Vinckevicius and Abe Jellinek
|
||||
Copyright (c) 2012 Aurimas Vinckevicius
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU Affero General Public License
|
||||
|
|
@ -30,33 +30,35 @@
|
|||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// add using BibTex
|
||||
//add using BibTex
|
||||
function addByBibTex(doi, tags) {
|
||||
var baseUrl = 'http://www.annualreviews.org';
|
||||
var risRequest = baseUrl + '/action/downloadCitation';
|
||||
var articleUrl = baseUrl + '/doi/abs/' + doi;
|
||||
var pdfUrl = baseUrl + '/doi/pdf/' + doi;
|
||||
|
||||
var postData = 'include=abs&direct=on&submit=Download+chapter+metadata&downloadFileName=citation'
|
||||
+ '&format=bibtex' // bibtex
|
||||
+ '&doi=' + encodeURIComponent(doi);
|
||||
var postData = 'include=abs&direct=on&submit=Download+chapter+metadata&downloadFileName=citation' +
|
||||
'&format=bibtex' + //bibtex
|
||||
'&doi=' + encodeURIComponent(doi);
|
||||
|
||||
Zotero.Utilities.HTTP.doPost(risRequest, postData, function (text) {
|
||||
Zotero.Utilities.HTTP.doPost(risRequest, postData, function(text) {
|
||||
var translator = Zotero.loadTranslator('import');
|
||||
translator.setTranslator('9cb70025-a888-4a29-a210-93ec52da40d4'); // bibtex
|
||||
translator.setTranslator('9cb70025-a888-4a29-a210-93ec52da40d4'); //bibtex
|
||||
translator.setString(text);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
// title is sometimes in all caps
|
||||
if (item.title == item.title.toUpperCase()) item.title = ZU.capitalizeTitle(item.title, true);
|
||||
if (item.abstractNote) {
|
||||
item.abstractNote = item.abstractNote.replace(/^...?Abstract/, "");
|
||||
translator.setHandler('itemDone', function(obj, item) {
|
||||
//title is sometimes in all caps
|
||||
if (item.title == item.title.toUpperCase())
|
||||
item.title = ZU.capitalizeTitle(item.title, true);
|
||||
if (item.abstractNote){
|
||||
item.abstractNote = item.abstractNote.replace(/^...?Abstract/, "")
|
||||
}
|
||||
// add tags
|
||||
//add tags
|
||||
if (tags) {
|
||||
item.tags = tags;
|
||||
}
|
||||
|
||||
// set PDF file
|
||||
//set PDF file
|
||||
item.attachments = [{
|
||||
url: pdfUrl,
|
||||
title: 'Full Text PDF',
|
||||
|
|
@ -71,52 +73,60 @@ function addByBibTex(doi, tags) {
|
|||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (/\/doi\/(abs|full|pdf|10\.)/.test(url)) {
|
||||
var title = doc.title.toLowerCase();
|
||||
|
||||
if ( url.match(/\/doi\/(abs|full|pdf)\//) ) {
|
||||
|
||||
return 'journalArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
|
||||
} else if ( title.match('- table of contents -') ||
|
||||
title.match('- most downloaded reviews') ||
|
||||
title.match('- most cited reviews') ||
|
||||
title.match('- forthcoming -') ||
|
||||
title.match('search results') ||
|
||||
url.match('/journal/') ) { //individual journal home page
|
||||
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.articleBoxWrapper');
|
||||
if (!rows.length) rows = doc.querySelectorAll('.teaser');
|
||||
for (let row of rows) {
|
||||
let doi = attr(row, 'input[name="doi"]', 'value');
|
||||
if (!doi) doi = ZU.cleanDOI(attr(row, 'h2 > a', 'href'));
|
||||
let title = ZU.trimInternal(text(row, 'h2 > a'));
|
||||
if (!doi || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[doi] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) Object.keys(items).forEach(addByBibTex);
|
||||
if ( detectWeb(doc, url) == 'multiple' ) {
|
||||
var articles = Zotero.Utilities.xpath(doc, '//div[@class="articleBoxWrapper"]');
|
||||
var selectList = new Object();
|
||||
var doi, title, article;
|
||||
for ( var i in articles ) {
|
||||
article = articles[i];
|
||||
doi = Zotero.Utilities.xpath(article, './div[@class="articleCheck"]/input');
|
||||
title = Zotero.Utilities.xpathText(article, './div[@class="articleBoxMeta"]/h2/a');
|
||||
if ( doi && doi[0].value && title) {
|
||||
selectList[doi[0].value] = title;
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.selectItems(selectList, function(selectedItems) {
|
||||
if (selectedItems == null) return true;
|
||||
for (var item in selectedItems) {
|
||||
addByBibTex(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var match = url.match(/\/(?:abs|full|pdf)\/([^?]+)/);
|
||||
if (match) {
|
||||
//get keywords before we leave
|
||||
var tags, keywords = ZU.xpath(doc,
|
||||
'//form[@id="frmQuickSearch"]\
|
||||
/div[@class="pageTitle" and contains(text(), "KEYWORD")]\
|
||||
/following-sibling::div/span[@class="data"]');
|
||||
if (keywords) {
|
||||
tags = new Array();
|
||||
for (var i=0, n=keywords.length; i<n; i++) {
|
||||
tags.push(keywords[i].textContent.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url) {
|
||||
// match both /doi/abs/10.1146 (etc.) and /doi/10.1146
|
||||
var match = url.match(/\/(?:doi)\/(?:abs|full|pdf)?\/?([^?]+)/);
|
||||
if (match) {
|
||||
let tags = attr(doc, 'meta[name="dc.Subject"]', 'content')
|
||||
.split('; ')
|
||||
.map(tag => ({ tag }));
|
||||
addByBibTex(match[1], tags);
|
||||
addByBibTex(match[1], tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +159,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.annualreviews.org/doi/abs/10.1146/annurev.biophys.29.1.545?prevSearch=&searchHistoryKey=",
|
||||
"url": "http://www.annualreviews.org/doi/abs/10.1146/annurev.biophys.29.1.545?prevSearch=&searchHistoryKey=",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -180,7 +190,7 @@ var testCases = [
|
|||
"libraryCatalog": "Annual Reviews",
|
||||
"pages": "545-576",
|
||||
"publicationTitle": "Annual Review of Biophysics and Biomolecular Structure",
|
||||
"url": "https://doi.org/10.1146/annurev.biophys.29.1.545",
|
||||
"url": "http://dx.doi.org/10.1146/annurev.biophys.29.1.545",
|
||||
"volume": "29",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -189,21 +199,11 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "ADF/cofilins"
|
||||
},
|
||||
{
|
||||
"tag": "Arp2/3 complex"
|
||||
},
|
||||
{
|
||||
"tag": "WASp"
|
||||
},
|
||||
{
|
||||
"tag": "cell motility"
|
||||
},
|
||||
{
|
||||
"tag": "profilin"
|
||||
}
|
||||
"ADF/cofilins",
|
||||
"Arp2/3 complex",
|
||||
"WASp",
|
||||
"cell motility",
|
||||
"profilin"
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
|
|
@ -214,116 +214,6 @@ var testCases = [
|
|||
"type": "web",
|
||||
"url": "http://www.annualreviews.org/toc/anchem/5/1",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.annualreviews.org/toc/linguistics/current",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.annualreviews.org/doi/abs/10.1146/annurev-linguistics-081720-111352",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Linguistics Then and Now: Some Personal Reflections",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Noam",
|
||||
"lastName": "Chomsky",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021",
|
||||
"DOI": "10.1146/annurev-linguistics-081720-111352",
|
||||
"abstractNote": "By mid-twentieth century, a working consensus had been reached in the linguistics community, based on the great achievements of preceding years. Synchronic linguistics had been established as a science, a “taxonomic” science, with sophisticated procedures of analysis of data. Taxonomic science has limits. It does not ask “why?” The time was ripe to seek explanatory theories, using insights provided by the theory of computation and studies of explanatory depth. That effort became the generative enterprise within the biolinguistics framework. Tensions quickly arose: The elements of explanatory theories (generative grammars) were far beyond the reach of taxonomic procedures. The structuralist principle that language is a matter of training and habit, extended by analogy, was unsustainable. More generally, the mood of “virtually everything is known” became “almost nothing is understood,” a familiar phenomenon in the history of science, opening a new and exciting era for a flourishing discipline.",
|
||||
"issue": "1",
|
||||
"itemID": "doi:10.1146/annurev-linguistics-081720-111352",
|
||||
"libraryCatalog": "Annual Reviews",
|
||||
"pages": "1-11",
|
||||
"publicationTitle": "Annual Review of Linguistics",
|
||||
"shortTitle": "Linguistics Then and Now",
|
||||
"url": "https://doi.org/10.1146/annurev-linguistics-081720-111352",
|
||||
"volume": "7",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "autobiography"
|
||||
},
|
||||
{
|
||||
"tag": "biolinguistics program"
|
||||
},
|
||||
{
|
||||
"tag": "explanatory linguistic theory"
|
||||
},
|
||||
{
|
||||
"tag": "explanatory theories"
|
||||
},
|
||||
{
|
||||
"tag": "generative enterprise"
|
||||
},
|
||||
{
|
||||
"tag": "history of linguistics"
|
||||
},
|
||||
{
|
||||
"tag": "history of science"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.annualreviews.org/doi/10.1146/annurev-physchem-040513-103712",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Phase Separation in Bulk Heterojunctions of Semiconducting Polymers and Fullerenes for Photovoltaics",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Neil D.",
|
||||
"lastName": "Treat",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Michael L.",
|
||||
"lastName": "Chabinyc",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"DOI": "10.1146/annurev-physchem-040513-103712",
|
||||
"abstractNote": "Thin-film solar cells are an important source of renewable energy. The most efficient thin-film solar cells made with organic materials are blends of semiconducting polymers and fullerenes called the bulk heterojunction (BHJ). Efficient BHJs have a nanoscale phase-separated morphology that is formed during solution casting. This article reviews recent work to understand the nature of the phase-separation process resulting in the formation of the domains in polymer-fullerene BHJs. The BHJ is now viewed as a mixture of polymer-rich, fullerene-rich, and mixed polymer-fullerene domains. The formation of this structure can be understood through fundamental knowledge of polymer physics. The implications of this structure for charge transport and charge generation are given.",
|
||||
"extra": "PMID: 24689796",
|
||||
"issue": "1",
|
||||
"itemID": "doi:10.1146/annurev-physchem-040513-103712",
|
||||
"libraryCatalog": "Annual Reviews",
|
||||
"pages": "59-81",
|
||||
"publicationTitle": "Annual Review of Physical Chemistry",
|
||||
"url": "https://doi.org/10.1146/annurev-physchem-040513-103712",
|
||||
"volume": "65",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "organic electronics"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -9,13 +9,13 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-09-22 19:39:49"
|
||||
"lastUpdated": "2017-11-11 15:26:37"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2017-2021 Velősy Péter Kristóf
|
||||
Copyright © 2017 Velősy Péter Kristóf
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
|
@ -36,14 +36,16 @@
|
|||
*/
|
||||
|
||||
|
||||
//Zotero attr() and text() functions:
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('konyv')) {
|
||||
return "book";
|
||||
}
|
||||
else if (url.includes('index.php?type=search') && getSearchResults(doc, true)) {
|
||||
} else if (url.includes('index.php?type=search') && getSearchResults(doc, true)){
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -51,9 +53,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.src-result-book');
|
||||
for (let row of rows) {
|
||||
var href = attr(row, '#searchResultKonyv-csempes', 'href');
|
||||
var title = ZU.trimInternal(text(row, '.book-title-src'));
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var href = attr(rows[i], '#searchResultKonyv-csempes', 'href');
|
||||
var title = ZU.trimInternal(text(rows[i], '.book-title-src'));
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
|
|
@ -66,16 +68,22 @@ function getSearchResults(doc, checkOnly) {
|
|||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, _url) {
|
||||
function scrape(doc, url) {
|
||||
var newItem = new Zotero.Item('book');
|
||||
|
||||
newItem.title = text(doc, '[itemprop=name]', 0).trim();
|
||||
|
|
@ -100,22 +108,24 @@ function scrape(doc, _url) {
|
|||
newItem.volume = newItem.seriesNumber;
|
||||
}
|
||||
|
||||
var publisherName = text(doc, '#konyvAdatlapKiadoLink [itemprop=name]')
|
||||
|| text(doc, '[itemprop=name]', 1);
|
||||
if (publisherName) {
|
||||
newItem.publisher = publisherName;
|
||||
}
|
||||
var publisherElement = doc.querySelector('[itemprop=publisher]');
|
||||
if (publisherElement) {
|
||||
|
||||
var publisherPlace = firstText(doc, '[itemprop=address]');
|
||||
if (publisherPlace) {
|
||||
newItem.place = publisherPlace.replace('(', '').replace(')', '');
|
||||
}
|
||||
|
||||
newItem.date = firstText(doc, '[itemprop=datePublished]');
|
||||
var publisherName = text(publisherElement, '[itemprop=name]', 0);
|
||||
if (publisherName) {
|
||||
newItem.publisher = publisherName;
|
||||
}
|
||||
|
||||
newItem.numPages = firstText(doc, '[itemprop=numberOfPages]');
|
||||
var publisherPlace = text(publisherElement, '[itemprop=address]', 0);
|
||||
if (publisherPlace) {
|
||||
newItem.place = publisherPlace.replace('(', '').replace(')', '');
|
||||
}
|
||||
}
|
||||
newItem.date = text(doc, '[itemprop=datePublished]');
|
||||
|
||||
newItem.numPages = text(doc, '[itemprop=numberOfPages]', 0);
|
||||
|
||||
newItem.language = firstText(doc, '[itemprop=inLanguage]');
|
||||
newItem.language = text(doc, '[itemprop=inLanguage]', 0);
|
||||
|
||||
var isbnElement = getElementByInnerText(doc, 'th', 'ISBN:');
|
||||
if (isbnElement) {
|
||||
|
|
@ -124,26 +134,14 @@ function scrape(doc, _url) {
|
|||
|
||||
var contentsElement = doc.getElementById('tartalomFull');
|
||||
if (contentsElement) {
|
||||
newItem.notes.push({ note: contentsElement.innerText });
|
||||
newItem.notes.push({note: contentsElement.innerText});
|
||||
}
|
||||
|
||||
newItem.attachments.push({ document: doc, title: "Antikvarium.hu Snapshot", mimeType: "text/html" });
|
||||
newItem.attachments.push({document: doc, title: "Antikvarium.hu Snapshot", mimeType: "text/html" });
|
||||
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element matching the selector with non-empty text.
|
||||
*/
|
||||
function firstText(docOrElem, selector) {
|
||||
for (let elem of docOrElem.querySelectorAll(selector)) {
|
||||
let elemText = elem.textContent.trim();
|
||||
if (elemText) return elemText;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getElementByInnerText(doc, elementType, innerText) {
|
||||
var tags = doc.getElementsByTagName(elementType);
|
||||
|
||||
|
|
@ -158,8 +156,7 @@ function getElementByInnerText(doc, elementType, innerText) {
|
|||
function cleanHungarianAuthor(authorName) {
|
||||
if (authorName.includes(',')) {
|
||||
return Zotero.Utilities.cleanAuthor(authorName, 'author', true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
var author = Zotero.Utilities.cleanAuthor(authorName, 'author', false);
|
||||
var firstName = author.lastName;
|
||||
var lastName = author.firstName;
|
||||
|
|
@ -172,7 +169,7 @@ function cleanHungarianAuthor(authorName) {
|
|||
function capitalizeHungarianTitle(title) {
|
||||
title = title[0].toUpperCase() + title.substring(1).toLowerCase();
|
||||
var words = title.split(/[ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/);
|
||||
words.forEach((w) => {
|
||||
words.forEach(w => {
|
||||
if (isRomanNumeral(w)) {
|
||||
title = title.replace(w, w.toUpperCase());
|
||||
}
|
||||
|
|
@ -182,9 +179,8 @@ function capitalizeHungarianTitle(title) {
|
|||
|
||||
function isRomanNumeral(word) {
|
||||
var romanRegex = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;
|
||||
return !!word.toUpperCase().match(romanRegex);
|
||||
return word.toUpperCase().match(romanRegex) ? true : false;
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -228,53 +224,6 @@ var testCases = [
|
|||
"type": "web",
|
||||
"url": "https://www.antikvarium.hu/index.php?type=search&ksz=atlasz&reszletes=0&newSearch=1&searchstart=ksz&interfaceid=101",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.antikvarium.hu/konyv/peter-harrison-mary-harrison-misztikus-erok-51027-0",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Misztikus erők: Mistic forces/testen túli tapasztalatok",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Harrison",
|
||||
"lastName": "Peter",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Harrison",
|
||||
"lastName": "Mary",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Nóra",
|
||||
"lastName": "Rohonczi",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"ISBN": "9789637994043",
|
||||
"language": "Magyar",
|
||||
"libraryCatalog": "Antikvarium.hu",
|
||||
"numPages": "274",
|
||||
"place": "Budapest",
|
||||
"publisher": "Pesti Szalon Könyvkiadó",
|
||||
"shortTitle": "Misztikus erők",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Antikvarium.hu Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "TARTALOM\nKöszönetnyilvánítás\t3\nElőszó\t5\nBevezetés\t9\nMi a TTT?\t13\nA fény\t23\nA magaslati nézőpont\t35\nA mennyországban?\t49\nA gyógyító erő\t55\nKülönös hatóerők\t75\nÁllatok\t91\nZene\t105\nA határterület\t111\nIdőutazások\t121\nA döntés\t141\nAz ezüstzsinór\t151\nEgybeesések\t163\nA fátum\t173\nMenekülés\t193\nGyermekek\t201\nA halálfélelem legyőzése\t213\nMegérzések\t231\nAz okkultizmus veszélyei\t235\nA lélek illata\t247\nAngyalok\t257\nPozitív végkövetkeztetések\t273"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
390
AquaDocs.js
390
AquaDocs.js
|
|
@ -1,390 +0,0 @@
|
|||
{
|
||||
"translatorID": "97b65138-71b7-424f-b305-4a2161e90661",
|
||||
"label": "AquaDocs",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://aquadocs\\.org/(handle|discover|browse)",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-08-24 02:41:29"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Sebastian Karcher
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/handle/') && attr(doc, 'meta[name="DC.type"]', 'content')) {
|
||||
let type = attr(doc, 'meta[name="DC.type"]', 'content');
|
||||
// Z.debug(type);
|
||||
return getType(type);
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.main-content .description-content a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(url);
|
||||
}
|
||||
}
|
||||
|
||||
function getType(string) {
|
||||
string = string.toLowerCase();
|
||||
if (string.includes("book_section") || string.includes("chapter")) {
|
||||
return "bookSection";
|
||||
}
|
||||
else if (string.includes("book") || string.includes("monograph")) {
|
||||
return "book";
|
||||
}
|
||||
else if (string.includes("report")) {
|
||||
return "report";
|
||||
}
|
||||
else if (string.includes("proceedings") || string.includes("conference")) {
|
||||
return "conferencePaper";
|
||||
}
|
||||
else {
|
||||
return "journalArticle"; // default -- most of the catalog
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(url) {
|
||||
let xmlURL = url.replace("/handle/", "/metadata/handle/").replace(/[?#].*$/, "") + "/mets.xml";
|
||||
// Z.debug(xmlURL);
|
||||
let xmlText = await requestText(xmlURL);
|
||||
// Z.debug(xmlText)
|
||||
let translator = Zotero.loadTranslator('import');
|
||||
translator.setTranslator('2c05e2d1-a533-448f-aa20-e919584864cb'); // DIM
|
||||
translator.setString(xmlText);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
for (let attachment of item.attachments) {
|
||||
if (attachment.url && !attachment.url.startsWith("http")) {
|
||||
attachment.url = "https://aquadocs.org" + attachment.url;
|
||||
}
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/handle/1834/42391",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Upwelling phenomenon in the marine regions of Southern Central of Vietnam: a review",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Hong Long",
|
||||
"lastName": "Bui",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Minh Thu",
|
||||
"lastName": "Phan",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022",
|
||||
"ISSN": "1859-3097",
|
||||
"abstractNote": "Upwelling is an oceanographic phenomenon that involves the physical process and contributes to changes in chemistry, biology, and natural resources. So, systematically, it is the particular ecosystems of whole marine regions with the upwelling. The strong upwelling waters in South Central Regions of Vietnam have uncertain features of the East Vietnam Sea (Bien Dong) and special characteristics of a coastal upwelling area, recorded in international scientific papers in the twentieth century. Their first signals were discovered in the early 1930s through conceptual ideas. The upwelling phenomenon is officially confirmed by scientific results of marine investigations of the NAGA Expedition (1959–1961). The paper aims to review and discuss the physical from Vietnamese investigation and results since 1990s. The following factors are the most contributing to forming and developing the strong upwelling in Southern Central Waters: (1) Influence scale (Mezo- and micro-scale); (2) Forming causes and developing mechanism of upwelling phenomenon, such as monsoon, morphography, shoreline, and western boundary current system of the East Vietnam Sea; (3) Influence of the water-mass from Mekong River on the upwelling area; (4) Ecological environmental consequences; (5) Impacts of the atmospheric-oceanic interaction processes on the western EVS on upwelling. Additionally, the review has targeted findings of upwelling phenomenon mainly in Vietnamese waters based on remote sensing analysis and reanalysis data series to simulate their forming, mechanizing, fluctuating models and the impacts of upwelling in the EVS on resources and ecosystems. The coupled atmosphere-ocean models resulted the upwelling mechanisms and formation. The long-time series of upwelling phenomenon (Macroscale) were evaluated by remote sensing and reanalyzed data series. It is also providing the supplementing and detailing causes and mechanisms of upwelling formation; impacts and interactions of upwelling on marine physics and hydrodynamics (ocean vortexes, seawater temperature), biochemical (nutrients, plankton organisms), and resources (fish, seafood). Within the framework of strong upwelling waters in the Southern Central Regions (Vietnam), the review has not only mentioned partly clarified scientific results but also indicates the limitations and challenges which were faced and encountered in the forecasters of upwelling phenomena in the future.",
|
||||
"issue": "2",
|
||||
"language": "en",
|
||||
"libraryCatalog": "AquaDocs",
|
||||
"pages": "103-122",
|
||||
"publicationTitle": "Vietnam of Journal Marine Science and Technology",
|
||||
"shortTitle": "Upwelling phenomenon in the marine regions of Southern Central of Vietnam",
|
||||
"url": "http://hdl.handle.net/1834/42391",
|
||||
"volume": "22",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Natural resources"
|
||||
},
|
||||
{
|
||||
"tag": "Upwelling phenomenon"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/handle/1834/20117?show=full",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "M/V CONNECTED Coral Reef Restoration Monitoring Report, Monitoring Events 2004-2005. Florida Keys National Marine Sanctuary Monroe County, Florida",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joe",
|
||||
"lastName": "Schittone",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Erik C.",
|
||||
"lastName": "Franklin",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "J. Harold",
|
||||
"lastName": "Hudson",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Jeff",
|
||||
"lastName": "Anderson",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2006",
|
||||
"abstractNote": "This document presents the results of the monitoring of a repaired coral reef injured by the M/V Connected vessel grounding incident of March 27, 2001. This groundingoccurred in Florida state waters within the boundaries of the Florida Keys National Marine Sanctuary (FKNMS). The National Oceanic and Atmospheric Administration (NOAA) and the Board of Trustees of the Internal Improvement Trust Fund of the State of Florida, (“State of Florida” or “state”) are the co-trustees for the natural resourceswithin the FKNMS and, thus, are responsible for mediating the restoration of the damaged marine resources and monitoring the outcome of the restoration actions. Therestoration monitoring program tracks patterns of biological recovery, determines the success of restoration measures, and assesses the resiliency to environmental andanthropogenic disturbances of the site over time.The monitoring program at the Connected site was to have included an assessment of the structural stability of installed restoration modules and biological condition of reattached corals performed on the following schedule: immediately (i.e., baseline), 1, 3, and 6 years after restoration and following a catastrophic event. Restoration of this site was completed on July 20, 2001. Due to unavoidable delays in the settlement of the case, the“baseline” monitoring event for this site occurred in July 2004. The catastrophic monitoring event occurred on August 31, 2004, some 2 ½ weeks after the passage of Hurricane Charley which passed nearby, almost directly over the Dry Tortugas. In September 2005, the year one monitoring event occurred shortly after the passage of Hurricane Katrina, some 70 km to the NW. This report presents the results of all three monitoring events. (PDF contains 37 pages.)",
|
||||
"language": "en",
|
||||
"libraryCatalog": "AquaDocs",
|
||||
"place": "Silver Spring, MD",
|
||||
"publisher": "NOAA/National Ocean Service/National Marine Sanctuary Program",
|
||||
"series": "Marine Sanctuaries Conservation Series",
|
||||
"url": "http://hdl.handle.net/1834/20117",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Acropora palmata"
|
||||
},
|
||||
{
|
||||
"tag": "Coral"
|
||||
},
|
||||
{
|
||||
"tag": "Ecology"
|
||||
},
|
||||
{
|
||||
"tag": "Environment"
|
||||
},
|
||||
{
|
||||
"tag": "Florida Keys National Marine Sanctuary"
|
||||
},
|
||||
{
|
||||
"tag": "Grounding"
|
||||
},
|
||||
{
|
||||
"tag": "Hurricane Charley"
|
||||
},
|
||||
{
|
||||
"tag": "Hurricane Katrina"
|
||||
},
|
||||
{
|
||||
"tag": "Management"
|
||||
},
|
||||
{
|
||||
"tag": "Monitoring"
|
||||
},
|
||||
{
|
||||
"tag": "Restoration"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/discover",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/browse?type=subject&value=A.+gueldenstaedtii",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/handle/1834/30052?show=full",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Ecological Attribute Alteration: Measurement and Evaluation: Activity Assessment Routine: Ecological Systems Component, Ecological Systems Component Handbook",
|
||||
"creators": [],
|
||||
"date": "1978-08",
|
||||
"abstractNote": "This technical paper is intended to provide a more complete treatment of implicit principles and assumptions contained in the user's manual for the ecological systems component of the activity assessment routine. The ecological systems component (ESC) defines a method for evaluating changes in an ecosystem which may result from resource use and consumption. This paper begins by characterizing an ecosystem as an organized collection of attributes mutually dependent on energy exchange. The magnitude matrix with which altered energy flows are scaled is described in Chapter 4. The magnitude of an alteration is assessed somewhat differently for the two categories of attributes: discussion of conventions relevant to this distinction is provided in Chapter 5. However, effects on attributes are variable through time, and additional remarks concerning duration are included in Chapter 6. Finally, possible exceptions to the general guidelines for designating the direction of an effect are introduced in Chapter 7.",
|
||||
"bookTitle": "Ecological Systems Component Handbook",
|
||||
"language": "en",
|
||||
"libraryCatalog": "AquaDocs",
|
||||
"place": "Austin, TX",
|
||||
"publisher": "RPC, Inc.",
|
||||
"series": "Technical Paper",
|
||||
"shortTitle": "Ecological Attribute Alteration",
|
||||
"url": "http://hdl.handle.net/1834/30052",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Ecology"
|
||||
},
|
||||
{
|
||||
"tag": "Management"
|
||||
},
|
||||
{
|
||||
"tag": "coastal zone management"
|
||||
},
|
||||
{
|
||||
"tag": "ecological assessment"
|
||||
},
|
||||
{
|
||||
"tag": "evaluation"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/handle/1834/970?show=full",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Report from the WPB on the Data Situation for Billfish",
|
||||
"creators": [],
|
||||
"date": "2000",
|
||||
"conferenceName": "IOTC 3",
|
||||
"language": "en",
|
||||
"libraryCatalog": "AquaDocs",
|
||||
"pages": "102-103",
|
||||
"proceedingsTitle": "IOTC Proceedings no. 3",
|
||||
"publisher": "IOTC",
|
||||
"url": "http://hdl.handle.net/1834/970",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Billfisheries"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://aquadocs.org/handle/1834/31638?show=full",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Introduction",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Caroline M.",
|
||||
"lastName": "Isaacs",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1997",
|
||||
"abstractNote": "The Thirteenth Annual PACLIM Workshop was held at the Asilomar Conference Center on April 14-17, 1996. Attended by about 100 registered participants, the workshop included 27 talks and 26 poster presentations. The talks consisted of a one-day theme session of seven 45-minute talks and two featured evening talks. Throughout the remainder of the meeting were nearly 20 shorter, 20-minute presentations. Poster presenters gave a short 1-2 minute introduction to their posters, which were displayed during the entire meeting.All presenters were invited to expand their abstracts into a manuscript for inclusion in the Proceedings volume, and nearly all presentations are included in manuscript or abstract form. In this Proceedings volume, manuscripts are presented first, and abstracts of talks and then posters follow.",
|
||||
"conferenceName": "Thirteenth Annual Pacific Climate (PACLIM) Workshop",
|
||||
"language": "en",
|
||||
"libraryCatalog": "AquaDocs",
|
||||
"pages": "1-8",
|
||||
"url": "http://hdl.handle.net/1834/31638",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Atmospheric Sciences"
|
||||
},
|
||||
{
|
||||
"tag": "Earth Sciences"
|
||||
},
|
||||
{
|
||||
"tag": "Ecology"
|
||||
},
|
||||
{
|
||||
"tag": "Limnology"
|
||||
},
|
||||
{
|
||||
"tag": "Oceanography"
|
||||
},
|
||||
{
|
||||
"tag": "PACLIM"
|
||||
},
|
||||
{
|
||||
"tag": "hydrology"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-12-27 20:43:34"
|
||||
"lastUpdated": "2020-03-09 12:23:02"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -54,59 +54,62 @@ var metaTags = {
|
|||
};
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var articles = [];
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var items = Zotero.Utilities.getItemArray(doc, doc, /sic_\d+|tel-\d+/);
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) return;
|
||||
ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
items = Zotero.selectItems(items);
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
scrape(doc);
|
||||
articles = [url];
|
||||
}
|
||||
}
|
||||
Zotero.Utilities.processDocuments(articles, function (doc) {
|
||||
var xpath = '//meta[@name]';
|
||||
var data = {};
|
||||
var metas = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var meta;
|
||||
|
||||
function scrape(doc) {
|
||||
var xpath = '//meta[@name]';
|
||||
var data = {};
|
||||
var metas = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var meta;
|
||||
|
||||
meta = metas.iterateNext();
|
||||
while (meta) {
|
||||
if (data[meta.name]) {
|
||||
data[meta.name] = data[meta.name] + ";" + meta.content;
|
||||
}
|
||||
else {
|
||||
data[meta.name] = meta.content;
|
||||
}
|
||||
meta = metas.iterateNext();
|
||||
}
|
||||
while (meta) {
|
||||
if (data[meta.name]) {
|
||||
data[meta.name] = data[meta.name] + ";" + meta.content;
|
||||
}
|
||||
else {
|
||||
data[meta.name] = meta.content;
|
||||
}
|
||||
meta = metas.iterateNext();
|
||||
}
|
||||
|
||||
var item = new Zotero.Item("journalArticle");
|
||||
for (var tag in metaTags) {
|
||||
if (tag == "DC.creator") {
|
||||
var authors = data['DC.creator'].split(";");
|
||||
for (var i = 0; i < authors.length; i++) {
|
||||
var aut = authors[i];
|
||||
aut = aut.replace(/^([^,]+),\s+(.*)$/, "$2 $1");
|
||||
item.creators.push(Zotero.Utilities.cleanAuthor(aut, "author"));
|
||||
var item = new Zotero.Item("journalArticle");
|
||||
for (var tag in metaTags) {
|
||||
if (tag == "DC.creator") {
|
||||
var authors = data['DC.creator'].split(";");
|
||||
for (var i = 0; i < authors.length; i++) {
|
||||
var aut = authors[i];
|
||||
aut = aut.replace(/^([^,]+),\s+(.*)$/, "$2 $1");
|
||||
item.creators.push(Zotero.Utilities.cleanAuthor(aut, "author"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
item[metaTags[tag]] = data[tag];
|
||||
}
|
||||
}
|
||||
else {
|
||||
item[metaTags[tag]] = data[tag];
|
||||
|
||||
var pdfurl = data.citation_pdf_url;
|
||||
|
||||
if (pdfurl) {
|
||||
item.attachments = [
|
||||
{ url: item.url, title: "AOSIC Snapshot", mimeType: "text/html" },
|
||||
{ url: pdfurl, title: "AOSIC Full Text PDF", mimeType: "application/pdf" }
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
var pdfurl = data.citation_pdf_url;
|
||||
|
||||
if (pdfurl) {
|
||||
item.attachments = [
|
||||
{ url: item.url, title: "AOSIC Snapshot", mimeType: "text/html" },
|
||||
{ url: pdfurl, title: "AOSIC Full Text PDF", mimeType: "application/pdf" }
|
||||
];
|
||||
}
|
||||
item.complete();
|
||||
item.complete();
|
||||
}, function () {
|
||||
Zotero.done();
|
||||
});
|
||||
Zotero.wait();
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,175 @@
|
|||
{
|
||||
"translatorID": "d9a16cf3-8b86-4cab-8610-dbd913ad1a44",
|
||||
"label": "Archives Canada-France",
|
||||
"creator": "Adam Crymble",
|
||||
"target": "^https?://bd\\.archivescanadafrance\\.org",
|
||||
"minVersion": "1.0.0b4.r5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"browserSupport": "gcsibv",
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"lastUpdated": "2012-01-01 01:42:16"
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
|
||||
if (doc.location.href.match("doc.xsp?")) {
|
||||
return "book";
|
||||
} else if (doc.evaluate('//li/a', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
return "multiple";
|
||||
} else if (doc.evaluate('//td[1][@class="icones"]/a', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
return "multiple";
|
||||
}
|
||||
}
|
||||
|
||||
function associateData (newItem, dataTags, field, zoteroField) {
|
||||
if (dataTags[field]) {
|
||||
newItem[zoteroField] = dataTags[field];
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
|
||||
var namespace = doc.documentElement.namespaceURI;
|
||||
var nsResolver = namespace ? function(prefix) {
|
||||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
var dataTags = new Object();
|
||||
var tagsContent = new Array();
|
||||
var fieldTitle;
|
||||
|
||||
var newItem = new Zotero.Item("book");
|
||||
var xPathHeaders = '//td[2]/div[@class="ead-c"]/div[@class="ead-did"]/table[@class="ead-did"]/tbody/tr/td[1]';
|
||||
|
||||
if (doc.evaluate(xPathHeaders, doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var headers = doc.evaluate(xPathHeaders, doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var contents = doc.evaluate('//td[2][@class="did-content"]', doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
|
||||
while (fieldTitle = headers.iterateNext()) {
|
||||
fieldTitle = fieldTitle.textContent.replace(/\s+/g, '');
|
||||
if (fieldTitle == "Origination" || fieldTitle == "Origine") {
|
||||
fieldTitle = "Origination";
|
||||
}
|
||||
dataTags[fieldTitle] = Zotero.Utilities.cleanTags(contents.iterateNext().textContent.replace(/^\s*|\s*$/g, ''));
|
||||
}
|
||||
|
||||
if (dataTags["Origination"]) {
|
||||
var author = dataTags["Origination"];
|
||||
if (!author.match(", ")) {
|
||||
newItem.creators.push({lastName: author, creatorType: "author"});
|
||||
} else {
|
||||
var authors = author.split(", ");
|
||||
author = authors[1] + " " + authors[0];
|
||||
newItem.creators.push(Zotero.Utilities.cleanAuthor(author, "author"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (doc.evaluate('//h1[@class="doc-title"]', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
newItem.title = doc.evaluate('//h1[@class="doc-title"]', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
} else if (doc.evaluate('//td[2]/div[@class="notice"]/p', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
newItem.title = doc.evaluate('//td[2]/div[@class="notice"]/p', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
} else {
|
||||
newItem.title = doc.title + " Title Not Found";
|
||||
}
|
||||
|
||||
associateData (newItem, dataTags, "PhysicalDescription", "pages");
|
||||
associateData (newItem, dataTags, "Descriptionmatérielle", "pages");
|
||||
|
||||
associateData (newItem, dataTags, "Repository", "repository");
|
||||
associateData (newItem, dataTags, "Lieudeconservation", "repository");
|
||||
|
||||
associateData (newItem, dataTags, "LanguageoftheMaterial", "language");
|
||||
associateData (newItem, dataTags, "Langue", "language");
|
||||
|
||||
associateData (newItem, dataTags, "Identifier", "callNumber");
|
||||
associateData (newItem, dataTags, "Cote", "callNumber");
|
||||
|
||||
associateData (newItem, dataTags, "Datesextrêmes", "date");
|
||||
associateData (newItem, dataTags, "Dates", "date");
|
||||
|
||||
newItem.url = doc.location.href;
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var namespace = doc.documentElement.namespaceURI;
|
||||
var nsResolver = namespace ? function(prefix) {
|
||||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
var articles = new Array();
|
||||
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
|
||||
var items = new Object();
|
||||
|
||||
if (doc.evaluate('//td[1][@class="icones"]/a', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var titles = doc.evaluate('//td[2][@class="ressource"]', doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var titlesCount = doc.evaluate('count (//td[2][@class="ressource"])', doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var links = doc.evaluate('//td[1][@class="icones"]/a', doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
|
||||
var next_link;
|
||||
|
||||
for (var i = 0; i < titlesCount.numberValue; i++) {
|
||||
next_link = links.iterateNext().href;
|
||||
if (!next_link.match("doc.xsp")) {
|
||||
next_link = links.iterateNext().href;
|
||||
}
|
||||
items[next_link] = titles.iterateNext().textContent;
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.evaluate('//li/a', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var titles = doc.evaluate('//li/a', doc, nsResolver, XPathResult.ANY_TYPE, null);
|
||||
var next_title;
|
||||
while (next_title = titles.iterateNext()) {
|
||||
items[next_title.href] = next_title.textContent;
|
||||
}
|
||||
}
|
||||
|
||||
items = Zotero.selectItems(items);
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
|
||||
} else if (doc.evaluate('//div[@class="ancestor"]/a', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
|
||||
var link = doc.evaluate('//div[@class="ancestor"]/a', doc, nsResolver, XPathResult.ANY_TYPE, null).iterateNext().href;
|
||||
|
||||
articles = [link];
|
||||
} else {
|
||||
articles = [url]
|
||||
}
|
||||
Zotero.Utilities.processDocuments(articles, scrape, function() {Zotero.done();});
|
||||
Zotero.wait();
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://bd.archivescanadafrance.org/sdx-222-acf-pleade-2/acf/search-acf.xsp?sq1=montreal&fi1=fulltext&sq2=&fi2=fulltext&sq3=&fi3=fulltext&ed=&dbeg=&dend=&frepo=&forig=&x=0&y=0#resume",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://bd.archivescanadafrance.org/sdx-222-acf-pleade-2/acf/doc.xsp?id=CAANQ_PISTARD_03Q808_392_CAANQ_PISTARD_03Q808_392&qid=sdx_q0&fmt=tab&base=fa&n=5&root=CAANQ_PISTARD_03Q808_392&ss=true&as=&ai=&from=",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"creators": [],
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [],
|
||||
"title": "Fonds Intendants",
|
||||
"url": "http://bd.archivescanadafrance.org/sdx-222-acf-pleade-2/acf/doc.xsp?id=ANQ_00001_intendants&fmt=tab&base=fa&root=CAANQ_PISTARD_03Q808_392&n=5&qid=sdx_q0&ss=true&as=&ai=",
|
||||
"libraryCatalog": "Archives Canada-France",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
203
Ariana News.js
203
Ariana News.js
|
|
@ -1,203 +0,0 @@
|
|||
{
|
||||
"translatorID": "44552245-d911-4613-8b4f-19f41a5e5b0d",
|
||||
"label": "Ariana News",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https://ariananews\\.af/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-16 15:20:38"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.body.classList.contains('single')) {
|
||||
return "newspaperArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('ul.mvp-blog-story-list li a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(text(row, 'h2'));
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.tags = item.tags.filter(tag => tag != 'featured' && tag != 'acci');
|
||||
|
||||
if (item.abstractNote) {
|
||||
item.abstractNote = item.abstractNote.replace(/^\([^)]+\)/, '');
|
||||
}
|
||||
|
||||
if (item.creators.length == 1 && item.creators[0].lastName == 'News') {
|
||||
item.creators = [];
|
||||
}
|
||||
|
||||
item.date = attr(doc, '[itemprop="datePublished"]', 'datetime');
|
||||
item.publicationTitle = 'Ariana News';
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = "newspaperArticle";
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ariananews.af/afghan-carpet-industry-facing-major-challenges-acci/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Afghan carpet industry facing major challenges: ACCI",
|
||||
"creators": [],
|
||||
"date": "2021-07-26",
|
||||
"abstractNote": "Afghanistan’s Chamber of Commerce and Investment (ACCI) said on Sunday that the Afghan carpet industry is facing numerous challenges despite the foreign aid that has been injected into the industry. The ACCI said that the lack of a dedicated industrial park and a suitable place to produce carpets are a […]",
|
||||
"language": "en-US",
|
||||
"libraryCatalog": "ariananews.af",
|
||||
"publicationTitle": "Ariana News",
|
||||
"shortTitle": "Afghan carpet industry facing major challenges",
|
||||
"url": "https://ariananews.af/afghan-carpet-industry-facing-major-challenges-acci/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "carpet"
|
||||
},
|
||||
{
|
||||
"tag": "export"
|
||||
},
|
||||
{
|
||||
"tag": "kabul"
|
||||
},
|
||||
{
|
||||
"tag": "production"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ariananews.af/us-troops-arrive-in-kabul-to-assist-with-evacuations/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "US troops arrive in Kabul to assist with evacuations",
|
||||
"creators": [],
|
||||
"date": "2021-08-14",
|
||||
"abstractNote": "American troops have flown into Kabul to help evacuate embassy personnel and other civilians in the Afghan capital, a U.S. official said on Saturday, a day after Taliban insurgents seized the country’s second- and third-biggest cities. The Pentagon has said two battalions of Marines and one infantry battalion will arrive […]",
|
||||
"language": "en-US",
|
||||
"libraryCatalog": "ariananews.af",
|
||||
"publicationTitle": "Ariana News",
|
||||
"url": "https://ariananews.af/us-troops-arrive-in-kabul-to-assist-with-evacuations/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "attacsk"
|
||||
},
|
||||
{
|
||||
"tag": "doha"
|
||||
},
|
||||
{
|
||||
"tag": "embassy"
|
||||
},
|
||||
{
|
||||
"tag": "peace"
|
||||
},
|
||||
{
|
||||
"tag": "taliban"
|
||||
},
|
||||
{
|
||||
"tag": "troops"
|
||||
},
|
||||
{
|
||||
"tag": "us"
|
||||
},
|
||||
{
|
||||
"tag": "violence"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://ariananews.af/?s=covid",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
{
|
||||
"translatorID": "8e98b11a-5648-42b2-8542-5f366cb953f6",
|
||||
"label": "Art Institute of Chicago",
|
||||
"creator": "nikhil trivedi, Illya Moskvin",
|
||||
"target": "^https?://(www\\.)?artic\\.edu/(artworks/|collection)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-06-04 20:08:22"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Art Institute of Chicago
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
function detectWeb(doc) {
|
||||
if (ZU.xpathText(doc, '//html[contains(@class, "p-artwork-show")]')) {
|
||||
return 'artwork';
|
||||
}
|
||||
else if (ZU.xpathText(doc, '//html[contains(@class, "p-collection-index")]')) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doWeb(doc) {
|
||||
if (detectWeb(doc) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
scrape(doc);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc) {
|
||||
var item = new Zotero.Item('artwork');
|
||||
item.title = ZU.xpathText(doc, '//h1');
|
||||
|
||||
var artists = ZU.xpath(doc, '//meta[contains(@name, "citation_author")]');
|
||||
for (var i = 0; i < artists.length; i++) {
|
||||
var cleaned = artists[i].content.replace(/\(.*\)$/, '').trim();
|
||||
item.creators.push(ZU.cleanAuthor(cleaned, 'artist'));
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.date = ZU
|
||||
.xpath(doc, '//dl[@id="dl-artwork-details"]/dd[@itemprop="dateCreated"]/*/a')
|
||||
.map(function (date) {
|
||||
return date.textContent;
|
||||
})
|
||||
.join(', ');
|
||||
|
||||
item.artworkMedium = ZU.xpathText(doc, '//dl[@id="dl-artwork-details"]/dd[@itemprop="material"]');
|
||||
item.artworkSize = ZU.xpathText(doc, '//dl[@id="dl-artwork-details"]/dd[@itemprop="size"]');
|
||||
item.callNumber = ZU.xpathText(doc, '//dl[@id="dl-artwork-details"]/dd[@itemprop="identifier"]');
|
||||
|
||||
item.url = ZU.xpathText(doc, '//link[@rel="canonical"]/@href');
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = ZU.xpath(doc, '//ul[@id="artworksList"]/li/a');
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artic.edu/artworks/129884/starry-night-and-the-astronauts",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Starry Night and the Astronauts",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Alma",
|
||||
"lastName": "Thomas",
|
||||
"creatorType": "artist"
|
||||
}
|
||||
],
|
||||
"date": "1972",
|
||||
"artworkMedium": "Acrylic on canvas",
|
||||
"artworkSize": "152.4 × 134.6 cm (60 × 53 in.)",
|
||||
"callNumber": "1994.36",
|
||||
"libraryCatalog": "Art Institute of Chicago",
|
||||
"url": "https://www.artic.edu/artworks/129884/starry-night-and-the-astronauts",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artic.edu/artworks/156538/chicago-stock-exchange-trading-room-reconstruction-at-the-art-institute-of-chicago",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Chicago Stock Exchange Trading Room: Reconstruction at the Art Institute of Chicago",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Architects",
|
||||
"creatorType": "artist",
|
||||
"firstName": "Adler & Sullivan"
|
||||
}
|
||||
],
|
||||
"date": "Built 1893–1894",
|
||||
"artworkMedium": "Mixed media recreation of room",
|
||||
"artworkSize": "Room is roughly 5,704 square feet (not including gallery)",
|
||||
"callNumber": "RX23310/0002",
|
||||
"libraryCatalog": "Art Institute of Chicago",
|
||||
"shortTitle": "Chicago Stock Exchange Trading Room",
|
||||
"url": "https://www.artic.edu/artworks/156538/chicago-stock-exchange-trading-room-reconstruction-at-the-art-institute-of-chicago",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artic.edu/artworks/28560/the-bedroom",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "The Bedroom",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Gogh",
|
||||
"creatorType": "artist",
|
||||
"firstName": "Vincent van"
|
||||
}
|
||||
],
|
||||
"date": "1889",
|
||||
"artworkMedium": "Oil on canvas",
|
||||
"artworkSize": "73.6 × 92.3 cm (29 × 36 5/8 in.)",
|
||||
"callNumber": "1926.417",
|
||||
"libraryCatalog": "Art Institute of Chicago",
|
||||
"url": "https://www.artic.edu/artworks/28560/the-bedroom",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artic.edu/artworks/52273/platform-bench",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Platform Bench",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "George",
|
||||
"lastName": "Nelson",
|
||||
"creatorType": "artist"
|
||||
},
|
||||
{
|
||||
"lastName": "Inc",
|
||||
"creatorType": "artist",
|
||||
"firstName": "Herman Miller"
|
||||
}
|
||||
],
|
||||
"date": "Designed 1946, Made 1946-1967, c. 1946-1967",
|
||||
"artworkMedium": "Birch",
|
||||
"artworkSize": "35.5 × 47 × 183.5 cm (14 × 18 1/2 × 72 1/4 in.)",
|
||||
"callNumber": "1978.141",
|
||||
"libraryCatalog": "Art Institute of Chicago",
|
||||
"url": "https://www.artic.edu/artworks/52273/platform-bench",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artic.edu/artworks/7691/gathering-seaweed-at-omori",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Gathering Seaweed at Omori",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Utagawa",
|
||||
"lastName": "Kuniyoshi",
|
||||
"creatorType": "artist"
|
||||
}
|
||||
],
|
||||
"artworkMedium": "Ink and red pigment on paper",
|
||||
"callNumber": "1958.191",
|
||||
"libraryCatalog": "Art Institute of Chicago",
|
||||
"url": "https://www.artic.edu/artworks/7691/gathering-seaweed-at-omori",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
438
Artforum.js
438
Artforum.js
|
|
@ -1,438 +0,0 @@
|
|||
{
|
||||
"translatorID": "a127f012-4ea4-4d05-a657-24d47f91b016",
|
||||
"label": "Artforum",
|
||||
"creator": "czar",
|
||||
"target": "^https?://(www\\.)?artforum\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-09-02 00:33:38"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2018 czar
|
||||
http://en.wikipedia.org/wiki/User_talk:Czar
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (/-\d{5,}([?#].*)?$/.test(url)) {
|
||||
if (doc.querySelector('h3.print-article__issue-title')) {
|
||||
return "magazineArticle";
|
||||
}
|
||||
return "blogPost";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48'); // embedded metadata (EM)
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) { // corrections to EM
|
||||
item.publicationTitle = "Artforum";
|
||||
item.language = 'en-US';
|
||||
var jsonLD = doc.querySelector('script[type="application/ld+json"]');
|
||||
if (jsonLD) {
|
||||
jsonLD = JSON.parse(jsonLD.textContent);
|
||||
item.title = jsonLD.name;
|
||||
item.date = jsonLD.dateModified || jsonLD.datePublished;
|
||||
|
||||
if (!item.creators.length && jsonLD.author) {
|
||||
item.creators.push(ZU.cleanAuthor(jsonLD.author.name, 'author'));
|
||||
}
|
||||
}
|
||||
var authorMetadata = doc.querySelectorAll('.contrib-link a');
|
||||
for (let author of authorMetadata) {
|
||||
item.creators.push(ZU.cleanAuthor(author.text, "author"));
|
||||
}
|
||||
if (url.includes('/print/')) {
|
||||
item.itemType = "magazineArticle";
|
||||
item.ISSN = "0004-3532";
|
||||
var issueDate = doc.querySelector('h3.print-article__issue-title');
|
||||
if (issueDate) {
|
||||
item.date = issueDate.textContent.trim().replace('PRINT ','');
|
||||
ZU.doGet(issueDate.querySelector('a').href, function (respText) {
|
||||
var voliss = respText.match(/Vol\.\s(\d+),\sNo\.\s(\d+)/);
|
||||
item.volume = voliss[1];
|
||||
item.issue = voliss[2];
|
||||
item.complete();
|
||||
});
|
||||
} else item.complete();
|
||||
} else item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function(trans) {
|
||||
trans.itemType = 'blogPost';
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
// 1st for search page, 2nd for issue ToC, 3rd/4th/5th for sections, 5th+ for homepage
|
||||
var rows = doc.querySelectorAll('h1.results-list__h1, .toc-article__title, .news-list h1, .reviews-list h1, .article-list h1, p.hp-singlefeature-author__writer, h3.hp-news__title, h3.hp-twocolumn__title a, h3.hp-artguide__title, p.hp-bloglist__teaser a');
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let href = attr(rows[i], 'a', 'href');
|
||||
if (!href) {
|
||||
let link = rows[i].closest('a');
|
||||
if (link) href = link.href;
|
||||
}
|
||||
let title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
switch (detectWeb(doc, url)) {
|
||||
case "multiple":
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
scrape(doc, url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/news/ugochukwu-smooth-nzewi-appointed-curator-of-hood-museum-40747",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Ugochukwu-Smooth Nzewi Appointed Curator of Hood Museum",
|
||||
"creators": [],
|
||||
"date": "2013-05-06",
|
||||
"abstractNote": "The Hood Museum of Art at Dartmouth College, Hanover, has appointed Ugochukwu-Smooth Nzewi as its first curator of African Art, reports Artdaily. Born in Nigeria, Nzewi received his PhD in Art History from Emory University. A specialist in modern and contemporary African and African Diaspora arts, he will be responsible in his new role for the documentation, preservation, and research of Hood’s African Art collection, which includes some 1,900 objects. He will also engage Dartmouth faculty and students in the development of curricular programming related to the museum’s African holdings. Nzewi",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/news/ugochukwu-smooth-nzewi-appointed-curator-of-hood-museum-40747",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/diary/kaitlin-phillips-at-the-11th-new-york-art-book-fair-63626",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Fine Print",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Kaitlin",
|
||||
"lastName": "Phillips",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2016-09-22",
|
||||
"abstractNote": "LAST THURSDAY, at the opening night preview of Printed Matter’s NY Book Fair at MoMA PS1, in the popup white dome in the courtyard, at one of the end-to-end merchandise tables, V. Vale (“That’s the name I’m famous under”), founder of RE/Search, complains to a fan that the fair, in its eleventh year, and its host city, have lost their street cred:“I never come to New York. Yeah, I never come to New York. I never come to New York,” says Vale, beaming defiantly.“Well, New York may have jumped the shark.”“I don’t know what that means. Jump the shark.”“It means that something has hit its peak, and",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/diary/kaitlin-phillips-at-the-11th-new-york-art-book-fair-63626",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/picks/alex-da-corte-62421",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Alex Da Corte",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Aria",
|
||||
"lastName": "Dean",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2016-07-28",
|
||||
"abstractNote": "As you enter this space, your senses are bombarded by Alex Da Corte’s scrambled, saturated landscape. A supersized witch’s hat fills the first area, lit by green and red neon from above. This is flanked by a stained-glass window depicting a red rose, referencing Disney’s Beauty and the Beast, and a floor-to-ceiling, blown-up image of a weeping bridesmaid. The exhibition is like a dream: Recognizable elements are mashed together, but something is off, and it gradually morphs into a surreal nightmare.The gallery buzzes with sound from three video works—the focal point of the second room—depicting",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/picks/alex-da-corte-62421",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/film/nick-pinkerton-on-gimme-shelter-hollywood-north-66885",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Canadian Makin’",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Nick",
|
||||
"lastName": "Pinkerton",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2017-02-24",
|
||||
"abstractNote": "AFTER THE EMERGENCE of alluring Canadian production subsidies in the late 1990s, moviegoers of the aughts became inured to watching downtown Vancouver fill in for AnyCity, USA, in a parade of multiplex productions that managed to extract bland back-lot anonymity from location shooting. But Anthology Film Archives’ twelve-film series “Gimme Shelter: Hollywood North” pays tribute to a very different, pioneering era of runaway production, part of an ongoing sesquicentennial celebration of our neighbors above to be followed by “1970s Canadian Independents,” beginning at Anthology on March 9.The",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/film/nick-pinkerton-on-gimme-shelter-hollywood-north-66885",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/print/previews/201701/whitney-biennial-2017-65484",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "Whitney Biennial 2017",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Beau",
|
||||
"lastName": "Rutland",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "January 2017",
|
||||
"ISSN": "0004-3532",
|
||||
"abstractNote": "Curated by Christopher Y. Lew and Mia LocksFollowing a three-year hiatus to accommodate the museum’s move downtown, the Whitney Biennial makes its Gansevoort Street debut this March. As the republic falls before our very eyes, one hopes that this divisive survey of American art will react against, and not just reflect, the current state of affairs. This year’s roster of sixty-three artists and collectives is thankfully diverse in perspectives and refreshingly full of emerging and underrecognized voices—absent are the many elder statesmen often gratuitously included in these affairs. The",
|
||||
"issue": "5",
|
||||
"language": "en-US",
|
||||
"libraryCatalog": "www.artforum.com",
|
||||
"publicationTitle": "Artforum",
|
||||
"url": "https://www.artforum.com/print/previews/201701/whitney-biennial-2017-65484",
|
||||
"volume": "55",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/interviews/jamie-stewart-talks-about-xiu-xiu-s-record-forget-and-recent-collaborations-66615",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Jamie Stewart",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Paige K.",
|
||||
"lastName": "Bradley",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2017-02-21",
|
||||
"abstractNote": "Across thirteen albums and a handful of EPs, Xiu Xiu have remained a prickly, relentless force, inspiring loyalty, love, annoyance, and disgust in equal measure. Some people never get over their music, and some you couldn’t pay to even approach it. On the occasion of the release of their latest album, FORGET, the band’s mainstay Jamie Stewart discusses how he met Vaginal Davis (who performs on its last track), the band’s collaborations with Danh Vō, and the concept behind the record’s title. Polyvinyl will release FORGET on February 24, 2017.HOW I MET VAGINAL DAVIS is actually a long story and",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/interviews/jamie-stewart-talks-about-xiu-xiu-s-record-forget-and-recent-collaborations-66615",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/print/reviews/201408/dak-art-2014-48214",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "Dak’Art 2014",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Chika",
|
||||
"lastName": "Okeke-Agulu",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "October 2014",
|
||||
"ISSN": "0004-3532",
|
||||
"abstractNote": "THE ELEVENTH EDITION of the Dak’Art Biennial of Contemporary African Art, which took place this past summer, may well have been the most ambitious since the exhibition’s inception in 1992. It was the largest and most diverse yet, not only showcasing emerging artists from across Africa but also including the work of many superstars from the established biennial circuit. This roster showed that the global art world must reckon with Dak’Art, which seems poised to take its place among the most established international art shows. Yet this year’s iteration also suggested that the biennial is still",
|
||||
"issue": "2",
|
||||
"language": "en-US",
|
||||
"libraryCatalog": "www.artforum.com",
|
||||
"publicationTitle": "Artforum",
|
||||
"url": "https://www.artforum.com/print/reviews/201408/dak-art-2014-48214",
|
||||
"volume": "53",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/search?search=1%3A54&sort=date",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/print/previews/current/new-york",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/print/201806",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/news/levy-gorvy-amalia-dayan-salon-94-merge-to-form-upper-east-side-megagallery-86598",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "New York Dealers Lévy Gorvy, Amalia Dayan, Salon 94, Announce Merger",
|
||||
"creators": [],
|
||||
"date": "2021-09-01",
|
||||
"abstractNote": "Two New York galleries—Lévy Gorvy and Salon 94—and dealer Amalia Dayan have announced that they are joining forces to establish a single consortium, called LGDR, whose flagship will be situated on the city’s tony Upper East Side. The news, first reported in the New York Times, is said to have come as a shock to a number of the galleries’ artists, whose fate is unclear.The new entity, which takes its name from the last initials of its owners—Dominique Lévy and Brett Gorvy, cofounders of Lévy Gorvy; veteran dealer Amalia Dayan; and Jeanne Greenberg Rohatyn, the owner of Salon 94—will occupy digs",
|
||||
"blogTitle": "Artforum",
|
||||
"language": "en-US",
|
||||
"url": "https://www.artforum.com/news/levy-gorvy-amalia-dayan-salon-94-merge-to-form-upper-east-side-megagallery-86598",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.artforum.com/print/202107/david-salle-on-janet-malcolm-86314",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "JANET MALCOLM (1934–2021)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "David",
|
||||
"lastName": "Salle",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "September 2021",
|
||||
"ISSN": "0004-3532",
|
||||
"abstractNote": "ABOUT TWENTY-FIVE YEARS AGO Janet Malcolm published a profile of me in the New Yorker that became something of a touchstone of art journalism. It served as the title essay of one of her collections, and has been reprinted several times. I’m told it’s often assigned in classes on art writing, on the assumption that it sheds some light on that murky enterprise.It’s uncommon for the subject of a profile to warmly remember the profiler, and my friendship with Janet struck some people as odd. For some, it would be hard, or so they imagined, to get past the discomforts of so much self-exposure, and",
|
||||
"issue": "1",
|
||||
"language": "en-US",
|
||||
"libraryCatalog": "www.artforum.com",
|
||||
"publicationTitle": "Artforum",
|
||||
"url": "https://www.artforum.com/print/202107/david-salle-on-janet-malcolm-86314",
|
||||
"volume": "60",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,311 +0,0 @@
|
|||
{
|
||||
"translatorID": "01322929-5782-4612-81f7-d861fb46d9f2",
|
||||
"label": "Atlanta Journal-Constitution",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?ajc\\.com",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-14 19:41:44"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (doc.querySelector('.c-articleContent')
|
||||
&& doc.querySelector('script[type="application/ld+json"]')) {
|
||||
if (url.includes('blog/')) {
|
||||
return "blogPost";
|
||||
}
|
||||
else {
|
||||
return "newspaperArticle";
|
||||
}
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('a.gs-title');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
let json = JSON.parse(text(doc, 'script[type="application/ld+json"]'));
|
||||
|
||||
let item = new Zotero.Item(
|
||||
url.includes('blog/')
|
||||
? 'blogPost'
|
||||
: 'newspaperArticle'
|
||||
);
|
||||
|
||||
item.title = json.headline;
|
||||
item.abstractNote = json.description
|
||||
|| attr(doc, 'meta[name="description"]', 'content');
|
||||
item.place = extractPlace(item.abstractNote);
|
||||
|
||||
let sectionLabel = text(doc, '.section-label');
|
||||
if (item.itemType == 'blogPost') {
|
||||
item.blogTitle = `${sectionLabel} (The Atlanta Journal-Constitution)`;
|
||||
}
|
||||
else {
|
||||
item.section = sectionLabel;
|
||||
item.publicationTitle = 'The Atlanta Journal-Constitution';
|
||||
item.ISSN = '1539-7459';
|
||||
}
|
||||
|
||||
item.language = attr(doc, 'meta[name="language"]', 'content');
|
||||
item.libraryCatalog = 'AJC.com';
|
||||
|
||||
for (let author of json.author.name.split(', ')) {
|
||||
item.creators.push(ZU.cleanAuthor(author, 'author'));
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
function extractPlace(leadText) {
|
||||
let placeRe = /^\s*([A-Z\-']{3,})\b/;
|
||||
if (placeRe.test(leadText)) {
|
||||
return ZU.capitalizeTitle(leadText.match(placeRe)[1], true);
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/politics/georgia-republicans-center-campaigns-on-false-claims-of-election-fraud/JNRJYNAG6BD5JC5BB2TQG3LYGA/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Georgia Republicans center campaigns on false claims of election fraud",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Greg",
|
||||
"lastName": "Bluestein",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"ISSN": "1539-7459",
|
||||
"abstractNote": "ROME — The organizers at the door handed out soft-pink “Trump Won” signs to each attendee. An out-of-state radio host spouted far-right conspiracies.",
|
||||
"language": "English",
|
||||
"libraryCatalog": "AJC.com",
|
||||
"place": "Rome",
|
||||
"publicationTitle": "The Atlanta Journal-Constitution",
|
||||
"section": "Politics",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/politics/politics-blog/the-jolt-details-emerge-about-ames-barnett-possible-brian-kemp-primary-foe/MI6WFP3L7VH4NADGFHSXOUS6KM/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "The Jolt: Details emerge about Ames Barnett, possible Brian Kemp primary foe",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Patricia",
|
||||
"lastName": "Murphy",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Greg",
|
||||
"lastName": "Bluestein",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Tia",
|
||||
"lastName": "Mitchell",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"abstractNote": "Ames Barnett, a wealthy businessman and former small-town mayor, is moving closer to a Republican primary challenge against Gov. Brian Kemp. But his r",
|
||||
"blogTitle": "Political Insider (The Atlanta Journal-Constitution)",
|
||||
"language": "English",
|
||||
"shortTitle": "The Jolt",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/neighborhoods/cobb/marietta-officials-homeowner-property-tax-bills-will-go-down-for-third-year-in-a-row/3AIW5PLTXRHLDCWF4Q6HYQVQKQ/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Marietta officials: Homeowner property tax bills will go down for third year in a row",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Matt",
|
||||
"lastName": "Bruce",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"ISSN": "1539-7459",
|
||||
"abstractNote": "Property values have surged during the pandemic, but Marietta officials say homeowners will pay less in taxes.",
|
||||
"language": "English",
|
||||
"libraryCatalog": "AJC.com",
|
||||
"publicationTitle": "The Atlanta Journal-Constitution",
|
||||
"section": "Cobb County",
|
||||
"shortTitle": "Marietta officials",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/things-to-do/restaurant-refresh/patio-picks-treat-yourself-to-alfresco-elegance/ZF4FZUMJYBB6HJXTS32QCEYGSA/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Atlanta patio picks: Treat yourself to alfresco elegance",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ligaya",
|
||||
"lastName": "Figueras",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Wendell",
|
||||
"lastName": "Brock",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"ISSN": "1539-7459",
|
||||
"abstractNote": "Check out four of the best patios in metro Atlanta to eat and drink, including the Chastain, Delbar, Banshee and Willow Bar.",
|
||||
"language": "English",
|
||||
"libraryCatalog": "AJC.com",
|
||||
"publicationTitle": "The Atlanta Journal-Constitution",
|
||||
"section": "Restaurant Refresh",
|
||||
"shortTitle": "Atlanta patio picks",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/life/radiotvtalk-blog/whats-filming-in-georgia-in-july-2021/7UJ6NZIF7NA6LJFG7QPHE4HFDM/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "What’s filming in Georgia in July 2021?",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Rodney",
|
||||
"lastName": "Ho",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"abstractNote": "\"Black Panther: Wakanda Forever\" began production in late June 2021 at Trilith Studios in Fayetteville.",
|
||||
"blogTitle": "Radio & TV Talk Blog (The Atlanta Journal-Constitution)",
|
||||
"language": "English",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.ajc.com/search/?q=labor",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -2,21 +2,21 @@
|
|||
"translatorID": "5ed5ab01-899f-4a3b-a74c-290fb2a1c9a4",
|
||||
"label": "AustLII and NZLII",
|
||||
"creator": "Justin Warren, Philipp Zumstein",
|
||||
"target": "^https?://(www\\d?|classic)\\.(austlii\\.edu\\.au|nzlii\\.org)",
|
||||
"target": "^https?://www\\d?\\.(austlii\\.edu\\.au|nzlii\\.org)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-11-21 18:54:11"
|
||||
"lastUpdated": "2018-03-02 09:46:09"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2018 Justin Warren, Philipp Zumstein
|
||||
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
Zotero is free software: you can redistribute it and/or modify
|
||||
|
|
@ -35,9 +35,15 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
// attr()/text() v2
|
||||
function attr(docOrElem,selector,attr,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.getAttribute(attr):null;}function text(docOrElem,selector,index){var elem=index?docOrElem.querySelectorAll(selector).item(index):docOrElem.querySelector(selector);return elem?elem.textContent:null;}
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
var classes = attr(doc, 'body', 'class');
|
||||
|
||||
// Z.debug(classes);
|
||||
|
||||
if (classes.includes('case')) {
|
||||
return "case";
|
||||
}
|
||||
|
|
@ -53,13 +59,9 @@ function detectWeb(doc, url) {
|
|||
if (url.includes('austlii.edu.au/cgi-bin/sinodisp/au/cases/') && url.includes('.html')) {
|
||||
return "case";
|
||||
}
|
||||
if (url.includes('classic.austlii.edu.au') && url.includes('.html')) {
|
||||
return "case";
|
||||
}
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -67,7 +69,7 @@ function getSearchResults(doc, checkOnly) {
|
|||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('#page-main ul>li>a');
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
for (let i=0; i<rows.length; i++) {
|
||||
let href = rows[i].href;
|
||||
let title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
|
|
@ -80,111 +82,49 @@ function getSearchResults(doc, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
scrape(await requestDocument(url), url);
|
||||
}
|
||||
}
|
||||
else if (new URL(url).hostname === 'classic.austlii.edu.au') {
|
||||
let urlObj = new URL(url);
|
||||
urlObj.hostname = 'www.austlii.edu.au';
|
||||
url = urlObj.toString();
|
||||
scrape(await requestDocument(url), url);
|
||||
}
|
||||
else {
|
||||
function doWeb(doc, url) {
|
||||
var type = detectWeb(doc, url);
|
||||
if (type == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust some jurisdiction abbreviations
|
||||
*/
|
||||
var jurisdictionAbbrev = {
|
||||
"Commonwealth": "Cth",
|
||||
"CTH": "Cth",
|
||||
"Australian Capital Territory": "ACT",
|
||||
"New South Wales": "NSW",
|
||||
"Northern Territory": "NT",
|
||||
"Queensland": "Qld",
|
||||
"QLD": "Qld",
|
||||
"South Australia": "SA",
|
||||
"Tasmania": "Tas",
|
||||
"TAS": "Tas",
|
||||
"Victoria": "Vic",
|
||||
"VIC": "Vic",
|
||||
"Western Australia": "WA"
|
||||
};
|
||||
|
||||
/*
|
||||
* ZU.capitalizeTitle doesn't cope with Act Names (With Parenthetical Names) Acts
|
||||
* so we give it a bit of help.
|
||||
*/
|
||||
function capitalizeWithPunctuation(string) {
|
||||
const actNameDelimRegex = /( \(|\) )/;
|
||||
var words = string.split(actNameDelimRegex);
|
||||
|
||||
var newString = "";
|
||||
var lastWordIndex = words.length - 1;
|
||||
for (var i = 0; i <= lastWordIndex; i++) {
|
||||
if (actNameDelimRegex.test(words[i])) {
|
||||
newString += words[i];
|
||||
}
|
||||
else {
|
||||
newString += ZU.capitalizeTitle(words[i].toLowerCase(), true);
|
||||
}
|
||||
}
|
||||
return newString;
|
||||
}
|
||||
|
||||
/*
|
||||
* AustLII includes the date on the end of all Acts
|
||||
*/
|
||||
function parseActName(nameOfAct) {
|
||||
// Split at the last space before the year
|
||||
const parsed = nameOfAct.split(/\s(\d{4})/);
|
||||
// Zotero.debug(parsed);
|
||||
let actName = parsed[0], actYear = parsed[1];
|
||||
actName = capitalizeWithPunctuation(actName);
|
||||
return { actName, actYear };
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var type = detectWeb(doc, url);
|
||||
var newItem = new Zotero.Item(type);
|
||||
var fullJurisdiction = text(doc, 'li.ribbon-jurisdiction > a > span');
|
||||
var jurisdiction = jurisdictionAbbrev[fullJurisdiction] || fullJurisdiction;
|
||||
if (jurisdiction && ZU.fieldIsValidForType('code', type)) {
|
||||
newItem.code = jurisdiction;
|
||||
var jurisdiction = text(doc, 'li.ribbon-jurisdiction>a>span');
|
||||
if (jurisdiction) {
|
||||
newItem.extra = "jurisdiction: " + jurisdiction;
|
||||
}
|
||||
var citation = text(doc, 'li.ribbon-citation>a>span');
|
||||
var voliss;
|
||||
var m;
|
||||
|
||||
|
||||
|
||||
if (text(doc, '#ribbon')) {
|
||||
if (type == "case") {
|
||||
voliss = text(doc, 'head>title');
|
||||
var voliss = text(doc, 'head>title');
|
||||
// e.g. C & M [2006] FamCA 212 (20 January 2006)
|
||||
newItem.caseName = voliss.replace(/\s?\[.*$/, '');
|
||||
newItem.title = newItem.caseName;
|
||||
|
||||
var lastParenthesis = voliss.match(/\(([^)]*)\)$/);
|
||||
|
||||
var lastParenthesis = voliss.match(/\(([^\)]*)\)$/);
|
||||
if (lastParenthesis) {
|
||||
newItem.dateDecided = ZU.strToISO(lastParenthesis[1]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.dateDecided = text(doc, 'li.ribbon-year>a>span');
|
||||
}
|
||||
var courtAbbrevInURL = url.match(/\/cases\/[^/]+\/([^/]+)\//);
|
||||
if (courtAbbrevInURL) {
|
||||
newItem.court = decodeURIComponent(courtAbbrevInURL[1]);
|
||||
}
|
||||
else {
|
||||
// Full court name
|
||||
newItem.court = text(doc, 'li.ribbon-database > a > span');
|
||||
}
|
||||
newItem.court = text(doc, 'li.ribbon-database>a>span');
|
||||
if (citation) {
|
||||
var lastNumber = citation.match(/(\d+)$/);
|
||||
if (lastNumber) {
|
||||
|
|
@ -193,56 +133,49 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
if (type == "statute") {
|
||||
// All AustLII Act titles end in the year the Act was passed
|
||||
const actInfo = parseActName(citation);
|
||||
newItem.nameOfAct = actInfo.actName;
|
||||
newItem.dateEnacted = actInfo.actYear;
|
||||
// title
|
||||
newItem.nameOfAct = citation.trim();
|
||||
// section
|
||||
newItem.section = text(doc, 'li.ribbon-subject>a>span');
|
||||
if (newItem.section) newItem.section = newItem.section.replace(/^SECT /, '');
|
||||
}
|
||||
if (type == "journalArticle") {
|
||||
var title = text(doc, 'title');
|
||||
m = title.match(/(.*) --- "([^"]*)"/);
|
||||
var m = title.match(/(.*) --- "([^"]*)"/);
|
||||
if (m) {
|
||||
newItem.title = m[2];
|
||||
var authors = m[1].split(';');
|
||||
for (let i = 0; i < authors.length; i++) {
|
||||
for (let i=0; i<authors.length; i++) {
|
||||
newItem.creators.push(ZU.cleanAuthor(authors[i], 'author', authors[i].includes(',')));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.title = title;
|
||||
}
|
||||
newItem.publicationTitle = text(doc, 'li.ribbon-database>a>span');
|
||||
newItem.date = text(doc, 'li.ribbon-year>a>span');
|
||||
}
|
||||
}
|
||||
else {
|
||||
voliss = text(doc, 'head>title');
|
||||
} else {
|
||||
var voliss = text(doc, 'head>title');
|
||||
// e.g. C & M [2006] FamCA 212 (20 January 2006)
|
||||
m = voliss.match(/^([^[]*)\[(\d+)\](.*)\(([^)]*)\)$/);
|
||||
var m = voliss.match(/^([^[]*)\[(\d+)\](.*)\(([^\)]*)\)$/);
|
||||
if (m) {
|
||||
newItem.title = m[1];
|
||||
newItem.dateDecided = ZU.strToISO(m[4]);
|
||||
var courtNumber = m[3].trim().split(' ');
|
||||
if (courtNumber.length >= 2) {
|
||||
if (courtNumber.length>=2) {
|
||||
newItem.court = courtNumber[0];
|
||||
newItem.docketNumber = courtNumber[1].replace(/[^\w]*$/, '');
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.title = voliss;
|
||||
}
|
||||
}
|
||||
|
||||
newItem.url = url
|
||||
.replace(/^http:\/\//, 'https://')
|
||||
.replace(/^(https:\/\/www)\d/, '$1');
|
||||
|
||||
newItem.url = url;
|
||||
newItem.attachments = [{
|
||||
document: doc,
|
||||
title: "Snapshot",
|
||||
mimeType: "text/html"
|
||||
mimeType:"text/html"
|
||||
}];
|
||||
newItem.complete();
|
||||
}
|
||||
|
|
@ -251,16 +184,17 @@ function scrape(doc, url) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"url": "http://www7.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "C & M",
|
||||
"creators": [],
|
||||
"dateDecided": "2006-01-20",
|
||||
"court": "FamCA",
|
||||
"court": "Family Court of Australia",
|
||||
"docketNumber": "212",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www7.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -275,16 +209,17 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Yeo, in the matter of AES Services (Aust) Pty Ltd (ACN 111 306 543) (Administrators Appointed)",
|
||||
"creators": [],
|
||||
"dateDecided": "2010-01-05",
|
||||
"court": "FCA",
|
||||
"court": "Federal Court of Australia",
|
||||
"docketNumber": "1",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -308,7 +243,7 @@ var testCases = [
|
|||
"dateDecided": "2008-02-08",
|
||||
"court": "NZSC",
|
||||
"docketNumber": "1",
|
||||
"url": "https://www.nzlii.org/nz/cases/NZSC/2008/1.html",
|
||||
"url": "http://www.nzlii.org/nz/cases/NZSC/2008/1.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -323,21 +258,22 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewtoc/au/cases/act/ACTSC/2010/",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewtoc/au/cases/act/ACTSC/2010/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "'NM' and Department of Human Services (Freedom of information)",
|
||||
"creators": [],
|
||||
"dateDecided": "2017-12-08",
|
||||
"court": "AICmr",
|
||||
"court": "Australian Information Commissioner",
|
||||
"docketNumber": "134",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -352,16 +288,15 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Freedom of Information Act",
|
||||
"nameOfAct": "Freedom of Information Act 1982",
|
||||
"creators": [],
|
||||
"dateEnacted": "1982",
|
||||
"code": "Cth",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"section": "24AB",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -376,15 +311,14 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Freedom of Information Act",
|
||||
"nameOfAct": "Freedom of Information Act 1982",
|
||||
"creators": [],
|
||||
"dateEnacted": "1982",
|
||||
"code": "Cth",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"extra": "jurisdiction: CTH",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -399,53 +333,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/antsasta1999402/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "A New Tax System (Goods and Services Tax) Act",
|
||||
"creators": [],
|
||||
"dateEnacted": "1999",
|
||||
"code": "Cth",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/antsasta1999402/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/caca2010265/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Competition and Consumer Act",
|
||||
"creators": [],
|
||||
"dateEnacted": "2010",
|
||||
"code": "Cth",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/caca2010265/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"url": "http://www9.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -465,7 +353,7 @@ var testCases = [
|
|||
"date": "2010",
|
||||
"libraryCatalog": "AustLII and NZLII",
|
||||
"publicationTitle": "Administrative Review Council - Admin Review",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"url": "http://www9.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -480,12 +368,12 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/sinosrch.cgi?mask_path=;method=auto;query=adam%20smith;view=relevance&mask_path=au/cases/act/ACTCA",
|
||||
"url": "http://www7.austlii.edu.au/cgi-bin/sinosrch.cgi?mask_path=;method=auto;query=adam%20smith;view=relevance&mask_path=au/cases/act/ACTCA",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www6.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/20.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/sinodisp/au/cases/cth/AICmr/2017/20.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
|
|
@ -494,100 +382,7 @@ var testCases = [
|
|||
"dateDecided": "2017-03-10",
|
||||
"court": "AICmr",
|
||||
"docketNumber": "20",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/20.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/qld/consol_act/pla1974179/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Property Law Act",
|
||||
"creators": [],
|
||||
"dateEnacted": "1974",
|
||||
"code": "Qld",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/qld/consol_act/pla1974179/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/vic/consol_act/ca195882/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Crimes Act",
|
||||
"creators": [],
|
||||
"dateEnacted": "1958",
|
||||
"code": "Vic",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/vic/consol_act/ca195882/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/nsw/consol_act/leara2002451/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Law Enforcement (Powers and Responsibilities) Act",
|
||||
"creators": [],
|
||||
"dateEnacted": "2002",
|
||||
"code": "NSW",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/nsw/consol_act/leara2002451/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FedCFamC1A/2024/214.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Dimitrova & Carman",
|
||||
"creators": [],
|
||||
"dateDecided": "2024-11-15",
|
||||
"court": "FedCFamC1A",
|
||||
"docketNumber": "214",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FedCFamC1A/2024/214.html",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/sinodisp/au/cases/cth/AICmr/2017/20.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
136
BAILII.js
136
BAILII.js
|
|
@ -9,128 +9,113 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-09-16 20:57:17"
|
||||
"lastUpdated": "2014-04-03 16:36:35"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Bill McKinney
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
var liiRegexp = /^https?:\/\/www\.bailii\.org(?:\/cgi-bin\/markup\.cgi\?doc=)?\/\w+\/cases\/.+\.html/;
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
var liiRegexp= /^https?:\/\/www\.bailii\.org(?:\/cgi\-bin\/markup\.cgi\?doc\=)?\/\w+\/cases\/.+\.html/
|
||||
if (liiRegexp.test(url)) {
|
||||
return "case";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
var aTags = doc.getElementsByTagName("a");
|
||||
for (var i = 0; i < aTags.length; i++) {
|
||||
for (var i=0; i<aTags.length; i++) {
|
||||
if (liiRegexp.test(aTags[i].href)) {
|
||||
return "multiple";
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var newItem = new Zotero.Item("case");
|
||||
newItem.title = doc.title;
|
||||
newItem.url = doc.location.href;
|
||||
var titleRegexp = /^(.+)\s+\[(\d+)\]\s+(.+)\s+\((\d+)\s+(\w+)\s+(\d+)\)/;
|
||||
var titleMatch = titleRegexp.exec(doc.title);
|
||||
if (titleMatch) {
|
||||
var titleRegexp = /^(.+)\s+\[(\d+)\]\s+(.+)\s+\((\d+)\s+(\w+)\s+(\d+)\)/
|
||||
var titleMatch = titleRegexp .exec(doc.title);
|
||||
if (titleMatch ) {
|
||||
newItem.caseName = titleMatch[1] + " [" + titleMatch[2] + "] " + titleMatch[3];
|
||||
newItem.dateDecided = titleMatch[4] + " " + titleMatch[5] + " " + titleMatch[6];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.caseName = doc.title;
|
||||
newItem.dateDecided = "not found";
|
||||
}
|
||||
|
||||
var courtRegexp = /cases\/([^/]+)\/([^/]+)\//;
|
||||
var courtRegexp = /cases\/([^\/]+)\/([^\/]+)\//
|
||||
var courtMatch = courtRegexp.exec(doc.location.href);
|
||||
if (courtMatch) {
|
||||
var divRegexp = /\w+/;
|
||||
var divRegexp = /\w+/
|
||||
var divMatch = divRegexp.exec(courtMatch[2]);
|
||||
if (divMatch) {
|
||||
newItem.court = courtMatch[1] + " (" + courtMatch[2] + ")";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.court = courtMatch[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newItem.court = "not found";
|
||||
}
|
||||
|
||||
// judge
|
||||
var panel = doc.getElementsByTagName("PANEL");
|
||||
if (panel.length > 0) {
|
||||
let name = panel[0].innerHTML;
|
||||
newItem.creators.push({ lastName: name, creatorType: "author", fieldMode: 1 });
|
||||
var tmp = panel[0].innerHTML;
|
||||
newItem.creators.push({lastName:tmp, creatorType:"judge", fieldMode:true});
|
||||
|
||||
}
|
||||
// citation
|
||||
var cite = doc.getElementsByTagName("CITATION");
|
||||
if (cite.length > 0) {
|
||||
let note = cite[0].childNodes[0].innerHTML;
|
||||
newItem.notes.push({ note });
|
||||
var tmpc = cite[0].childNodes[0].innerHTML;
|
||||
newItem.notes.push({note:tmpc});
|
||||
}
|
||||
newItem.attachments = [{ url: url, title: "Snapshot", mimeType: "text/html" }];
|
||||
newItem.attachments = [{url: url, title: "BAILII Snapshot", mimeType: "text/html"}];
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var liiRegexp= /http:\/\/www\.bailii\.org(?:\/cgi\-bin\/markup\.cgi\?doc\=)?\/\w+\/cases\/.+\.html/
|
||||
if (liiRegexp.test(url)) {
|
||||
scrape(doc);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
var items = Zotero.Utilities.getItemArray(doc, doc, liiRegexp);
|
||||
var urls = new Array();
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
for (var i in items) {
|
||||
urls.push(i);
|
||||
}
|
||||
Zotero.Utilities.processDocuments(urls, scrape, function () {
|
||||
Zotero.done();
|
||||
});
|
||||
Zotero.wait();
|
||||
});
|
||||
}
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bailii.org/cgi-bin/markup.cgi?doc=/eu/cases/EUECJ/2011/C40308.html&query=copyright&method=boolean",
|
||||
"url": "http://www.bailii.org/cgi-bin/markup.cgi?doc=/eu/cases/EUECJ/2011/C40308.html&query=copyright&method=boolean",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Football Association Premier League & Ors (Freedom to provide services) [2011] EUECJ C-403/08",
|
||||
"creators": [],
|
||||
"dateDecided": "04 October 2011",
|
||||
"court": "EUECJ (2011)",
|
||||
"url": "https://www.bailii.org/cgi-bin/markup.cgi?doc=/eu/cases/EUECJ/2011/C40308.html&query=copyright&method=boolean",
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"title": "BAILII Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"title": "Football Association Premier League & Ors (Freedom to provide services) [2011] EUECJ C-403/08",
|
||||
"url": "http://www.bailii.org/cgi-bin/markup.cgi?doc=/eu/cases/EUECJ/2011/C40308.html&query=copyright&method=boolean",
|
||||
"caseName": "Football Association Premier League & Ors (Freedom to provide services) [2011] EUECJ C-403/08",
|
||||
"dateDecided": "04 October 2011",
|
||||
"court": "EUECJ (2011)",
|
||||
"libraryCatalog": "BAILII",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -138,39 +123,6 @@ var testCases = [
|
|||
"type": "web",
|
||||
"url": "http://www.bailii.org/eu/cases/EUECJ/2007/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bailii.org/ew/cases/EWHC/Comm/2020/170.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Forum Services International Ltd & Anor v OOS International BV [2020] EWHC 170 (Comm)",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "MR JUSTICE ROBIN KNOWLES CBE",
|
||||
"creatorType": "author",
|
||||
"fieldMode": true
|
||||
}
|
||||
],
|
||||
"dateDecided": "31 January 2020",
|
||||
"court": "EWHC (Comm)",
|
||||
"url": "https://www.bailii.org/ew/cases/EWHC/Comm/2020/170.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "Neutral Citation Number: [2020] EWHC 170 (Comm)"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
37
BIBSYS.js
37
BIBSYS.js
|
|
@ -8,8 +8,8 @@
|
|||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-12-28 04:44:52"
|
||||
"browserSupport": "gcsbv",
|
||||
"lastUpdated": "2014-04-04 10:08:22"
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
|
|
@ -33,24 +33,21 @@ function doWeb(doc, url) {
|
|||
titles.iterateNext();
|
||||
while (title=titles.iterateNext())
|
||||
items[codes.iterateNext().nodeValue]=title.nodeValue;
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) return;
|
||||
var string="http://ask.bibsys.no/ask/action/result?control=ctr_top";
|
||||
for (var codes in items)
|
||||
string+="&valg="+codes;
|
||||
string+="&control=ctr_bottom&eksportFormat=refmanager&eksportEpostAdresse=&eksportEpostFormat=fortekst&cmd=sendtil";
|
||||
Zotero.Utilities.HTTP.doGet(string, function(text) {
|
||||
var trans=Zotero.loadTranslator("import");
|
||||
trans.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
trans.setString(text);
|
||||
trans.setHandler("itemDone", function(obj, item) {
|
||||
item.title = item.title.replace(/\s\s+/, " ").replace(/\s:/, ":");
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
items=Zotero.selectItems(items);
|
||||
var string="http://ask.bibsys.no/ask/action/result?control=ctr_top";
|
||||
for (var codes in items)
|
||||
string+="&valg="+codes;
|
||||
string+="&control=ctr_bottom&eksportFormat=refmanager&eksportEpostAdresse=&eksportEpostFormat=fortekst&cmd=sendtil";
|
||||
Zotero.Utilities.HTTP.doGet(string, function(text) {
|
||||
var trans=Zotero.loadTranslator("import");
|
||||
trans.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
trans.setString(text);
|
||||
trans.setHandler("itemDone", function(obj, item) {
|
||||
item.title = item.title.replace(/\s\s+/, " ").replace(/\s:/, ":");
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
return;
|
||||
}
|
||||
var singlereg=new RegExp("http://ask\.bibsys\.no/ask/action/show");
|
||||
if (singlereg.test(url)) {
|
||||
|
|
@ -109,4 +106,4 @@ var testCases = [
|
|||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
229
BOE.js
229
BOE.js
|
|
@ -1,229 +0,0 @@
|
|||
{
|
||||
"translatorID": "3f1b68b1-8ee7-4ab7-a514-185d72b2f80d",
|
||||
"label": "BOE",
|
||||
"creator": "Félix Brezo (@febrezo)",
|
||||
"target": "^https?://([a-z]+\\.)?boe\\.es/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-26 17:07:40"
|
||||
}
|
||||
|
||||
/*
|
||||
BOE Translator
|
||||
Copyright (C) 2020-2021 Félix Brezo, felixbrezo@disroot.org
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the Affero GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes("diario_boe") || url.includes("www.boe.es/eli") || url.includes("/doc.php")) {
|
||||
return "statute";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var resourceType = detectWeb(doc, url);
|
||||
var newItem = new Zotero.Item(resourceType);
|
||||
|
||||
var metadataUri;
|
||||
if (!url.includes("/xml")) {
|
||||
var index = 0;
|
||||
|
||||
while (true) {
|
||||
index++;
|
||||
metadataUri = ZU.xpathText(doc, "(//meta[@property='http://data.europa.eu/eli/ontology#is_embodied_by'])[" + index + "]/@resource");
|
||||
if (!metadataUri || metadataUri.includes("/xml")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
metadataUri = url;
|
||||
}
|
||||
|
||||
Zotero.Utilities.HTTP.doGet(metadataUri, function (resText) {
|
||||
// Clean and parse metadata web
|
||||
resText = resText.replace(/<!DOCTYPE[^>]*>/, "").replace(/<\?xml[^>]*\?>/, "");
|
||||
resText = Zotero.Utilities.trim(resText);
|
||||
var parser = new DOMParser();
|
||||
var metadataDoc = parser.parseFromString(resText, "text/xml");
|
||||
|
||||
// Start scraping
|
||||
var tmpAuthor = ZU.xpathText(metadataDoc, "//departamento");
|
||||
if (tmpAuthor) {
|
||||
newItem.creators.push({ lastName: tmpAuthor, creatorType: "author", fieldMode: 1 });
|
||||
}
|
||||
|
||||
var tmpDate = ZU.xpathText(metadataDoc, "//fecha_publicacion");
|
||||
newItem.dateEnacted = ZU.strToISO(tmpDate.substring(0, 4) + "/" + tmpDate.substring(4, 6) + "/" + tmpDate.substring(6, 8));
|
||||
|
||||
newItem.nameOfAct = ZU.xpathText(metadataDoc, "//titulo").replace(/\.$/, ""); // Remove trailing dot
|
||||
newItem.section = ZU.xpathText(metadataDoc, "//seccion");
|
||||
newItem.pages = ZU.xpathText(metadataDoc, "//pagina_inicial") + "-" + ZU.xpathText(metadataDoc, "//pagina_final");
|
||||
newItem.session = ZU.xpathText(metadataDoc, "//diario") + " núm. " + ZU.xpathText(metadataDoc, "//diario_numero");
|
||||
newItem.codeNumber = ZU.xpathText(metadataDoc, "//identificador");
|
||||
newItem.publicLawNumber = ZU.xpathText(metadataDoc, "//rango") + " " + ZU.xpathText(metadataDoc, "//numero_oficial");
|
||||
newItem.url = ZU.xpathText(metadataDoc, "//url_eli");
|
||||
|
||||
// Adding the attachment
|
||||
newItem.attachments.push({
|
||||
title: "Snapshot",
|
||||
mimeType: "text/html",
|
||||
url: url
|
||||
});
|
||||
|
||||
newItem.complete();
|
||||
});
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.boe.es/eli/es/rd/2020/06/30/614",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Real Decreto 614/2020, de 30 de junio, por el que se establece una cualificación profesional de la familia profesional Comercio y Marketing, que se incluye en el Catálogo Nacional de Cualificaciones Profesionales",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Ministerio de Educación y Formación Profesional",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"dateEnacted": "2020-07-20",
|
||||
"codeNumber": "BOE-A-2020-8150",
|
||||
"pages": "53856-53876",
|
||||
"publicLawNumber": "Real Decreto 614/2020",
|
||||
"section": "1",
|
||||
"session": "Boletín Oficial del Estado núm. 197",
|
||||
"url": "https://www.boe.es/eli/es/rd/2020/06/30/614",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.boe.es/eli/es/rd/2020/06/30/614/dof/spa/xml",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Real Decreto 614/2020, de 30 de junio, por el que se establece una cualificación profesional de la familia profesional Comercio y Marketing, que se incluye en el Catálogo Nacional de Cualificaciones Profesionales",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Ministerio de Educación y Formación Profesional",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"dateEnacted": "2020-07-20",
|
||||
"codeNumber": "BOE-A-2020-8150",
|
||||
"pages": "53856-53876",
|
||||
"publicLawNumber": "Real Decreto 614/2020",
|
||||
"section": "1",
|
||||
"session": "Boletín Oficial del Estado núm. 197",
|
||||
"url": "https://www.boe.es/eli/es/rd/2020/06/30/614",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.boe.es/diario_boe/xml.php?id=BOE-A-1978-31229",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Constitución Española",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Cortes Generales",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"dateEnacted": "1978-12-29",
|
||||
"codeNumber": "BOE-A-1978-31229",
|
||||
"pages": "29313-29424",
|
||||
"publicLawNumber": "Constitución",
|
||||
"section": "1",
|
||||
"session": "Boletín Oficial del Estado núm. 311",
|
||||
"url": "https://www.boe.es/eli/es/c/1978/12/27/(1)",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.boe.es/buscar/doc.php?id=BOE-A-1978-31229",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Constitución Española",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Cortes Generales",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"dateEnacted": "1978-12-29",
|
||||
"codeNumber": "BOE-A-1978-31229",
|
||||
"pages": "29313-29424",
|
||||
"publicLawNumber": "Constitución",
|
||||
"section": "1",
|
||||
"session": "Boletín Oficial del Estado núm. 311",
|
||||
"url": "https://www.boe.es/eli/es/c/1978/12/27/(1)",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-06-16 17:43:54"
|
||||
"lastUpdated": "2019-12-24 12:46:21"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -88,12 +88,9 @@ function doWeb(doc, url) {
|
|||
|
||||
function scrape(doc, _url) {
|
||||
var dataUrl = attr(doc, 'i.reqdata', 'url');
|
||||
let paperId = undefined;
|
||||
const paperIdMatches = _url.match(/paperid=([a-z0-9]*)/i);
|
||||
if (paperIdMatches[1]) {
|
||||
paperId = paperIdMatches[1];
|
||||
}
|
||||
const risUrl = `https://xueshu.baidu.com/u/citation?type=ris&paperid=${paperId}`;
|
||||
var diversion = attr(doc, 'i.reqdata', 'diversion');
|
||||
var sign = attr(doc, 'a.sc_q', 'data-sign');
|
||||
var risUrl = "http://xueshu.baidu.com/u/citation?&url=" + encodeURIComponent(dataUrl) + "&sign=" + sign + "&diversion=" + diversion + "&t=ris";
|
||||
var title = doc.title.replace('_百度学术', '');
|
||||
|
||||
var tags = [];
|
||||
|
|
@ -102,6 +99,7 @@ function scrape(doc, _url) {
|
|||
// Z.debug({ ris });
|
||||
// delete parenthesis in pages information, e.g. SP - 5-7(3)
|
||||
ris = ris.replace(/(SP\s+-\s\d+-\d+)\(\d+\)$/m, "$1");
|
||||
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(ris);
|
||||
|
|
@ -153,20 +151,19 @@ function scrape(doc, _url) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://xueshu.baidu.com/usercenter/paper/show?paperid=b3ab239032d44d951d8eee26d7bc44bf&site=xueshu_se",
|
||||
"url": "http://xueshu.baidu.com/usercenter/paper/show?paperid=b3ab239032d44d951d8eee26d7bc44bf&site=xueshu_se",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Zotero: information management software 2.0",
|
||||
"title": "Zotero: Information management software 2.0",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Fernandez",
|
||||
"firstName": "P.",
|
||||
"firstName": "Peter",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
|
|
@ -178,12 +175,11 @@ var testCases = [
|
|||
"pages": "5-7",
|
||||
"publicationTitle": "Library Hi Tech News",
|
||||
"shortTitle": "Zotero",
|
||||
"url": "http://www.emeraldinsight.com/doi/pdfplus/10.1108/07419051111154758",
|
||||
"url": "http://www.emeraldinsight.com/doi/full/10.1108/07419051111154758",
|
||||
"volume": "28",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -213,7 +209,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://xueshu.baidu.com/usercenter/paper/show?paperid=29fcf50a863692823c3f336a9ee1efea&site=xueshu_se",
|
||||
"url": "http://xueshu.baidu.com/s?wd=paperuri%3A%2829fcf50a863692823c3f336a9ee1efea%29&filter=sc_long_sign&sc_ks_para=q%3DComparativo%20dos%20softwares%20de%20gerenciamento%20de%20refer%C3%AAncias%20bibliogr%C3%A1ficas%3A%20Mendeley%2C%20EndNote%20e%20Zotero&sc_us=1497086148200551335&tn=SE_baiduxueshu_c1gjeupa&ie=utf-8",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -221,44 +217,30 @@ var testCases = [
|
|||
"creators": [
|
||||
{
|
||||
"lastName": "Yamakawa",
|
||||
"firstName": "E. K.",
|
||||
"firstName": "Eduardo Kazumi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Kubota",
|
||||
"firstName": "F. I.",
|
||||
"firstName": "Flávio Issao",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Beuren",
|
||||
"firstName": "F. H.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Scalvenzi",
|
||||
"firstName": "L.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Miguel",
|
||||
"firstName": "Pac",
|
||||
"firstName": "Fernanda Hansch",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"DOI": "10.1590/0103-37862014000200006",
|
||||
"abstractNote": "A elaboração de uma revisão bibliográfica confiável, a partir de trabalhos relevantes publicados anteriormente, é fundamental para evidenciar a originalidade e a contribuição científica dos trabalhos de pesquisa. Devido à grande quantidade de bases de dados e de publicações disponíveis, torna-se necessário utilizar ferramentas que auxiliem na gestão das referências bibliográficas de uma maneira fácil e padronizada. O objetivo deste artigo é examinar três de gerenciamento bibliográfico utilizados com frequência por pesquisadores acadêmicos, são eles: , e . Nesse sentido, buscou-se, em primeiro lugar, evidenciar seus principais benefícios e as possíveis dificuldades de utilização. Em segundo lugar, procurou-se comparar suas principais características por meio de uma pesquisa teórico-conceitual baseada em literatura especializada, o que permitiu utilizá-los e analisá-los de maneira crítica. Assim sendo, evidenciou-se as principais particularidades de cada e foi elaborado um quadro comparativo entre os mesmos. Considerando as características analisadas nos três , concluiu-se que todos, ao mesmo tempo em que facilitam o trabalho dos pesquisadores, possuem ferramentas que facilitam as buscas, a organização e a análise dos artigos.",
|
||||
"issue": "2",
|
||||
"libraryCatalog": "Baidu Scholar",
|
||||
"pages": "167-176",
|
||||
"publicationTitle": "Transinformao",
|
||||
"publicationTitle": "Transinformação",
|
||||
"shortTitle": "Comparativo dos softwares de gerenciamento de referências bibliográficas",
|
||||
"url": "http://www.scielo.br/scielo.php?script=sci_arttext&pid=S0103-37862014000200167&lng=pt&nrm=is",
|
||||
"volume": "26",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -269,7 +251,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://xueshu.baidu.com/s?wd=zotero&rsv_bp=0&tn=SE_baiduxueshu_c1gjeupa&rsv_spt=3&ie=utf-8&f=8&rsv_sug2=0&sc_f_para=sc_tasktype%3D%7BfirstSimpleSearch%7D",
|
||||
"url": "http://xueshu.baidu.com/s?wd=zotero&rsv_bp=0&tn=SE_baiduxueshu_c1gjeupa&rsv_spt=3&ie=utf-8&f=8&rsv_sug2=0&sc_f_para=sc_tasktype%3D%7BfirstSimpleSearch%7D",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "7f74d823-d2ba-481c-b717-8b12c90ed874",
|
||||
"label": "Bangkok Post",
|
||||
"creator": "Matt Mayer",
|
||||
"target": "^https://www\\.bangkokpost\\.com/[a-z0-9-]+/([a-z0-9-]+/)?[0-9]+",
|
||||
"target": "^https://www.bangkokpost.com/[a-z0-9-]+/([a-z0-9-]+/)?[0-9]+",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-06-18 20:46:45"
|
||||
"lastUpdated": "2020-09-08 07:45:28"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -41,7 +41,13 @@ function detectWeb(_doc, _url) {
|
|||
function doWeb(doc, url) {
|
||||
scrape(doc, url);
|
||||
}
|
||||
|
||||
function getMetaTag(doc, attr, value, contentattr) {
|
||||
const tag = Array.from(doc.getElementsByTagName("meta")).filter(m => m.attributes[attr] && m.attributes[attr].value == value)[0];
|
||||
if (tag && tag.attributes[contentattr]) {
|
||||
return tag.attributes[contentattr].value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function scrape(doc, _url) {
|
||||
const translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
|
|
@ -51,15 +57,12 @@ function scrape(doc, _url) {
|
|||
translator.setHandler('itemDone', function (obj, item) {
|
||||
// Add data for fields that are not covered by Embedded Metadata
|
||||
// Author name is stored as firstname lastname
|
||||
let authorName = attr(doc, "meta[name='lead:author']", "content");
|
||||
if (!authorName) {
|
||||
authorName = text(doc, '.info-opinion .columnnist-name a');
|
||||
}
|
||||
const authorName = getMetaTag(doc, "property", "cXenseParse:author", "content");
|
||||
if (authorName) {
|
||||
item.creators = [ZU.cleanAuthor(authorName, "author", false)];
|
||||
}
|
||||
// Date is stored as a timestamp like 2020-09-07T17:37:00+07:00, just extract the YYYY-MM-DD at start
|
||||
const date = attr(doc, "meta[name='lead:published_at']", "content");
|
||||
const date = getMetaTag(doc, "name", "cXenseParse:recs:publishtime", "content");
|
||||
if (date) {
|
||||
item.date = date.substr(0, 10);
|
||||
}
|
||||
|
|
@ -70,9 +73,7 @@ function scrape(doc, _url) {
|
|||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
|
|
@ -90,7 +91,6 @@ var testCases = [
|
|||
],
|
||||
"date": "2020-09-07",
|
||||
"abstractNote": "A general debate without a vote in the House of Representatives has been scheduled for Wednesday for MPs to question the government on the current economic and political crises and suggest ways of solving related problems.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.bangkokpost.com",
|
||||
"publicationTitle": "Bangkok Post",
|
||||
"url": "https://www.bangkokpost.com/thailand/politics/1981267/house-general-debate-set-for-wednesday",
|
||||
|
|
@ -121,7 +121,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bangkokpost.com/life/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"url": "https://www.bangkokpost.com/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
|
|
@ -135,10 +135,9 @@ var testCases = [
|
|||
],
|
||||
"date": "2020-09-03",
|
||||
"abstractNote": "The Royal Thai Air Force’s first security satellite, Napa-1, was successfully launched on a European rocket from French Guiana on Thursday morning.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.bangkokpost.com",
|
||||
"publicationTitle": "Bangkok Post",
|
||||
"url": "https://www.bangkokpost.com/life/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"url": "https://www.bangkokpost.com/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -182,8 +181,7 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2020-09-08",
|
||||
"abstractNote": "Southeast Asia relies heavily on tourism. In 2019, the travel and tourism industry contributed 12.1% of the region",
|
||||
"language": "en",
|
||||
"abstractNote": "Southeast Asia relies heavily on tourism. In 2019, the travel and tourism industry contributed 12.1% of the region's GDP and approximately one in 10 people are employed within and around it, according to the World Travel and Tourism Council (WTTC).",
|
||||
"libraryCatalog": "www.bangkokpost.com",
|
||||
"publicationTitle": "Bangkok Post",
|
||||
"url": "https://www.bangkokpost.com/opinion/opinion/1981587/tech-is-key-to-rebooting-tourism",
|
||||
|
|
|
|||
|
|
@ -1,175 +0,0 @@
|
|||
{
|
||||
"translatorID": "283d6b78-d3d7-48d4-8fc0-0bdabef7c4ee",
|
||||
"label": "Baruch Foundation",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://baruchfoundation\\.org/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-20 18:55:13"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.querySelector('#img-artist')) {
|
||||
return "artwork";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h4 > a[href*=".jpg.php"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
let item = new Zotero.Item('artwork');
|
||||
|
||||
item.title = text(doc, 'h1#title b');
|
||||
item.abstractNote = text(doc, '.description');
|
||||
item.artworkMedium = [...doc.querySelectorAll('.taglist a')]
|
||||
.map(a => a.innerText.trim()).join(', ');
|
||||
item.artworkSize = text(doc, '.zp_uneditable_image_location'); // not sure why this class
|
||||
item.date = text(doc, '.zp_uneditable_image_city'); // again...
|
||||
if (item.date.trim() == 'no date') item.date = '';
|
||||
item.archive = 'Baruch Foundation';
|
||||
item.url = url;
|
||||
item.rights = text(doc, '.credit');
|
||||
|
||||
item.creators.push(ZU.cleanAuthor(
|
||||
text(doc, '#img-artist em').replace(/^Dr\.?\b/, ''),
|
||||
'artist'
|
||||
));
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Image',
|
||||
mimeType: 'image/jpeg',
|
||||
url: attr(doc, '#img-full', 'href')
|
||||
});
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://baruchfoundation.org/banka/banka_portrait-with-coiled-wire.jpg.php",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Portrait with Coiled Wire",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Pavel",
|
||||
"lastName": "Baňka",
|
||||
"creatorType": "artist"
|
||||
}
|
||||
],
|
||||
"date": "1986",
|
||||
"archive": "Baruch Foundation",
|
||||
"artworkMedium": "Gelatin Silver Print, Toned Photograph",
|
||||
"artworkSize": "12 1/4 x 15 5/16 in.",
|
||||
"libraryCatalog": "Baruch Foundation",
|
||||
"url": "http://baruchfoundation.org/banka/banka_portrait-with-coiled-wire.jpg.php",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Image",
|
||||
"mimeType": "image/jpeg"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://baruchfoundation.org/j_feyfar/j_feyfar_untitled-stream-in-woods.jpg.php",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Untitled (Wooded Landscape with Stream)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jaroslav",
|
||||
"lastName": "Feyfar",
|
||||
"creatorType": "artist"
|
||||
}
|
||||
],
|
||||
"abstractNote": "on blue mount",
|
||||
"archive": "Baruch Foundation",
|
||||
"artworkMedium": "Black And White Photograph, Gelatin Silver Print",
|
||||
"artworkSize": "4 3/4 x 3 1/2 in.",
|
||||
"libraryCatalog": "Baruch Foundation",
|
||||
"url": "http://baruchfoundation.org/j_feyfar/j_feyfar_untitled-stream-in-woods.jpg.php",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Image",
|
||||
"mimeType": "image/jpeg"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://baruchfoundation.org/balcar",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
280
Beobachter.js
280
Beobachter.js
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"translatorID": "a571680e-6338-46c2-a740-3cd9eb80fc7f",
|
||||
"label": "Beobachter",
|
||||
"creator": "Sebastian Karcher",
|
||||
"creator": "ibex",
|
||||
"target": "^https?://((www\\.)?beobachter\\.ch/.)",
|
||||
"minVersion": "2.1.9",
|
||||
"maxVersion": "",
|
||||
|
|
@ -9,96 +9,177 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-02-05 20:11:36"
|
||||
"lastUpdated": "2016-09-07 21:24:35"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Beobachter Translator - Parses Beobachter articles and creates Zotero-based
|
||||
metadata.
|
||||
Copyright (C) 2011 ibex
|
||||
|
||||
Copyright © 2022 Sebastian Karcher
|
||||
|
||||
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
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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,
|
||||
This program 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.
|
||||
GNU 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 *****
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
if (doc.getElementsByClassName('article-header').length > 0) {
|
||||
/*
|
||||
Reference URLs:
|
||||
Article: http://www.beobachter.ch/natur/natuerlich-leben/wohnen-freizeit/artikel/beleuchtung_es-werde-led/
|
||||
Topic list: http://www.beobachter.ch/natur/forschung-wissen/
|
||||
*/
|
||||
|
||||
/* Zotero API */
|
||||
function detectWeb(doc, url) {
|
||||
// Z.debug("ibex detectWeb URL = " + url);
|
||||
if (doc.location.href.match(/.*\/artikel\//i) && (ZU.xpath(doc, '//div[' + containingClass('mediaarticleSingleView') + ']//h3').length > 0)) {
|
||||
return "magazineArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
// AJAX-ified results are currently not compatible with Zotero.
|
||||
// The following condition is not useful:
|
||||
// http://forums.zotero.org/discussion/18518/import-citation-from-an-ajaxbased-site/
|
||||
// } else if (doc.location.href.match(/\/suche\//i) && (ZU.xpath(doc, '//div[@id = "multiSerachListContainer"]') + ']').length > 0)) {
|
||||
} else if (ZU.xpath(doc, '//html/body[' + containingClass('article') + ']').length > 0) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
|
||||
var rows = doc.querySelectorAll('a[class*="teaser"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = text(row, 'span');
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
/* Zotero API */
|
||||
function doWeb(doc, url) {
|
||||
// Z.debug("ibex doWeb URL = " + url);
|
||||
var urls = new Array();
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url) {
|
||||
var authors = doc.querySelectorAll('meta[name="parsely-author"]');
|
||||
var date = attr(doc, 'meta[name="published_at"]', 'content');
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
// translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
for (let author of authors) {
|
||||
item.creators.push(ZU.cleanAuthor(author.content, "author"));
|
||||
var items = ZU.getItemArray(doc, doc.getElementById("mainContent").getElementsByTagName('h3'), '.*');
|
||||
if (!items || countObjectProperties(items) == 0) {
|
||||
return true;
|
||||
}
|
||||
items = Z.selectItems(items);
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
item.title = item.title.replace(/\s*\|\s*Beobachter/, "");
|
||||
item.date = date;
|
||||
item.ISSN = "1661-7444";
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = "magazineArticle";
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
for (var i in items) {
|
||||
urls.push(i);
|
||||
}
|
||||
} else {
|
||||
urls.push(doc.location.href);
|
||||
}
|
||||
ZU.processDocuments(urls, scrape);
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
/* Zotero API */
|
||||
function scrape(doc) {
|
||||
// Z.debug("ibex scrape URL = " + doc.location.href);
|
||||
|
||||
// Fetch meta tags and fill meta tag array for associateMeta() function
|
||||
var metaTags = fetchMeta(doc);
|
||||
|
||||
var newItem = new Z.Item('magazineArticle');
|
||||
newItem.url = doc.location.href;
|
||||
var shortTitle = ZU.xpath(doc, '//div[' + containingClass('mediaarticleSingleView') + ']//h3');
|
||||
if (shortTitle.length > 0) {
|
||||
newItem.shortTitle = ZU.trimInternal(shortTitle[0].textContent);
|
||||
}
|
||||
|
||||
associateMeta(newItem, metaTags, "DC.title", "title");
|
||||
associateMeta(newItem, metaTags, "DC.date", "date");
|
||||
associateMeta(newItem, metaTags, "publisher", "publicationTitle");
|
||||
associateMeta(newItem, metaTags, "abstract", "abstractNote");
|
||||
associateMeta(newItem, metaTags, "DC.Language", "language");
|
||||
// Other potentially usful meta data: DC.keywords
|
||||
|
||||
newItem.ISSN = "1661-7444";
|
||||
|
||||
var authorline = ZU.xpath(doc, '//div[' + containingClass('mediaarticleSingleView') + ']//dl/dt[. = "Autor:"]');
|
||||
if (authorline.length > 0) {
|
||||
authorline = ZU.trimInternal(authorline[0].nextSibling.textContent);
|
||||
// Assumption of authorline: "name1[, name2] [und Name3]"
|
||||
var authors = authorline.split(/,|und/);
|
||||
for (var i = 0; i < authors.length && authorline.length > 0; i++) {
|
||||
newItem.creators.push(ZU.cleanAuthor(authors[i], "author"));
|
||||
}
|
||||
}
|
||||
|
||||
var issueDt = ZU.xpath(doc, '//div[' + containingClass('mediaarticleSingleView') + ']//dl/dt[. = "Ausgabe:"]');
|
||||
if (issueDt.length > 0) {
|
||||
issueArray = issueDt[0].nextSibling.textContent.split("/");
|
||||
newItem.issue = ZU.trimInternal(issueArray[0]);
|
||||
newItem.volume = ZU.trimInternal(issueArray[1]);
|
||||
}
|
||||
|
||||
// A print dialog is shown to the user. The print page listens to the
|
||||
// onload JavaScriptevent and executes window.print().
|
||||
// I do not know how to disable this behaviour.
|
||||
newItem.attachments.push({title: "Beobachter Article Snapshot", mimeType: "text/html", url: doc.location.href + "/print.html", snapshot: true});
|
||||
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
/*
|
||||
* There is no built-in function to count object properties which often are used as associative arrays.
|
||||
*
|
||||
* @param {Object} obj Associative array
|
||||
* @return {int} Number of object properties = ength of associative array
|
||||
*/
|
||||
function countObjectProperties(obj) {
|
||||
var size = 0;
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch meta tags and fill meta tag array for associateMeta() function
|
||||
*
|
||||
* @param {element} doc Document DOM
|
||||
* @return {Object} Associative array (Object) of meta tags, array[name] = value
|
||||
*/
|
||||
function fetchMeta(doc) {
|
||||
var metaTagHTML = doc.getElementsByTagName("meta");
|
||||
var metaTags = new Object();
|
||||
for (var i = 0 ; i < metaTagHTML.length ; i++) {
|
||||
metaTags[metaTagHTML[i].getAttribute("name")] = metaTagHTML[i].getAttribute("content");
|
||||
}
|
||||
return metaTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an HTML meta tag to a Zotero item field.
|
||||
* The meta tags array can be filled with fetchMeta() function.
|
||||
*
|
||||
* @param {Object} newItem The Zotero item
|
||||
* @param {Object} metaTags Associative array (Object) of meta tags, array[name] = value
|
||||
* @param {String} name The meta tag name
|
||||
* @param {String} zoteroField The Zotero field name in the Zotero item.
|
||||
* @return {null} Nothing is returned
|
||||
*/
|
||||
function associateMeta(newItem, metaTags, name, zoteroField) {
|
||||
if (metaTags[name]) {
|
||||
newItem[zoteroField] = ZU.trimInternal(ZU.unescapeHTML(metaTags[name]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a partial xpath expression that matches an element whose 'class' attribute
|
||||
* contains the given CSS className. So to match <div class='foo bar'> you would
|
||||
* say "//div[" + containingClass("foo") + "]".
|
||||
*
|
||||
* Reference: http://pivotallabs.com/users/alex/blog/articles/427-xpath-css-class-matching
|
||||
*
|
||||
* @param {String} className CSS class name
|
||||
* @return {String} XPath fragment
|
||||
*/
|
||||
function containingClass(className) {
|
||||
return "contains(concat(' ',normalize-space(@class),' '),' " + className + " ')";
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
|
|
@ -107,11 +188,10 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.beobachter.ch/umwelt/blitze-suche-nicht-die-buche",
|
||||
"url": "http://www.beobachter.ch/natur/forschung-wissen/klima-wetter/artikel/blitzschlag_suche-nicht-die-buche/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "Blitze: Suche nicht die Buche!",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Tanja",
|
||||
|
|
@ -119,55 +199,27 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2013-08-16T16:28:50+02:00",
|
||||
"ISSN": "1661-7444",
|
||||
"abstractNote": "Acht Tipps, was man tun und lassen soll, wenn man von Blitz und Donner überrascht wird.",
|
||||
"language": "de-CH",
|
||||
"libraryCatalog": "www.beobachter.ch",
|
||||
"shortTitle": "Blitze",
|
||||
"url": "https://www.beobachter.ch/umwelt/blitze-suche-nicht-die-buche",
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Beobachter Article Snapshot",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.beobachter.ch/gesundheit/medizin-krankheit/immer-schlapp-wieso-fuhlen-wir-uns-standig-mude",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "magazineArticle",
|
||||
"title": "Immer schlapp: Wieso fühlen wir uns ständig müde?",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Andreas",
|
||||
"lastName": "Grote",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022-01-11T09:30:00+01:00",
|
||||
"url": "http://www.beobachter.ch/natur/forschung-wissen/klima-wetter/artikel/blitzschlag_suche-nicht-die-buche/",
|
||||
"shortTitle": "Neun Tipps, was man tun und lassen soll, wenn man von Blitz und Donner überrascht wird.",
|
||||
"title": "Blitze: Suche nicht die Buche!",
|
||||
"publicationTitle": "Beobachter",
|
||||
"abstractNote": "Neun Tipps, was man tun und lassen soll, wenn man von Blitz und Donner überrascht wird.",
|
||||
"language": "de",
|
||||
"ISSN": "1661-7444",
|
||||
"abstractNote": "Wer andauernd schläfrig und erschöpft ist, leidet – und nervt andere. Ein kurzer Selbsttest zeigt, ob Ihre Müdigkeit normal ist und was dagegen helfen kann.",
|
||||
"language": "de-CH",
|
||||
"libraryCatalog": "www.beobachter.ch",
|
||||
"shortTitle": "Immer schlapp",
|
||||
"url": "https://www.beobachter.ch/gesundheit/medizin-krankheit/immer-schlapp-wieso-fuhlen-wir-uns-standig-mude",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"issue": "23. August 2013, Beobachter 17",
|
||||
"volume": "2013",
|
||||
"libraryCatalog": "Beobachter",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
41
BibLaTeX.js
41
BibLaTeX.js
|
|
@ -1,11 +1,13 @@
|
|||
{
|
||||
"translatorID": "b6e39b57-8942-4d11-8259-342c46ce395f",
|
||||
"translatorType": 2,
|
||||
"label": "BibLaTeX",
|
||||
"creator": "Simon Kornblith, Richard Karnesky and Anders Johansson",
|
||||
"target": "bib",
|
||||
"minVersion": "2.1.9",
|
||||
"maxVersion": "",
|
||||
"maxVersion": "null",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"configOptions": {
|
||||
"getCollections": true
|
||||
},
|
||||
|
|
@ -15,9 +17,7 @@
|
|||
"exportFileData": false,
|
||||
"useJournalAbbreviation": false
|
||||
},
|
||||
"inRepository": true,
|
||||
"translatorType": 2,
|
||||
"lastUpdated": "2024-03-25 14:49:42"
|
||||
"lastUpdated": "2019-12-15 14:26:00"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -371,7 +371,7 @@ var numberRe = /^[0-9]+/;
|
|||
// it includes the indefinite articles of English, German, French and Spanish, as well as a small set of English prepositions whose
|
||||
// force is more grammatical than lexical, i.e. which are likely to strike many as 'insignificant'.
|
||||
// The assumption is that most who want a title word in their key would prefer the first word of significance.
|
||||
var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l'|les|el|las|los|al|uno|una|unos|unas|de|des|del|d')(\s+|\b)|(<\/?(i|b|sup|sub|sc|span style="small-caps"|span)>)/g;
|
||||
var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l'|el|las|los|al|uno|una|unos|unas|de|des|del|d')(\s+|\b)|(<\/?(i|b|sup|sub|sc|span style="small-caps"|span)>)/g;
|
||||
var citeKeyConversionsRe = /%([a-zA-Z])/;
|
||||
|
||||
var citeKeyConversions = {
|
||||
|
|
@ -484,12 +484,6 @@ function encodeFilePathComponent(value) {
|
|||
return value.replace(encodeFilePathRE, "\\$&");
|
||||
}
|
||||
|
||||
// We strip out {} in general, because \{ and \} break BibLaTeX
|
||||
function cleanFilePath(str) {
|
||||
if (!str) return '';
|
||||
return str.replace(/(?:\s*[{}]+)+\s*/g, ' ');
|
||||
}
|
||||
|
||||
function doExport() {
|
||||
// Zotero.write("% biblatex export generated by Zotero "+Zotero.Utilities.getVersion());
|
||||
// to make sure the BOM gets ignored
|
||||
|
|
@ -854,21 +848,16 @@ function doExport() {
|
|||
|
||||
for (let i = 0; i < item.attachments.length; i++) {
|
||||
var attachment = item.attachments[i];
|
||||
var title = cleanFilePath(attachment.title),
|
||||
path = null;
|
||||
|
||||
if (Zotero.getOption("exportFileData") && attachment.saveFile) {
|
||||
path = cleanFilePath(attachment.defaultPath);
|
||||
attachment.saveFile(path, true);
|
||||
attachment.saveFile(attachment.defaultPath, true);
|
||||
attachmentString += ";" + encodeFilePathComponent(attachment.title) + ":"
|
||||
+ encodeFilePathComponent(attachment.defaultPath) + ":"
|
||||
+ encodeFilePathComponent(attachment.mimeType);
|
||||
}
|
||||
else if (attachment.localPath) {
|
||||
path = cleanFilePath(attachment.localPath);
|
||||
}
|
||||
|
||||
if (path) {
|
||||
attachmentString += ";" + encodeFilePathComponent(title)
|
||||
+ ":" + encodeFilePathComponent(path)
|
||||
+ ":" + encodeFilePathComponent(attachment.mimeType);
|
||||
attachmentString += ";" + encodeFilePathComponent(attachment.title) + ":"
|
||||
+ encodeFilePathComponent(attachment.localPath) + ":"
|
||||
+ encodeFilePathComponent(attachment.mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -879,10 +868,4 @@ function doExport() {
|
|||
|
||||
Zotero.write(",\n}");
|
||||
}
|
||||
|
||||
Zotero.write("\n");
|
||||
}
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
399
BibTeX.js
399
BibTeX.js
|
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"inRepository": true,
|
||||
"translatorType": 3,
|
||||
"lastUpdated": "2024-03-25 14:51:02"
|
||||
"lastUpdated": "2020-03-13 03:07:49"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -152,28 +152,6 @@ var eprintIds = {
|
|||
'googlebooks': 'GoogleBooksID'
|
||||
};
|
||||
|
||||
function dateFieldsToDate(year, month, day) {
|
||||
// per the latest ISO 8601 standard, you can't have a month/day without a
|
||||
// year (and it would be silly anyway)
|
||||
if (year) {
|
||||
let date = year;
|
||||
if (month) {
|
||||
if (month.includes(date)) {
|
||||
date = month;
|
||||
}
|
||||
else {
|
||||
date += `-${month}`;
|
||||
}
|
||||
|
||||
if (day) {
|
||||
date += `-${day}`;
|
||||
}
|
||||
}
|
||||
return ZU.strToISO(date);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseExtraFields(extra) {
|
||||
var lines = extra.split(/[\r\n]+/);
|
||||
var fields = [];
|
||||
|
|
@ -248,7 +226,7 @@ var bibtex2zoteroTypeMap = {
|
|||
"booklet":"book",
|
||||
"manual":"book",
|
||||
"mastersthesis":"thesis",
|
||||
"misc":"document",
|
||||
"misc":"book",
|
||||
"proceedings":"book",
|
||||
"online":"webpage",
|
||||
// alias for online from BibLaTeX:
|
||||
|
|
@ -326,9 +304,6 @@ function processField(item, field, value, rawValue) {
|
|||
if (field == "doi" &&!ZU.fieldIsValidForType("DOI", item.itemType) && ZU.cleanDOI(value)) {
|
||||
item._extraFields.push({field: "DOI", value: ZU.cleanDOI(value)});
|
||||
}
|
||||
if (field == "url") { // pass raw values for URL
|
||||
item.url = rawValue;
|
||||
}
|
||||
else {
|
||||
item[fieldMap[field]] = value;
|
||||
}
|
||||
|
|
@ -405,20 +380,33 @@ function processField(item, field, value, rawValue) {
|
|||
} else {
|
||||
item.issue = value;
|
||||
}
|
||||
} else if (field == "day") {
|
||||
// this and the following two blocks assign to temporary fields that
|
||||
// are cleared before the item is completed. "day" isn't an official
|
||||
// field, but some sites use it.
|
||||
item.day = value;
|
||||
} else if (field == "month") {
|
||||
var monthIndex = months.indexOf(value.toLowerCase());
|
||||
if (monthIndex != -1) {
|
||||
value = Zotero.Utilities.formatDate({month:monthIndex});
|
||||
} else {
|
||||
value += " ";
|
||||
}
|
||||
|
||||
item.month = value;
|
||||
if (item.date) {
|
||||
if (value.includes(item.date)) {
|
||||
// value contains year and more
|
||||
item.date = value;
|
||||
} else {
|
||||
item.date = value+item.date;
|
||||
}
|
||||
} else {
|
||||
item.date = value;
|
||||
}
|
||||
} else if (field == "year") {
|
||||
item.year = value;
|
||||
if (item.date) {
|
||||
if (!item.date.includes(value)) {
|
||||
// date does not already contain year
|
||||
item.date += value;
|
||||
}
|
||||
} else {
|
||||
item.date = value;
|
||||
}
|
||||
} else if (field == "date") {
|
||||
//We're going to assume that "date" and the date parts don't occur together. If they do, we pick date, which should hold all.
|
||||
item.date = value;
|
||||
|
|
@ -684,7 +672,6 @@ function unescapeBibTeX(value) {
|
|||
value = value.replace(mapped, unicode);
|
||||
}
|
||||
}
|
||||
value = value.replace(/\$([^$]+)\$/g, '$1')
|
||||
|
||||
// kill braces
|
||||
value = value.replace(/([^\\])[{}]+/g, "$1");
|
||||
|
|
@ -871,10 +858,6 @@ function beginRecord(type, closeChar) {
|
|||
}
|
||||
var item = new Zotero.Item(zoteroType);
|
||||
item._extraFields = [];
|
||||
}
|
||||
else if (type == "preamble") { // Preamble (keeping separate in case we want to do something with these)
|
||||
Zotero.debug("discarded preamble from BibTeX");
|
||||
return;
|
||||
}
|
||||
|
||||
// For theses write the thesisType determined by the BibTeX type.
|
||||
|
|
@ -977,13 +960,6 @@ function beginRecord(type, closeChar) {
|
|||
delete item.backupLocation;
|
||||
}
|
||||
|
||||
if (!item.date) {
|
||||
item.date = dateFieldsToDate(item.year, item.month, item.day);
|
||||
}
|
||||
delete item.year;
|
||||
delete item.month;
|
||||
delete item.day;
|
||||
|
||||
item.extra = extraFieldsToString(item._extraFields);
|
||||
delete item._extraFields;
|
||||
|
||||
|
|
@ -1072,7 +1048,6 @@ function readString(resolve, reject) {
|
|||
function writeField(field, value, isMacro) {
|
||||
if (!value && typeof value != "number") return;
|
||||
value = value + ""; // convert integers to strings
|
||||
|
||||
Zotero.write(",\n\t" + field + " = ");
|
||||
if (!isMacro) Zotero.write("{");
|
||||
// url field is preserved, for use with \href and \url
|
||||
|
|
@ -1085,8 +1060,7 @@ function writeField(field, value, isMacro) {
|
|||
value = ZU.XRegExp.replace(value, protectCapsRE, "$1{$2$3}"); // only $2 or $3 will have a value, not both
|
||||
}
|
||||
}
|
||||
var exportCharset = Zotero.getOption("exportCharset");
|
||||
if (exportCharset && !exportCharset.startsWith("UTF-8")) {
|
||||
if (Zotero.getOption("exportCharset") != "UTF-8") {
|
||||
value = value.replace(/[\u0080-\uFFFF]/g, mapAccent);
|
||||
}
|
||||
//convert the HTML markup allowed in Zotero for rich text to TeX; excluding doi/url/file shouldn't be necessary, but better to be safe;
|
||||
|
|
@ -1110,23 +1084,15 @@ function mapHTMLmarkup(characters){
|
|||
return characters;
|
||||
}
|
||||
|
||||
function xcase(prefix, cased, tag, tex) {
|
||||
return (prefix ? `$${prefix}$` : '') + (reversemappingTable[`$${tex}{${cased}}$`] || `<${tag}>${cased}</${tag}>`)
|
||||
}
|
||||
function sup(match, prefix, cased) {
|
||||
return xcase(prefix, cased, 'sup', '^');
|
||||
}
|
||||
function sub(match, prefix, cased) {
|
||||
return xcase(prefix, cased, 'sub', '_');
|
||||
}
|
||||
|
||||
function mapTeXmarkup(tex){
|
||||
//reverse of the above - converts tex mark-up into html mark-up permitted by Zotero
|
||||
//italics and bold
|
||||
tex = tex.replace(/\\textit\{([^\}]+\})/g, "<i>$1</i>").replace(/\\textbf\{([^\}]+\})/g, "<b>$1</b>");
|
||||
//two versions of subscript the .* after $ is necessary because people m
|
||||
tex = tex.replace(/\$([^\{\$]*)_\{([^\}]+)\}\$/g, sub).replace(/\$([^\{\$]*)_\{\\textrm\{([^\}\$]+)\}\}\$/g, sub);
|
||||
tex = tex.replace(/\$[^\{\$]*_\{([^\}]+\})\$/g, "<sub>$1</sub>").replace(/\$[^\{]*_\{\\textrm\{([^\}]+\}\})/g, "<sub>$1</sub>");
|
||||
//two version of superscript
|
||||
tex = tex.replace(/\$([^\{\$]*)\^\{([^\}]+)\}\$/g, sup).replace(/\$([^\{\$]*)\^\{\\textrm\{([^\}]+)\}\}\$/g, sup);
|
||||
tex = tex.replace(/\$[^\{]*\^\{([^\}]+\}\$)/g, "<sup>$1</sup>").replace(/\$[^\{]*\^\{\\textrm\{([^\}]+\}\})/g, "<sup>$1</sup>");
|
||||
//small caps
|
||||
tex = tex.replace(/\\textsc\{([^\}]+)/g, "<span style=\"small-caps\">$1</span>");
|
||||
return tex;
|
||||
|
|
@ -1242,7 +1208,7 @@ var numberRe = /^[0-9]+/;
|
|||
// force is more grammatical than lexical, i.e. which are likely to strike many as 'insignificant'.
|
||||
// The assumption is that most who want a title word in their key would prefer the first word of significance.
|
||||
// Also remove markup
|
||||
var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l\'|les|el|las|los|al|uno|una|unos|unas|de|des|del|d\')(\s+|\b)|(<\/?(i|b|sup|sub|sc|span style=\"small-caps\"|span)>)/g;
|
||||
var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l\'|el|las|los|al|uno|una|unos|unas|de|des|del|d\')(\s+|\b)|(<\/?(i|b|sup|sub|sc|span style=\"small-caps\"|span)>)/g;
|
||||
var citeKeyConversionsRe = /%([a-zA-Z])/;
|
||||
|
||||
var citeKeyConversions = {
|
||||
|
|
@ -2664,7 +2630,6 @@ var reversemappingTable = {
|
|||
"{\\textunderscore}" : "\u2017", // DOUBLE LOW LINE
|
||||
"{\\textquoteleft}" : "\u2018", // LEFT SINGLE QUOTATION MARK
|
||||
"{\\textquoteright}" : "\u2019", // RIGHT SINGLE QUOTATION MARK
|
||||
"{\\textquotesingle}" : "'", // APOSTROPHE / NEUTRAL SINGLE QUOTATION MARK
|
||||
"{\\quotesinglbase}" : "\u201A", // SINGLE LOW-9 QUOTATION MARK
|
||||
"{\\textquotedblleft}" : "\u201C", // LEFT DOUBLE QUOTATION MARK
|
||||
"{\\textquotedblright}" : "\u201D", // RIGHT DOUBLE QUOTATION MARK
|
||||
|
|
@ -2791,7 +2756,6 @@ var reversemappingTable = {
|
|||
"{\\~A}" : "\u00C3", // LATIN CAPITAL LETTER A WITH TILDE
|
||||
"{\\\"A}" : "\u00C4", // LATIN CAPITAL LETTER A WITH DIAERESIS
|
||||
"{\\r A}" : "\u00C5", // LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||
"{\\AA}" : "\u00C5", // LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||
"{\\c C}" : "\u00C7", // LATIN CAPITAL LETTER C WITH CEDILLA
|
||||
"{\\`E}" : "\u00C8", // LATIN CAPITAL LETTER E WITH GRAVE
|
||||
"{\\'E}" : "\u00C9", // LATIN CAPITAL LETTER E WITH ACUTE
|
||||
|
|
@ -2818,7 +2782,6 @@ var reversemappingTable = {
|
|||
"{\\~a}" : "\u00E3", // LATIN SMALL LETTER A WITH TILDE
|
||||
"{\\\"a}" : "\u00E4", // LATIN SMALL LETTER A WITH DIAERESIS
|
||||
"{\\r a}" : "\u00E5", // LATIN SMALL LETTER A WITH RING ABOVE
|
||||
"{\\aa}" : "\u00E5", // LATIN SMALL LETTER A WITH RING ABOVE
|
||||
"{\\c c}" : "\u00E7", // LATIN SMALL LETTER C WITH CEDILLA
|
||||
"{\\`e}" : "\u00E8", // LATIN SMALL LETTER E WITH GRAVE
|
||||
"{\\'e}" : "\u00E9", // LATIN SMALL LETTER E WITH ACUTE
|
||||
|
|
@ -2896,8 +2859,8 @@ var reversemappingTable = {
|
|||
"{\\c l}" : "\u013C", // LATIN SMALL LETTER L WITH CEDILLA
|
||||
"{\\v L}" : "\u013D", // LATIN CAPITAL LETTER L WITH CARON
|
||||
"{\\v l}" : "\u013E", // LATIN SMALL LETTER L WITH CARON
|
||||
"{\\L}" : "\u0141", //LATIN CAPITAL LETTER L WITH STROKE
|
||||
"{\\l}" : "\u0142", //LATIN SMALL LETTER L WITH STROKE
|
||||
"{\\L }" : "\u0141", //LATIN CAPITAL LETTER L WITH STROKE
|
||||
"{\\l }" : "\u0142", //LATIN SMALL LETTER L WITH STROKE
|
||||
"{\\'N}" : "\u0143", // LATIN CAPITAL LETTER N WITH ACUTE
|
||||
"{\\'n}" : "\u0144", // LATIN SMALL LETTER N WITH ACUTE
|
||||
"{\\c N}" : "\u0145", // LATIN CAPITAL LETTER N WITH CEDILLA
|
||||
|
|
@ -3250,7 +3213,7 @@ var testCases = [
|
|||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2006-10",
|
||||
"date": "October 2006",
|
||||
"itemID": "conference:06",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
|
|
@ -3335,7 +3298,7 @@ var testCases = [
|
|||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Test of markupconversion: Italics, bold, superscript, subscript, and small caps: Mitochondrial DNA₂ sequences suggest unexpected phylogenetic position of Corso-Sardinian grass snakes (<i>Natrix cetti</i>) and <b>do not</b> support their <span style=\"small-caps\">species status</span>, with notes on phylogeography and subspecies delineation of grass snakes.",
|
||||
"title": "Test of markupconversion: Italics, bold, superscript, subscript, and small caps: Mitochondrial DNA<sub>2</sub>$ sequences suggest unexpected phylogenetic position of Corso-Sardinian grass snakes (<i>Natrix cetti</i>) and <b>do not</b> support their <span style=\"small-caps\">species status</span>, with notes on phylogeography and subspecies delineation of grass snakes.",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "U.",
|
||||
|
|
@ -3357,7 +3320,7 @@ var testCases = [
|
|||
"DOI": "10.1007/s13127-011-0069-8",
|
||||
"itemID": "Frit2",
|
||||
"pages": "71-80",
|
||||
"publicationTitle": "Actes du 4<sup>ème</sup> Congrès Français d'Acoustique",
|
||||
"publicationTitle": "Actes du <sup>ème</sup>$ Congrès Français d'Acoustique",
|
||||
"volume": "12",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
|
|
@ -3371,7 +3334,7 @@ var testCases = [
|
|||
"input": "@misc{american_rights_at_work_public_2012,\n title = {Public Service Research Foundation},\n\turl = {http://www.americanrightsatwork.org/blogcategory-275/},\n\turldate = {2012-07-27},\n\tauthor = {American Rights at Work},\n\tyear = {2012},\n\thowpublished = {http://www.americanrightsatwork.org/blogcategory-275/},\n}",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "document",
|
||||
"itemType": "book",
|
||||
"title": "Public Service Research Foundation",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -3634,7 +3597,7 @@ var testCases = [
|
|||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "2013-03",
|
||||
"date": "March 2013",
|
||||
"DOI": "10.1161/CIR.0b013e318288b4dd",
|
||||
"ISSN": "1524-4539",
|
||||
"extra": "PMID: 23439512",
|
||||
|
|
@ -3647,36 +3610,16 @@ var testCases = [
|
|||
"volume": "127",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Administrative Personnel"
|
||||
},
|
||||
{
|
||||
"tag": "American Heart Association"
|
||||
},
|
||||
{
|
||||
"tag": "Cardiopulmonary Resuscitation"
|
||||
},
|
||||
{
|
||||
"tag": "Community Health Services"
|
||||
},
|
||||
{
|
||||
"tag": "Health Personnel"
|
||||
},
|
||||
{
|
||||
"tag": "Heart Arrest"
|
||||
},
|
||||
{
|
||||
"tag": "Humans"
|
||||
},
|
||||
{
|
||||
"tag": "Leadership"
|
||||
},
|
||||
{
|
||||
"tag": "Public Health"
|
||||
},
|
||||
{
|
||||
"tag": "United States"
|
||||
}
|
||||
"Administrative Personnel",
|
||||
"American Heart Association",
|
||||
"Cardiopulmonary Resuscitation",
|
||||
"Community Health Services",
|
||||
"Health Personnel",
|
||||
"Heart Arrest",
|
||||
"Humans",
|
||||
"Leadership",
|
||||
"Public Health",
|
||||
"United States"
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
|
|
@ -3970,7 +3913,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1942-03",
|
||||
"date": "März 1942",
|
||||
"itemID": "sweig42",
|
||||
"publisher": "D\\ëad Po<sub>eee</sub>t Society",
|
||||
"attachments": [],
|
||||
|
|
@ -3979,258 +3922,6 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "import",
|
||||
"input": "@preamble{BibTeX for papers by David Kotz; for complete/updated list see\nhttps://www.cs.dartmouth.edu/~kotz/research/papers.html}\n\n@Article{batsis:rural,\n author = {John A. Batsis and Curtis L. Petersen and Matthew M. Clark and Summer B. Cook and David Kotz and Tyler L. Gooding and Meredith N. Roderka and Rima I. Al-Nimr and Dawna M. Pidgeon and Ann Haedrich and KC Wright and Christina Aquila and Todd A. Mackenzie},\n title = {A Rural Mobile Health Obesity Wellness Intervention for Older Adults with Obesity},\n journal = {BMC Geriatrics},\n year = 2020,\n month = {December},\n copyright = {the authors},\n URL = {https://www.cs.dartmouth.edu/~kotz/research/batsis-rural/index.html},\n note = {Accepted for publication},\n}\n",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "A Rural Mobile Health Obesity Wellness Intervention for Older Adults with Obesity",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "John A.",
|
||||
"lastName": "Batsis",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Curtis L.",
|
||||
"lastName": "Petersen",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Matthew M.",
|
||||
"lastName": "Clark",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Summer B.",
|
||||
"lastName": "Cook",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "David",
|
||||
"lastName": "Kotz",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Tyler L.",
|
||||
"lastName": "Gooding",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Meredith N.",
|
||||
"lastName": "Roderka",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Rima I.",
|
||||
"lastName": "Al-Nimr",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Dawna M.",
|
||||
"lastName": "Pidgeon",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Ann",
|
||||
"lastName": "Haedrich",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "K. C.",
|
||||
"lastName": "Wright",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Christina",
|
||||
"lastName": "Aquila",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Todd A.",
|
||||
"lastName": "Mackenzie",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-12",
|
||||
"itemID": "batsis:rural",
|
||||
"publicationTitle": "BMC Geriatrics",
|
||||
"rights": "the authors",
|
||||
"url": "https://www.cs.dartmouth.edu/~kotz/research/batsis-rural/index.html",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<p>Accepted for publication</p>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "import",
|
||||
"input": "@techreport{ietf-bmwg-evpntest-09,\n\tnumber =\t{draft-ietf-bmwg-evpntest-09},\n\ttype =\t\t{Internet-Draft},\n\tinstitution =\t{Internet Engineering Task Force},\n\tpublisher =\t{Internet Engineering Task Force},\n\tnote =\t\t{Work in Progress},\n\turl =\t\t{https://datatracker.ietf.org/doc/html/draft-ietf-bmwg-evpntest-09},\n author =\t{sudhin jacob and Kishore Tiruveedhula},\n\ttitle =\t\t{{Benchmarking Methodology for EVPN and PBB-EVPN}},\n\tpagetotal =\t28,\n\tyear =\t\t2021,\n\tmonth =\t\tjun,\n\tday =\t\t18,\n\tabstract =\t{This document defines methodologies for benchmarking EVPN and PBB- EVPN performance. EVPN is defined in RFC 7432, and is being deployed in Service Provider networks. Specifically, this document defines the methodologies for benchmarking EVPN/PBB-EVPN convergence, data plane performance, and control plane performance.},\n}\n",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"title": "Benchmarking Methodology for EVPN and PBB-EVPN",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "sudhin",
|
||||
"lastName": "jacob",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Kishore",
|
||||
"lastName": "Tiruveedhula",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-06-18",
|
||||
"abstractNote": "This document defines methodologies for benchmarking EVPN and PBB- EVPN performance. EVPN is defined in RFC 7432, and is being deployed in Service Provider networks. Specifically, this document defines the methodologies for benchmarking EVPN/PBB-EVPN convergence, data plane performance, and control plane performance.",
|
||||
"institution": "Internet Engineering Task Force",
|
||||
"itemID": "ietf-bmwg-evpntest-09",
|
||||
"reportNumber": "draft-ietf-bmwg-evpntest-09",
|
||||
"reportType": "Internet-Draft",
|
||||
"url": "https://datatracker.ietf.org/doc/html/draft-ietf-bmwg-evpntest-09",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<p>Work in Progress</p>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "import",
|
||||
"input": "@inproceedings{NIPS2009_0188e8b8,\n author = {Cuturi, Marco and Vert, Jean-philippe and D\\textquotesingle aspremont, Alexandre},\n booktitle = {Advances in Neural Information Processing Systems},\n editor = {Y. Bengio and D. Schuurmans and J. Lafferty and C. Williams and A. Culotta},\n pages = {},\n publisher = {Curran Associates, Inc.},\n title = {White Functionals for Anomaly Detection in Dynamical Systems},\n url = {https://proceedings.neurips.cc/paper/2009/file/0188e8b8b014829e2fa0f430f0a95961-Paper.pdf},\n volume = {22},\n year = {2009}\n}",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "White Functionals for Anomaly Detection in Dynamical Systems",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Marco",
|
||||
"lastName": "Cuturi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Jean-philippe",
|
||||
"lastName": "Vert",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Alexandre",
|
||||
"lastName": "D' aspremont",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Y.",
|
||||
"lastName": "Bengio",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "D.",
|
||||
"lastName": "Schuurmans",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "J.",
|
||||
"lastName": "Lafferty",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "C.",
|
||||
"lastName": "Williams",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "A.",
|
||||
"lastName": "Culotta",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2009",
|
||||
"itemID": "NIPS2009_0188e8b8",
|
||||
"proceedingsTitle": "Advances in Neural Information Processing Systems",
|
||||
"publisher": "Curran Associates, Inc.",
|
||||
"url": "https://proceedings.neurips.cc/paper/2009/file/0188e8b8b014829e2fa0f430f0a95961-Paper.pdf",
|
||||
"volume": "22",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "import",
|
||||
"input": "@article{Borissov:2855446,\r\n author = \"Borissov, Alexander and Solokhin, Sergei\",\r\n collaboration = \"ALICE\",\r\n title = \"{Production of $\\Sigma^{0}$ Hyperon and Search of\r\n $\\Sigma^{0}$ Hypernuclei at LHC with ALICE}\",\r\n journal = \"Phys. At. Nucl.\",\r\n volume = \"85\",\r\n number = \"6\",\r\n pages = \"970-975\",\r\n year = \"2023\",\r\n url = \"https://cds.cern.ch/record/2855446\",\r\n doi = \"10.1134/S1063778823010131\",\r\n }",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Production of Σ⁰ Hyperon and Search of Σ⁰ Hypernuclei at LHC with ALICE",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Alexander",
|
||||
"lastName": "Borissov",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Sergei",
|
||||
"lastName": "Solokhin",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023",
|
||||
"DOI": "10.1134/S1063778823010131",
|
||||
"issue": "6",
|
||||
"itemID": "Borissov:2855446",
|
||||
"pages": "970-975",
|
||||
"publicationTitle": "Phys. At. Nucl.",
|
||||
"url": "https://cds.cern.ch/record/2855446",
|
||||
"volume": "85",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "import",
|
||||
"input": "@book{derbis1998poczucie,\r\ntitle={Poczucie jako{\\'s}ci {\\.z}ycia a swoboda dzia{\\l}ania i odpowiedzialno{\\'s}{\\'c}},\r\nauthor={Derbis, Romuald and Ba{\\'n}ka, Augustyn},\r\nyear={1998},\r\npublisher={Stowarzyszenie Psychologia i Architektura}\r\n}",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Poczucie jakości życia a swoboda działania i odpowiedzialność",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Romuald",
|
||||
"lastName": "Derbis",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Augustyn",
|
||||
"lastName": "Bańka",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1998",
|
||||
"itemID": "derbis1998poczucie",
|
||||
"publisher": "Stowarzyszenie Psychologia i Architektura",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
248
Biblio.com.js
248
Biblio.com.js
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"translatorID": "9932d1a7-cc6d-4d83-8462-8f6658b13dc0",
|
||||
"label": "Biblio.com",
|
||||
"creator": "Adam Crymble, Michael Berkowitz, Sebastian Karcher, and Abe Jellinek",
|
||||
"creator": "Adam Crymble, Michael Berkowitz, and Sebastian Karcher",
|
||||
"target": "^https?://www\\.biblio\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
|
|
@ -9,50 +9,87 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-14 21:52:42"
|
||||
"lastUpdated": "2016-09-08 06:09:28"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/book/')) {
|
||||
if (doc.location.href.match("bookseller_search") || doc.location.href.match("bookstores") || doc.location.href.match("textbooks")) {
|
||||
|
||||
} else if (doc.location.href.search(/\/search\.php/)!=-1) {
|
||||
return "multiple";
|
||||
} else if (doc.location.href.search(/\/book/)!=-1) {
|
||||
return "book";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//Biblio.com translator. Code by Adam Crymble.
|
||||
|
||||
function associateData (newItem, dataTags, field, zoteroField) {
|
||||
if (dataTags[field]) {
|
||||
newItem[zoteroField] = dataTags[field];
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
|
||||
var dataTags = new Object();
|
||||
var contents = new Array();
|
||||
var multiAuthors = new Array();
|
||||
var fieldTitle;
|
||||
var author1;
|
||||
|
||||
var newItem = new Zotero.Item("book");
|
||||
|
||||
var content = doc.evaluate('//div[@id="description"]/ul/li', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var xPathCount = doc.evaluate('count (//div[@id="description"]/ul/li)', doc, null, XPathResult.ANY_TYPE, null);
|
||||
|
||||
for (var i=0; i<xPathCount.numberValue; i++) {
|
||||
contents = content.iterateNext().textContent.split(": ");
|
||||
if (contents.length>1) {
|
||||
fieldTitle = contents[0].replace(/\s*/g, '');
|
||||
dataTags[fieldTitle] = contents[1].replace(/^\s*|\s*$/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
//Authors
|
||||
if (doc.evaluate('//h2', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var authors = doc.evaluate('//h2', doc, null, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
if (authors.match(/\w/)) {
|
||||
authors = authors.replace(/^\s*by/, "");
|
||||
multiAuthors = authors.split(";");
|
||||
for (var j=0; j<multiAuthors.length; j++) {
|
||||
var aut = multiAuthors[j];
|
||||
newItem.creators.push(Zotero.Utilities.cleanAuthor(aut, "author", aut.match(/,/)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//extra
|
||||
if (dataTags["Quantityavailable"]) {
|
||||
newItem.extra = "Quantity Available: " + dataTags["Quantityavailable"];
|
||||
}
|
||||
|
||||
associateData (newItem, dataTags, "Publisher", "publisher");
|
||||
associateData (newItem, dataTags, "Place", "place");
|
||||
associateData (newItem, dataTags, "Datepublished", "date");
|
||||
associateData (newItem, dataTags, "ISBN10", "ISBN");
|
||||
associateData (newItem, dataTags, "ISBN13", "ISBN");
|
||||
associateData (newItem, dataTags, "Pages", "pages");
|
||||
associateData (newItem, dataTags, "Edition", "edition");
|
||||
|
||||
newItem.title = ZU.xpathText(doc, '//h1').replace(/^\s*|\.\s*$/g, '');
|
||||
newItem.url = doc.location.href;
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h2.title > a[href*="/book/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
var rows = ZU.xpath(doc, '//div[@class="row"]//a[@class="sr-title-text"]');
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
|
|
@ -61,65 +98,23 @@ function getSearchResults(doc, checkOnly) {
|
|||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, _url) {
|
||||
let item = new Zotero.Item('book');
|
||||
|
||||
for (let keyElem of doc.querySelectorAll('#d-book-details dt')) {
|
||||
let key = ZU.trimInternal(keyElem.textContent);
|
||||
let value = keyElem.nextElementSibling.textContent;
|
||||
|
||||
switch (key) {
|
||||
case 'Title':
|
||||
item.title = value.replace(/\.\s*$/, '');
|
||||
break;
|
||||
case 'Author':
|
||||
for (let name of value.split(';')) {
|
||||
item.creators.push(ZU.cleanAuthor(name, 'author', true));
|
||||
}
|
||||
break;
|
||||
case 'Edition':
|
||||
item.edition = value;
|
||||
break;
|
||||
case 'Publisher':
|
||||
item.publisher = value;
|
||||
break;
|
||||
case 'Place of Publication':
|
||||
item.place = value;
|
||||
break;
|
||||
case 'Date published':
|
||||
case 'First published':
|
||||
case 'This edition first published':
|
||||
item.date = ZU.strToISO(value);
|
||||
break;
|
||||
case 'ISBN 10':
|
||||
case 'ISBN 13':
|
||||
item.ISBN = ZU.cleanISBN(value);
|
||||
break;
|
||||
default:
|
||||
if (!item.date && /\bpublished\b/i.test(key)) {
|
||||
// handle odd date labels, just in case
|
||||
item.date = ZU.strToISO(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
item.url = attr(doc, 'link[rel="canonical"]', 'href');
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -129,11 +124,10 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.biblio.com/book/through-year-dickens-compiled-his-eldest/d/29965287",
|
||||
"url": "http://www.biblio.com/book/through-year-dickens-compiled-his-eldest/d/29965287",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Through The Year With Dickens. Compiled by his Eldest Daughter",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Charles",
|
||||
|
|
@ -141,76 +135,20 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [],
|
||||
"publisher": "DeWolfe, Fiske & Co",
|
||||
"place": "Boston, USA",
|
||||
"date": "1909",
|
||||
"edition": "First American",
|
||||
"title": "Through The Year With Dickens. Compiled by his Eldest Daughter",
|
||||
"url": "http://www.biblio.com/book/through-year-dickens-compiled-his-eldest/d/29965287",
|
||||
"libraryCatalog": "Biblio.com",
|
||||
"place": "Boston, USA",
|
||||
"publisher": "DeWolfe, Fiske & Co",
|
||||
"url": "https://www.biblio.com/book/through-year-dickens-compiled-his-eldest/d/29965287",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.biblio.com/book/charming-children-dickens-stories-dickens-charles/d/1397028696",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Charming Children of Dickens' Stories",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Charles",
|
||||
"lastName": "Dickens",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Angela",
|
||||
"lastName": "Dickens",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1906",
|
||||
"libraryCatalog": "Biblio.com",
|
||||
"place": "Chicago",
|
||||
"publisher": "John A. Hertel Company",
|
||||
"url": "https://www.biblio.com/book/charming-children-dickens-stories-dickens-charles/d/1397028696",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.biblio.com/book/birds-without-wings-bernieres-louis/d/920369973",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Birds Without Wings",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "LOUIS",
|
||||
"lastName": "DE BERNIERES",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2005-06-28",
|
||||
"ISBN": "9781400079322",
|
||||
"libraryCatalog": "Biblio.com",
|
||||
"place": "New York",
|
||||
"publisher": "Vintage",
|
||||
"url": "https://www.biblio.com/book/birds-without-wings-bernieres-louis/d/920369973",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 3,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-09-30 10:56:50"
|
||||
"lastUpdated": "2019-09-01 13:38:00"
|
||||
}
|
||||
|
||||
var n = {
|
||||
|
|
@ -785,15 +785,7 @@ function getStatementsByDefinition(definition, node) {
|
|||
|
||||
function detectImport() {
|
||||
// look for a bibo item type
|
||||
let rdfTypes = null;
|
||||
try {
|
||||
rdfTypes = Zotero.RDF.getStatementsMatching(null, RDF_TYPE, null);
|
||||
}
|
||||
catch (err) {
|
||||
// probably just not RDF
|
||||
return false;
|
||||
}
|
||||
|
||||
var rdfTypes = Zotero.RDF.getStatementsMatching(null, RDF_TYPE, null);
|
||||
if (rdfTypes) {
|
||||
for (var i=0; i<rdfTypes.length; i++) {
|
||||
if (typeof rdfTypes[i][2] === "object" && Z.RDF.getResourceURI(rdfTypes[i][2]).substr(0, BIBO_NS_LENGTH) == n.bibo) return true;
|
||||
|
|
@ -1071,10 +1063,6 @@ function doExport() {
|
|||
var item;
|
||||
var items = {};
|
||||
while (item = Zotero.nextItem()) {
|
||||
// Skip standalone notes
|
||||
if (item.itemType == 'note') {
|
||||
continue;
|
||||
}
|
||||
items[item.itemID] = item;
|
||||
}
|
||||
var autoTags = {};
|
||||
|
|
@ -1163,4 +1151,4 @@ var testCases = [
|
|||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -126,6 +126,8 @@ function doWeb(doc, url) {
|
|||
if (prefix == 'x') return namespace; else return null;
|
||||
} : null;
|
||||
|
||||
var articles = new Array();
|
||||
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var items = new Object();
|
||||
|
||||
|
|
@ -137,11 +139,13 @@ function doWeb(doc, url) {
|
|||
items[next_title.href] = next_title.textContent;
|
||||
}
|
||||
}
|
||||
Zotero.selectItems(items, function (items) {
|
||||
ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
items = Zotero.selectItems(items);
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
} else {
|
||||
articles = [url];
|
||||
}
|
||||
Zotero.Utilities.processDocuments(articles, scrape, function() {Zotero.done();});
|
||||
Zotero.wait();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,296 +0,0 @@
|
|||
{
|
||||
"translatorID": "0524c89b-2a96-4d81-bb05-ed91ed8b2b47",
|
||||
"label": "Bloomsbury Food Library",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://(www\\.)?bloomsburyfoodlibrary\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-03 01:17:12"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (doc.querySelector('a[href*="/getris"]')) {
|
||||
if (url.includes('bloomsburyfoodlibrary.com/encyclopedia-chapter')) {
|
||||
if (text(doc, '.subfacet').includes('Book chapter')) {
|
||||
return 'bookSection';
|
||||
}
|
||||
else {
|
||||
return 'encyclopediaArticle';
|
||||
}
|
||||
}
|
||||
else if (url.includes('bloomsburyfoodlibrary.com/audio')) {
|
||||
// would like to support these, but the RIS isn't useful
|
||||
return false;
|
||||
}
|
||||
else if (url.includes('bloomsburyfoodlibrary.com/museum')) {
|
||||
return 'artwork';
|
||||
}
|
||||
else {
|
||||
return 'book';
|
||||
}
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('a#search-result-link');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var risURL = attr(doc, 'a[href*="/getris"]', 'href');
|
||||
|
||||
ZU.doGet(risURL, function (text) {
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
let detectedType = detectWeb(doc, url);
|
||||
if (detectedType == 'encyclopediaArticle' && item.itemType == 'bookSection') {
|
||||
item.itemType = 'encyclopediaArticle';
|
||||
item.encyclopediaTitle = item.bookTitle;
|
||||
delete item.bookTitle;
|
||||
}
|
||||
else if (detectedType == 'book' && item.itemType == 'bookSection') {
|
||||
item.itemType = 'book';
|
||||
delete item.bookTitle;
|
||||
|
||||
// filter out duplicate "editor" names
|
||||
let names = new Set();
|
||||
item.creators = item.creators.filter((creator) => {
|
||||
let fullName = `${creator.lastName}, ${creator.firstName}`;
|
||||
if (names.has(fullName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
names.add(fullName);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
else if (detectedType == 'artwork') {
|
||||
item.itemType = 'artwork';
|
||||
}
|
||||
|
||||
for (let prop of ['title', 'bookTitle', 'encyclopediaTitle']) {
|
||||
if (item[prop]) {
|
||||
item[prop] = item[prop].replace(/ : /, ': ');
|
||||
}
|
||||
}
|
||||
|
||||
if (item.publisher) {
|
||||
item.publisher = item.publisher.replace('©', '');
|
||||
}
|
||||
|
||||
item.archive = '';
|
||||
|
||||
// contains full text, if we're on a chapter
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia-chapter?docid=b-9781474208642&tocid=b-9781474208642-000399&pdfid=9781474208642.0008.pdf",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "Burkina Faso",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Debevec",
|
||||
"firstName": "Liza",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Albala",
|
||||
"firstName": "Ken",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"ISBN": "9781474208642",
|
||||
"edition": "1",
|
||||
"encyclopediaTitle": "Food Cultures of the World Encyclopedia: Africa and the Middle East",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bloomsbury Food Library",
|
||||
"pages": "23-30",
|
||||
"place": "Santa Barbara",
|
||||
"publisher": "ABC-Clio Inc",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia-chapter?docid=b-9781474208642&tocid=b-9781474208642-000399",
|
||||
"volume": "1",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia?docid=b-9781474205283",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "The Agency of Eating: Mediation, Food and the Body",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Abbots",
|
||||
"firstName": "Emma-Jayne",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2017",
|
||||
"ISBN": "9781474205283",
|
||||
"edition": "1",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bloomsbury Food Library",
|
||||
"place": "London",
|
||||
"publisher": "Bloomsbury Academic",
|
||||
"series": "Contemporary Food Studies: Economy, Culture and Politics",
|
||||
"shortTitle": "The Agency of Eating",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia?docid=b-9781474205283",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia?docid=b-9781474203937",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Agri-Food and Rural Development: Sustainable Place-Making",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Marsden",
|
||||
"firstName": "Terry",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2017",
|
||||
"ISBN": "9781474203937",
|
||||
"edition": "1",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bloomsbury Food Library",
|
||||
"place": "London",
|
||||
"publisher": "Bloomsbury Academic",
|
||||
"series": "Contemporary Food Studies: Economy, Culture and Politics",
|
||||
"shortTitle": "Agri-Food and Rural Development",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/encyclopedia?docid=b-9781474203937",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/museumobject?docid=TNA_COPY1_241-95",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "artwork",
|
||||
"title": "Advert for Hill Evans's barley malt vinegar",
|
||||
"creators": [],
|
||||
"libraryCatalog": "Bloomsbury Food Library",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/museum?docid=TNA_COPY1_241-95",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.bloomsburyfoodlibrary.com/search-results?any=corn",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
195
Bluesky.js
195
Bluesky.js
|
|
@ -1,195 +0,0 @@
|
|||
{
|
||||
"translatorID": "3bba003a-ad42-457e-9ea1-547df39d9d00",
|
||||
"label": "Bluesky",
|
||||
"creator": "Stephan Hügel",
|
||||
"target": "^https://bsky\\.app/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-03-26 14:26:25"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Stephan Hügel <urschrei@gmail.com>
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
let handleRe = /(?:\/profile\/)(([^/]+))/;
|
||||
let postIdRe = /(?:\/post\/)([a-zA-Z0-9]+)/;
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/post/') && handleRe.test(url) && postIdRe.test(url)) {
|
||||
return 'forumPost';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
await scrapeAPI(doc, url);
|
||||
}
|
||||
|
||||
async function scrapeAPI(doc, url) {
|
||||
let foundHandle = url.match(handleRe)[1];
|
||||
let foundPostId = url.match(postIdRe)[1];
|
||||
|
||||
let apiUrl = `https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=at://${foundHandle}/app.bsky.feed.post/${foundPostId}`;
|
||||
let data = await ZU.requestJSON(apiUrl);
|
||||
if (!(data.thread && data.thread.post)) {
|
||||
throw new Error("Couldn't save post due to missing metadata");
|
||||
}
|
||||
else {
|
||||
let post = data.thread.post;
|
||||
let item = new Zotero.Item("forumPost");
|
||||
// Main post details
|
||||
|
||||
// remove newlines and extra whitespace
|
||||
let titleCleaned = post.record.text.replace(/\s+/g, ' ');
|
||||
// Ensure that full post text is always available
|
||||
item.abstractNote = titleCleaned;
|
||||
// Tidy if necessary
|
||||
if (titleCleaned.length < 140) {
|
||||
item.title = titleCleaned;
|
||||
}
|
||||
else {
|
||||
item.title = ZU.ellipsize(titleCleaned, 140, true);
|
||||
}
|
||||
item.forumTitle = "Bluesky";
|
||||
item.type = "Post";
|
||||
item.url = url;
|
||||
item.date = post.record.createdAt;
|
||||
// Add author information
|
||||
if (post.author) {
|
||||
if (post.author.displayName !== "") {
|
||||
item.creators.push(Zotero.Utilities.cleanAuthor(post.author.displayName, "author"));
|
||||
}
|
||||
else if (post.author.handle !== "handle.invalid") {
|
||||
item.creators.push(Zotero.Utilities.cleanAuthor(post.author.handle, "author"));
|
||||
}
|
||||
// we've got a blank display name and an invalid handle, so we can't add an author: bail out
|
||||
else {
|
||||
throw new Error("Couldn't save post due to missing author data: neither display name nor handle are available");
|
||||
}
|
||||
if (post.author.handle !== "handle.invalid") {
|
||||
item.setExtra("Author Handle", post.author.handle);
|
||||
}
|
||||
// DID is the creator's unique id in the ATProto network
|
||||
item.setExtra("DID", post.author.did);
|
||||
}
|
||||
// Add metadata for likes, reposts, etc.
|
||||
item.setExtra("Likes", post.likeCount);
|
||||
item.setExtra("Reposts", post.repostCount);
|
||||
item.setExtra("Quotes", post.quoteCount);
|
||||
|
||||
// Handle embedded quote records (if any)
|
||||
if (post.embed && post.embed.record && post.embed.record.value) {
|
||||
let embeddedPost = post.embed.record.value;
|
||||
item.notes.push({ note: `This post is quoting a post by @${post.embed.record.author.handle}: "${embeddedPost.text}"` });
|
||||
}
|
||||
|
||||
// Handle replies (if any)
|
||||
if (data.thread.replies && data.thread.replies.length > 0) {
|
||||
item.notes.push({ note: `This post had ${data.thread.replies.length} direct replies when it was saved` });
|
||||
}
|
||||
item.attachments.push({ document: doc, title: "Snapshot" });
|
||||
item.complete();
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bsky.app/profile/watershedlab.bsky.social/post/3lcl3glmdx226",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "forumPost",
|
||||
"title": "My first and only job in media was as a reporter on a small newspaper in England in 2002. My salary was £8700. Per year.",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Dan",
|
||||
"lastName": "Shugar",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-12-05T16:25:35.749Z",
|
||||
"abstractNote": "My first and only job in media was as a reporter on a small newspaper in England in 2002. My salary was £8700. Per year.",
|
||||
"extra": "Author Handle: watershedlab.bsky.social\nDID: did:plc:ufufhaxc74cfl7fpjccykkyh\nLikes: 8\nReposts: 0\nQuotes: 0",
|
||||
"forumTitle": "Bluesky",
|
||||
"postType": "Post",
|
||||
"url": "https://bsky.app/profile/watershedlab.bsky.social/post/3lcl3glmdx226",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [
|
||||
{
|
||||
"note": "This post is quoting a post by @ericwickham.ca: \"Told the guy replacing my car window how much I made at my first job in radio and I feel like it deeply changed what he thought about people in media.\""
|
||||
},
|
||||
{
|
||||
"note": "This post had 1 direct replies when it was saved"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bsky.app/profile/did:plc:cxq4zxu7soi67juyvxml46zs/post/3ldr6ebdz5c24",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "forumPost",
|
||||
"title": "💚 Site of the Day - Rain Delay Media Love that menu! ⚙️ SplitText 🛠️ Webflow site → raindelaymedia.com showcase → gsap.com/showcase",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "",
|
||||
"lastName": "GSAP",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-12-20T19:59:08.958Z",
|
||||
"abstractNote": "💚 Site of the Day - Rain Delay Media Love that menu! ⚙️ SplitText 🛠️ Webflow site → raindelaymedia.com showcase → gsap.com/showcase",
|
||||
"extra": "Author Handle: gsap-greensock.bsky.social\nDID: did:plc:cxq4zxu7soi67juyvxml46zs\nLikes: 6\nReposts: 0\nQuotes: 0",
|
||||
"forumTitle": "Bluesky",
|
||||
"postType": "Post",
|
||||
"url": "https://bsky.app/profile/did:plc:cxq4zxu7soi67juyvxml46zs/post/3ldr6ebdz5c24",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
129
BnF ISBN.js
129
BnF ISBN.js
|
|
@ -1,129 +0,0 @@
|
|||
{
|
||||
"translatorID": "f349954c-9957-4b5f-be24-1a8bb52f7fbd",
|
||||
"label": "BnF ISBN",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "",
|
||||
"minVersion": "4.0",
|
||||
"maxVersion": "",
|
||||
"priority": 98,
|
||||
"inRepository": true,
|
||||
"translatorType": 8,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-30 21:23:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
let ns = {
|
||||
srw: 'http://www.loc.gov/zing/srw/',
|
||||
mxc: 'info:lc/xmlns/marcxchange-v2'
|
||||
};
|
||||
|
||||
function detectSearch(item) {
|
||||
return !!item.ISBN;
|
||||
}
|
||||
|
||||
function doSearch(item) {
|
||||
let ISBN = ZU.cleanISBN(item.ISBN);
|
||||
let url = `https://catalogue.bnf.fr/api/SRU?version=1.2&operation=searchRetrieve&query=bib.isbn%20all%20%22${ISBN}%22`;
|
||||
ZU.doGet(url, function (xmlText) {
|
||||
let parser = new DOMParser();
|
||||
let xml = parser.parseFromString(xmlText, 'application/xml');
|
||||
let records = ZU.xpath(xml.documentElement, '/srw:searchRetrieveResponse/srw:records/srw:record', ns);
|
||||
if (!records) return;
|
||||
|
||||
for (let record of records) {
|
||||
if (ZU.xpathText(record, '//srw:recordSchema', ns) != 'marcxchange') continue;
|
||||
|
||||
let marcRecords = ZU.xpath(record, '//srw:recordData/mxc:record', ns);
|
||||
if (!marcRecords) continue;
|
||||
|
||||
for (let marcRecord of marcRecords) {
|
||||
marcRecord.setAttribute('xmlns:marc', 'http://www.loc.gov/MARC21/slim');
|
||||
|
||||
// Here we convert the XML we get from BnF from the original
|
||||
// MarcXchange format into MARCXML by search-and-replacing
|
||||
// the namespace. MARCXML and and MarcXchange are essentially
|
||||
// the same format: the latter is a "generalization (mainly by
|
||||
// weakening restrictions)" of the former. We didn't enforce
|
||||
// those restrictions to begin with.
|
||||
|
||||
// MarcXchange spec:
|
||||
// https://www.loc.gov/standards/iso25577/ISO_DIS_25577__E_.pdf
|
||||
|
||||
let marcxchangeText = new XMLSerializer().serializeToString(marcRecord);
|
||||
let marcXMLText = marcxchangeText.replace(/<mxc:/g, '<marc:').replace(/<\/mxc:/g, '</marc:');
|
||||
|
||||
let translator = Zotero.loadTranslator('import');
|
||||
// MARCXML
|
||||
translator.setTranslator('edd87d07-9194-42f8-b2ad-997c4c7deefd');
|
||||
translator.setString(marcXMLText);
|
||||
translator.translate();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9781841692203"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Markus",
|
||||
"firstName": "Keith A.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Borsboom",
|
||||
"creatorType": "author",
|
||||
"firstName": "Denny"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"attachments": [],
|
||||
"libraryCatalog": "BnF ISBN",
|
||||
"place": "New York",
|
||||
"ISBN": "9781841692203",
|
||||
"title": "Frontiers in test validity theory: measurement, causation and meaning",
|
||||
"publisher": "Routledge",
|
||||
"date": "2013",
|
||||
"language": "eng",
|
||||
"shortTitle": "Frontiers in test validity theory",
|
||||
"series": "Multivariate applications series",
|
||||
"callNumber": "150.287"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
14
Bookmarks.js
14
Bookmarks.js
|
|
@ -8,7 +8,8 @@
|
|||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 3,
|
||||
"lastUpdated": "2022-07-14 20:21:20"
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2017-12-17 17:43:00"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -233,18 +234,13 @@ function doExport() {
|
|||
'<H1>Bookmarks Menu</H1>\n'+
|
||||
'<DL>\n';
|
||||
var footer = '</DL>';
|
||||
//var tags = "";
|
||||
|
||||
Zotero.write(header);
|
||||
while (item = Zotero.nextItem()) {
|
||||
// TODO Be more verbose, making an informative title and including more metadata
|
||||
let tags = item.tags.map(tag => tag.tag).join(',');
|
||||
if (item.url) {
|
||||
Zotero.write(' <DT><A HREF="'+item.url+'"');
|
||||
if (tags) {
|
||||
Zotero.write(' TAGS="' + tags + '"');
|
||||
}
|
||||
Zotero.write('>'+item.title+'</A>\n');
|
||||
}
|
||||
//tags = item.tags.forEach(function (tag) {return tag.tag}).join(",");
|
||||
if (item.url) Zotero.write(' <DT><A HREF="'+item.url+'">'+item.title+'</A>\n');
|
||||
else Zotero.debug("Skipping item without URL: "+item.title);
|
||||
}
|
||||
Zotero.write(footer);
|
||||
|
|
|
|||
223
Bookshop.org.js
223
Bookshop.org.js
|
|
@ -1,223 +0,0 @@
|
|||
{
|
||||
"translatorID": "05997944-d1c2-41bf-a399-9932268c81e5",
|
||||
"label": "Bookshop.org",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https://bookshop\\.org/books",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-01 17:14:32"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (/\/books\/[^/]+\/[0-9]+/.test(url)
|
||||
&& attr('meta[property="og:type"]', 'content') == 'book') {
|
||||
return "book";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h2 a[href*="/books/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.numPages = text(doc, '[itemprop="numberOfPages"]');
|
||||
item.publisher = text(doc, '[itemprop="publisher"]');
|
||||
|
||||
item.tags = [];
|
||||
item.attachments = [];
|
||||
item.url = '';
|
||||
|
||||
for (let author of doc.querySelectorAll('span[itemprop="author"]')) {
|
||||
let name = text(author, 'span[itemprop="name"]');
|
||||
let type = author.parentNode.nextSibling.textContent;
|
||||
|
||||
if (type.includes('Author')) {
|
||||
type = 'author';
|
||||
}
|
||||
else if (type.includes('Editor')) {
|
||||
type = 'editor';
|
||||
}
|
||||
else if (type.includes('Translator')) {
|
||||
type = 'translator';
|
||||
}
|
||||
else {
|
||||
type = 'contributor';
|
||||
}
|
||||
|
||||
item.creators.push(ZU.cleanAuthor(name, type));
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = "book";
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bookshop.org/books/crying-in-h-mart-a-memoir/9780525657743",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Crying in H Mart: A Memoir",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Michelle",
|
||||
"lastName": "Zauner",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-04-20T12:00:00-04:00",
|
||||
"ISBN": "9780525657743",
|
||||
"abstractNote": "NEW YORK TIMES BEST SELLER - A Best Book of 2021: AV Club - Bustle - Entertainment Weekly - Good Morning America - Chicago Review of Books - Fortune - TIME - CNN Underscored - Apartment Therapy - Popsugar - Hello Giggles - Business Insider - The Millions - Wall Street Journal Magazine - Glamour From the indie rockstar of Japanese Breakfast fame, and author of the viral 2018 New Yorker essay that shares the title of this book, an unflinching, powerful memoir about growing up Korean American, losing her mother, and forging her own identity. In this exquisite story of family, food, grief, and endurance, Michelle Zauner proves herself far more than a dazzling singer, songwriter, and guitarist. With humor and heart, she tells of growing up one of the few Asian American kids at her school in Eugene, Oregon; of struggling with her mother's particular, high expectations of her; of a painful adolescence; of treasured months spent in her grandmother's tiny apartment in Seoul, where she and her mother would bond, late at night, over heaping plates of food. As she grew up, moving to the East Coast for college, finding work in the restaurant industry, and performing gigs with her fledgling band--and meeting the man who would become her husband--her Koreanness began to feel ever more distant, even as she found the life she wanted to live. It was her mother's diagnosis of terminal cancer, when Michelle was twenty-five, that forced a reckoning with her identity and brought her to reclaim the gifts of taste, language, and history her mother had given her. Vivacious and plainspoken, lyrical and honest, Zauner's voice is as radiantly alive on the page as it is onstage. Rich with intimate anecdotes that will resonate widely, and complete with family photos, Crying in H Mart is a book to cherish, share, and reread.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "bookshop.org",
|
||||
"numPages": "256",
|
||||
"publisher": "Knopf Publishing Group",
|
||||
"shortTitle": "Crying in H Mart",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bookshop.org/books/organic-chemistry-for-babies/9781492671169",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Organic Chemistry for Babies",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Chris",
|
||||
"lastName": "Ferrie",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Cara",
|
||||
"lastName": "Florance",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018-05-01T12:00:00-04:00",
|
||||
"ISBN": "9781492671169",
|
||||
"abstractNote": "Fans of Chris Ferrie's Rocket Science for Babies, Quantum Physics for Babies, and 8 Little Planets will love this introduction to organic chemistry for babies and toddlers!It only takes a small spark to ignite a child's mind.Written by an expert, Organic Chemistry for Babies is a colorfully simple introduction to the structure of organic, carbon-containing compounds and materials. Gift your special little one the opportunity to learn with this perfect science baby gift and help them be one step ahead of pre-med students! With a tongue-in-cheek approach that adults will love, this installment of the Baby University baby board book series is the perfect way to introduce STEM concepts for babies and toddlers. After all, it's never too early to become an organic chemist!If you're looking for the perfect STEAM book for teachers, science toys for babies, or chemistry toys for kids, look no further! Organic Chemistry for Babies offers fun early learning for your little scientist!",
|
||||
"language": "en",
|
||||
"libraryCatalog": "bookshop.org",
|
||||
"numPages": "24",
|
||||
"publisher": "Sourcebooks Explore",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bookshop.org/books?keywords=pippi",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bookshop.org/books/meditations-a-new-translation-7be5ded9-87a9-4056-af72-d6c917125a29/9780812968255",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Meditations: A New Translation",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Marcus",
|
||||
"lastName": "Aurelius",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Gregory",
|
||||
"lastName": "Hays",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"date": "2003-05-06T12:00:00-04:00",
|
||||
"ISBN": "9780812968255",
|
||||
"abstractNote": "Nearly two thousand years after it was written, Meditations remains profoundly relevant for anyone seeking to lead a meaningful life. Few ancient works have been as influential as the Meditations of Marcus Aurelius, philosopher and emperor of Rome (A.D. 161-180). A series of spiritual exercises filled with wisdom, practical guidance, and profound understanding of human behavior, it remains one of the greatest works of spiritual and ethical reflection ever written. Marcus's insights and advice--on everything from living in the world to coping with adversity and interacting with others--have made the Meditations required reading for statesmen and philosophers alike, while generations of ordinary readers have responded to the straightforward intimacy of his style. For anyone who struggles to reconcile the demands of leadership with a concern for personal integrity and spiritual well-being, the Meditations remains as relevant now as it was two thousand years ago. In Gregory Hays's new translation--the first in thirty-five years--Marcus's thoughts speak with a new immediacy. In fresh and unencumbered English, Hays vividly conveys the spareness and compression of the original Greek text. Never before have Marcus's insights been so directly and powerfully presented. With an Introduction that outlines Marcus's life and career, the essentials of Stoic doctrine, the style and construction of the Meditations, and the work's ongoing influence, this edition makes it possible to fully rediscover the thoughts of one of the most enlightened and intelligent leaders of any era.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "bookshop.org",
|
||||
"numPages": "256",
|
||||
"publisher": "Modern Library",
|
||||
"shortTitle": "Meditations",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue