Compare commits
390 Commits
dependabot
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
b1c986427b | |
|
|
2e13e9407d | |
|
|
ffa1be434c | |
|
|
2f7fc8eb9b | |
|
|
7f632f76bc | |
|
|
ee1746de4d | |
|
|
36745ead6d | |
|
|
4fe143f5d0 | |
|
|
6365ccdf13 | |
|
|
b44a279901 | |
|
|
7e1b981f92 | |
|
|
a79e3bea38 | |
|
|
93af89a882 | |
|
|
20b8729b80 | |
|
|
303ca7d64d | |
|
|
59967fbfab | |
|
|
d7d7426860 | |
|
|
7d12fd8f2d | |
|
|
b56c554203 | |
|
|
bb41570843 | |
|
|
259ea55d73 | |
|
|
ea900c2124 | |
|
|
2eef9d03f9 | |
|
|
a095751f8a | |
|
|
352989d042 | |
|
|
4ae717da83 | |
|
|
d0f2d15874 | |
|
|
df835b0e1d | |
|
|
8a9ef4a1de | |
|
|
2da50c6a39 | |
|
|
e9335d57c9 | |
|
|
0855c33a6c | |
|
|
085b8db857 | |
|
|
41f8149d88 | |
|
|
f6d9cb90e5 | |
|
|
e343623dfe | |
|
|
c44f7f6489 | |
|
|
52a114f843 | |
|
|
727fd1cc63 | |
|
|
f9ff5e2818 | |
|
|
d9f3bb8f77 | |
|
|
c30b7d743b | |
|
|
ea61c7bc35 | |
|
|
83d1bae957 | |
|
|
ff648a300c | |
|
|
17b68b5ea4 | |
|
|
045d65428b | |
|
|
063470ef1e | |
|
|
ba32042c02 | |
|
|
04550f03ff | |
|
|
fa5940aad8 | |
|
|
a0de6dc471 | |
|
|
746e8a71f0 | |
|
|
fcab5e6679 | |
|
|
70ee40d3e1 | |
|
|
4d2bfbd39d | |
|
|
a12fe985be | |
|
|
e0398e97d2 | |
|
|
32b768595e | |
|
|
a1d40d2aa6 | |
|
|
c089bf10db | |
|
|
38662755f4 | |
|
|
8f3c5f73d0 | |
|
|
47bbe8f716 | |
|
|
3491570a60 | |
|
|
da3d32b5e3 | |
|
|
6776c18568 | |
|
|
50113e5cf3 | |
|
|
3e194622e7 | |
|
|
3db53195f7 | |
|
|
29bf90b2e6 | |
|
|
45e839c3ef | |
|
|
0673614c60 | |
|
|
6a0659b90e | |
|
|
7224c4668d | |
|
|
9e4cae74d9 | |
|
|
66ab19e9e6 | |
|
|
1757ec73e0 | |
|
|
94e7ff02de | |
|
|
19c8cc97d9 | |
|
|
b4a6852cd1 | |
|
|
9ad46e744d | |
|
|
d32bd3bb22 | |
|
|
0b8f70904d | |
|
|
c693a59fcd | |
|
|
d9a2688253 | |
|
|
9a7f28a04f | |
|
|
54f4e65bf1 | |
|
|
59a1de0470 | |
|
|
207b7f72ee | |
|
|
6cff1f4c1d | |
|
|
3659936600 | |
|
|
4ef374389f | |
|
|
0bdc06b390 | |
|
|
889e905800 | |
|
|
75352d087e | |
|
|
d7a64e5842 | |
|
|
48a0faa183 | |
|
|
332bba842c | |
|
|
3ffcdba00a | |
|
|
18b44c8b1f | |
|
|
77683d278a | |
|
|
44d83480a4 | |
|
|
2b991e6e37 | |
|
|
edb3937b96 | |
|
|
00964a667d | |
|
|
fa1a4c28fb | |
|
|
09b064e02c | |
|
|
612ecfa0b7 | |
|
|
8e06b8ccb2 | |
|
|
f9081536ca | |
|
|
7b36f5a7e9 | |
|
|
d02ee39c70 | |
|
|
6abf235b7f | |
|
|
5aa84e297c | |
|
|
0aeca28290 | |
|
|
437ca4d9af | |
|
|
66ebf4b697 | |
|
|
6e05103170 | |
|
|
8eb08a3fe9 | |
|
|
5b446a2066 | |
|
|
0b2d2976dd | |
|
|
1d3f8e299c | |
|
|
238a3df895 | |
|
|
3ff2d78a07 | |
|
|
6446641421 | |
|
|
b4c2573997 | |
|
|
a11115e67b | |
|
|
b3849ae21a | |
|
|
a4e777f7ae | |
|
|
64a54226e6 | |
|
|
c3b8382f1d | |
|
|
c39954fdd6 | |
|
|
484110c925 | |
|
|
fd56161715 | |
|
|
45e73116fd | |
|
|
d658478af3 | |
|
|
f7d4e977e4 | |
|
|
1e263be310 | |
|
|
fcad450b95 | |
|
|
60a7cb79e9 | |
|
|
63b4ce23ab | |
|
|
107cabd195 | |
|
|
248804fc82 | |
|
|
b59e11c7ba | |
|
|
a93eaee137 | |
|
|
bb9efc470b | |
|
|
d4e43e214d | |
|
|
8396616aa8 | |
|
|
6497f56219 | |
|
|
e5b6d98ea5 | |
|
|
c84ee621e3 | |
|
|
368d01bb94 | |
|
|
3226b5a963 | |
|
|
8607c377bf | |
|
|
f2ddb99a63 | |
|
|
5f6cf567c7 | |
|
|
a2bd2f25e3 | |
|
|
f7f06c2538 | |
|
|
9f1d764903 | |
|
|
4cadb3e145 | |
|
|
daa4501bbe | |
|
|
60cf886195 | |
|
|
6696be6cc2 | |
|
|
21a45ca590 | |
|
|
6c34a311d0 | |
|
|
912c514fef | |
|
|
75b2eb9ad8 | |
|
|
5c77d6977d | |
|
|
552b3dc129 | |
|
|
bdb36008ba | |
|
|
43fce727d6 | |
|
|
bc846072a5 | |
|
|
7ca20decc6 | |
|
|
d1bb75a7c2 | |
|
|
874154ce49 | |
|
|
51cf9bf665 | |
|
|
cdc1712be9 | |
|
|
d247318f42 | |
|
|
30eca8d6e4 | |
|
|
a90a241126 | |
|
|
76fab728fa | |
|
|
448baccad0 | |
|
|
017fdf0f44 | |
|
|
115162d2eb | |
|
|
30664cea8f | |
|
|
e6f65ba72c | |
|
|
56c3b87d7d | |
|
|
e7d033c178 | |
|
|
518493acb9 | |
|
|
60ab069092 | |
|
|
f784fff615 | |
|
|
22fa76e1fe | |
|
|
ce30da9524 | |
|
|
263546a74e | |
|
|
2c553e90a7 | |
|
|
87bb5b2647 | |
|
|
41673978cf | |
|
|
3b4ec8298e | |
|
|
6c9d01f6a3 | |
|
|
b3dd8cfa6c | |
|
|
9eb7cabbef | |
|
|
ca01e23e65 | |
|
|
b39ffb20c4 | |
|
|
e62d24350a | |
|
|
d515188ec4 | |
|
|
3439b09f9e | |
|
|
1ca9f86eb5 | |
|
|
1b7d772db0 | |
|
|
f8bc01e48c | |
|
|
1124865649 | |
|
|
f8f3277788 | |
|
|
6aa0d2f3bf | |
|
|
d8006e0af2 | |
|
|
5f03dc91ba | |
|
|
7baf5eb647 | |
|
|
21a40178c3 | |
|
|
f5d465b7aa | |
|
|
d02d3f7b6a | |
|
|
5908f0f6f8 | |
|
|
c7199cc0bd | |
|
|
aa67ced33e | |
|
|
0fd931ab9b | |
|
|
c528844c36 | |
|
|
e368f7b784 | |
|
|
11d37c9c91 | |
|
|
fdcdb127ac | |
|
|
61cab7f51b | |
|
|
64509648bb | |
|
|
7dc9469a8b | |
|
|
e2bcb03a15 | |
|
|
7d3a67b6ee | |
|
|
0374a06a47 | |
|
|
dbe6fe123c | |
|
|
682cb285cd | |
|
|
ee9ed8df2c | |
|
|
dda46ea9b5 | |
|
|
427d10c137 | |
|
|
fa69cf7b65 | |
|
|
241a99cf72 | |
|
|
09e3751758 | |
|
|
047cda3a84 | |
|
|
b947ce66c9 | |
|
|
8f6c91b0d6 | |
|
|
6a0d413b79 | |
|
|
c140b80588 | |
|
|
650cbb8564 | |
|
|
c46011097e | |
|
|
d0e7827d06 | |
|
|
3871bb2a11 | |
|
|
ffb252e58b | |
|
|
b3dd2b40c1 | |
|
|
82f28ce75a | |
|
|
5af5f73c11 | |
|
|
b04cfc962f | |
|
|
3acc13a70d | |
|
|
820b285549 | |
|
|
d6e325dc1d | |
|
|
b6d1b858e8 | |
|
|
7efeb1955c | |
|
|
ff73d0dcb8 | |
|
|
de439f74c3 | |
|
|
97cd07f406 | |
|
|
0cd3df5ef7 | |
|
|
e5d3420edf | |
|
|
b2c73c9638 | |
|
|
a3591e1ef7 | |
|
|
1c99c1a2b0 | |
|
|
d81f5fdb5d | |
|
|
1d7c11ec5a | |
|
|
f3404ea73f | |
|
|
ab9cb7adce | |
|
|
5b3600e8a2 | |
|
|
41966c2d0b | |
|
|
c18f6ee030 | |
|
|
06ba6d625f | |
|
|
facbef8de9 | |
|
|
d916216f99 | |
|
|
ea4775bd1b | |
|
|
e8a2581696 | |
|
|
251549a4c2 | |
|
|
86a51975f4 | |
|
|
ab50e8c580 | |
|
|
49dc06a079 | |
|
|
42cc3d5edc | |
|
|
7bed28c0ed | |
|
|
8cc630507f | |
|
|
7c0b19974d | |
|
|
9a1d789475 | |
|
|
bad6238df3 | |
|
|
e7004416a8 | |
|
|
e84ecfb370 | |
|
|
7837c42670 | |
|
|
c07d2dfb97 | |
|
|
ee832ffcda | |
|
|
edf44a1943 | |
|
|
12021cddbb | |
|
|
ac6628e867 | |
|
|
cc94c2f725 | |
|
|
d955310149 | |
|
|
469b1b0576 | |
|
|
4a8bd03064 | |
|
|
35fc547908 | |
|
|
564c65cb90 | |
|
|
6b4a4dce60 | |
|
|
d24b779808 | |
|
|
8e3f5722e3 | |
|
|
c73db0a6b2 | |
|
|
8cc91dcff1 | |
|
|
713999d25c | |
|
|
450efe2d87 | |
|
|
3ad35cf1e3 | |
|
|
7bf0dfbede | |
|
|
db2771d52d | |
|
|
eb9fca0787 | |
|
|
4d6204d400 | |
|
|
f4741eca4c | |
|
|
fd45efc081 | |
|
|
6df218c9b8 | |
|
|
5333a7eb61 | |
|
|
ccad9be5bd | |
|
|
0121bf0fce | |
|
|
0fdbcd0fd4 | |
|
|
5bc9435b63 | |
|
|
9518fb4cdd | |
|
|
30dcd15276 | |
|
|
7c4cc221d9 | |
|
|
9fd351f0ea | |
|
|
606ba8218d | |
|
|
f94af5d875 | |
|
|
394f5b715d | |
|
|
113b77b14b | |
|
|
158299ca47 | |
|
|
7711e87f07 | |
|
|
8e5c648bb1 | |
|
|
6a2e0b7825 | |
|
|
f88a29b3f0 | |
|
|
e9a6b958c8 | |
|
|
0f67da4c73 | |
|
|
5f7e0bd99f | |
|
|
fdcacbd9ac | |
|
|
42e14d3be0 | |
|
|
868a29413d | |
|
|
7363e03f77 | |
|
|
9868aebb9e | |
|
|
5187948c67 | |
|
|
1fcdcbaa9f | |
|
|
56f29b8877 | |
|
|
3e73b583eb | |
|
|
4c39a47b0f | |
|
|
70aa1e2076 | |
|
|
0145a6d1e7 | |
|
|
b6eb880277 | |
|
|
b4f925cbbd | |
|
|
2e467e0478 | |
|
|
a4596b5540 | |
|
|
999764abc2 | |
|
|
083c9e0d79 | |
|
|
937f29704a | |
|
|
a847b8984c | |
|
|
8ce9ce194d | |
|
|
daaa60382d | |
|
|
5112951e99 | |
|
|
de71137dc6 | |
|
|
5a6bf02961 | |
|
|
07bbb58919 | |
|
|
839a1b74be | |
|
|
51ed2d95da | |
|
|
f15c4238a9 | |
|
|
2928aa1bc4 | |
|
|
61558f8a7b | |
|
|
2682e4c58a | |
|
|
9180801bd8 | |
|
|
e1241286b1 | |
|
|
c3c67911ff | |
|
|
06fed1df88 | |
|
|
27f711219b | |
|
|
f3d77f2327 | |
|
|
c86fe6b0ad | |
|
|
7fc02305ef | |
|
|
1590d01890 | |
|
|
3f7531774d | |
|
|
ca1b311eb0 | |
|
|
b68ed12912 | |
|
|
2b08a392f7 | |
|
|
756ce0791c | |
|
|
c9784da115 | |
|
|
bb8c02b5fc | |
|
|
fc532cd1a8 | |
|
|
b5180b5847 |
|
|
@ -2,140 +2,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const find = require('recursive-readdir');
|
||||
const { ESLint } = require("eslint");
|
||||
const argv = require('commander');
|
||||
|
||||
const translators = require('../lib/translators');
|
||||
process.argv = process.argv.map(arg => arg === '--output-json' ? [ '--format', 'json', '--output-file' ] : arg).flat();
|
||||
|
||||
argv
|
||||
.version(ESLint.version)
|
||||
.option('-o, --output-json [file | -]', 'Write report to file or stdout as JSON')
|
||||
.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;
|
||||
|
||||
async function main() {
|
||||
// split sources to lint into regular javascript (handled by lintFiles) and translators (handled by lintText)
|
||||
const sources = {
|
||||
javascripts: [],
|
||||
translators: [],
|
||||
errors: 0,
|
||||
};
|
||||
|
||||
let allResults = [];
|
||||
|
||||
function findIgnore(file, stats) {
|
||||
if (stats.isDirectory()) return (path.basename(file) == "node_modules" || path.basename(file) == ".ci");
|
||||
return !file.endsWith('.js');
|
||||
}
|
||||
for (const target of argv.args) {
|
||||
if (!fs.existsSync(target)) {
|
||||
console.error(`Target file '${target}' does not exist; skipping`); // eslint-disable-line no-console
|
||||
continue;
|
||||
}
|
||||
const files = fs.lstatSync(target).isDirectory() ? await 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 eslint = new ESLint({
|
||||
cwd: translators.cache.repo,
|
||||
fix: argv.fix,
|
||||
ignore: !!argv.ignore, // otherwise you can't lint stuff in hidden dirs
|
||||
});
|
||||
const formatter = await eslint.loadFormatter();
|
||||
function showResults(files, results) {
|
||||
if (argv.quiet) results = ESLint.getErrorResults(results);
|
||||
for (const res of results) {
|
||||
sources.errors += res.errorCount;
|
||||
}
|
||||
|
||||
if (results.length) {
|
||||
console.log(formatter.format(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 results = await eslint.lintFiles(sources.javascripts);
|
||||
if (argv.fix) {
|
||||
for (const result of 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
|
||||
}
|
||||
}
|
||||
ESLint.outputFixes(results);
|
||||
}
|
||||
if (argv.outputJson) {
|
||||
allResults.push(...results);
|
||||
}
|
||||
else {
|
||||
showResults(sources.javascripts, results);
|
||||
}
|
||||
}
|
||||
|
||||
for (const translator of sources.translators) {
|
||||
if (argv.dumpDecorated) fs.writeFileSync(argv.dumpDecorated, translator.source, 'utf-8');
|
||||
const results = await eslint.lintText(translator.source, { filePath: translator.filename });
|
||||
if (argv.fix) {
|
||||
for (const result of 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argv.outputJson) {
|
||||
allResults.push(...results);
|
||||
}
|
||||
else {
|
||||
showResults(translator.filename, results);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv.outputJson) {
|
||||
if (argv.outputJson === '-') {
|
||||
process.stdout.write(JSON.stringify(allResults) + '\n');
|
||||
}
|
||||
else {
|
||||
fs.writeFileSync(argv.outputJson, JSON.stringify(allResults), 'utf-8');
|
||||
}
|
||||
}
|
||||
else {
|
||||
process.exit(sources.errors); // eslint-disable-line no-process-exit
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
require('../../../node_modules/.bin/eslint')
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ const requireDir = require('require-dir');
|
|||
module.exports = {
|
||||
rules: requireDir('./lib/rules'),
|
||||
processors: {
|
||||
'.js': require('./lib/processor'),
|
||||
}
|
||||
translator: require('./processor'),
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
'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];
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
'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,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
'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()}"`),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
'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 translators = require('../translators').cache;
|
||||
const { parsed, json } = require('../../processor').support;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -14,14 +14,15 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (_node) {
|
||||
const translator = translators.get(context.getFilename());
|
||||
const translator = parsed(context.getFilename());
|
||||
|
||||
if (!translator.source) return; // regular js source
|
||||
if (!translator || translator.header.fields) return; // regular js source, or header is valid json
|
||||
|
||||
if (translator.header.error) {
|
||||
const err = json.try(translator.header.text, { line: 0, position: 1 });
|
||||
if (err) {
|
||||
context.report({
|
||||
message: `Could not parse header: ${translator.header.error.message}`,
|
||||
loc: { start: { line: translator.error.line, column: translator.error.column } },
|
||||
message: `Could not parse header: ${err.message}`,
|
||||
loc: { start: { line: err.line, column: err.column } },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +0,0 @@
|
|||
'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 now = new Date()
|
||||
.toISOString()
|
||||
.replace('T', ' ')
|
||||
.replace(/\..*/, '');
|
||||
|
||||
if (!header.properties.lastUpdated) {
|
||||
context.report({
|
||||
node: header.declaration,
|
||||
message: 'Header needs lastUpdated field'
|
||||
});
|
||||
}
|
||||
else if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(header.properties.lastUpdated.value)) {
|
||||
context.report({
|
||||
node: header.properties.lastUpdated,
|
||||
message: `lastUpdated field must be in YYYY-MM-DD HH:MM:SS format`,
|
||||
fix: function (fixer) {
|
||||
return fixer.replaceText(header.properties.lastUpdated, `"${now}"`);
|
||||
},
|
||||
});
|
||||
}
|
||||
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, `"${now}"`);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators');
|
||||
const { parsed } = require('../../processor').support;
|
||||
const findRoot = require("find-root");
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
|
@ -18,69 +18,63 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
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 translator = parsed(context.getFilename());
|
||||
|
||||
if (!translator) return; // regular js source
|
||||
|
||||
if (node.body.length < 2) return; // no body?
|
||||
|
||||
const options = context.options[0];
|
||||
if (!options.mustMatch) throw new Error('mustMatch not set');
|
||||
if (!options.mustMatch) throw new Error('license/mustMatch not set');
|
||||
if (!options.templateFile) throw new Error('license/templateFile not set');
|
||||
|
||||
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
|
||||
const license = context.getSourceCode().getAllComments().find((comment) => {
|
||||
return comment.type === 'Block' && comment.value.match(/(BEGIN LICENSE BLOCK[\s\S]+END LICENSE BLOCK)|(Copyright)/i);
|
||||
});
|
||||
|
||||
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;
|
||||
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.match(/copyright/i)) {
|
||||
copyright = comment;
|
||||
}
|
||||
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');
|
||||
|
||||
firstComment = firstComment || comment;
|
||||
}
|
||||
if (copyright) {
|
||||
const licenseText = '\n\n' + template.trim().replace(/\${(.*?)\}/g, (_, id) => {
|
||||
id = id.trim();
|
||||
return copyright[id] || `<undefined '${id}'>`;
|
||||
}) + '\n\n';
|
||||
context.report({
|
||||
loc: copyright.loc,
|
||||
message: `Copyright preferred to be ${options.mustMatch}`,
|
||||
message: 'Missing license block',
|
||||
loc: node.body[1].loc.start,
|
||||
fix: fixer => fixer.insertTextBefore(node.body[1], licenseText),
|
||||
});
|
||||
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}`;
|
||||
if (node.body.length > 2 && node.body[1].loc.start.line < license.loc.start.line) {
|
||||
context.report({
|
||||
loc: license.loc,
|
||||
message: 'Preferred to have license block at the top'
|
||||
});
|
||||
return;
|
||||
}
|
||||
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),
|
||||
});
|
||||
if (!license.value.match(new RegExp(options.mustMatch))) {
|
||||
context.report({
|
||||
loc: license.loc,
|
||||
message: `Copyright preferred to be ${options.mustMatch}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,7 +20,6 @@ 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 translators = require('../translators').cache;
|
||||
const { parsed } = require('../../processor').support;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -19,11 +19,8 @@ module.exports = {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ module.exports = {
|
|||
message: node.callee.property.name === 'indexOf'
|
||||
? "Unnecessary '.indexOf()', use '.includes()' instead"
|
||||
: "Unnecessary '.search()', use 'RegExp#test()' instead",
|
||||
*fix(fixer) {
|
||||
* 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)})`;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
message: "Prefer #id over [id=\"id\"]",
|
||||
*fix(fixer) {
|
||||
* fix(fixer) {
|
||||
yield fixer.replaceText(node.arguments[0], arg.replaceAll(idRe, "#$2"));
|
||||
}
|
||||
});
|
||||
|
|
@ -31,7 +31,7 @@ module.exports = {
|
|||
context.report({
|
||||
node,
|
||||
message: "Prefer .class over [class=\"class\"]",
|
||||
*fix(fixer) {
|
||||
* fix(fixer) {
|
||||
yield fixer.replaceText(node.arguments[0],
|
||||
arg.replaceAll(classRe, (_, __, name) => `.${name.replaceAll(/\s+/g, '.')}`));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
'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,6 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators').cache;
|
||||
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;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -15,132 +31,154 @@ module.exports = {
|
|||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const translator = translators.get(context.getFilename());
|
||||
const translator = parsed(context.getFilename());
|
||||
if (!translator || !translator.testcases.text) return; // regular js source, or no testcases
|
||||
|
||||
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();
|
||||
const token = sourceCode.getLastToken(node);
|
||||
if (token.type === 'Punctuator' && token.value === ';') {
|
||||
context.report({
|
||||
message: 'testCases should not have trailing semicolon',
|
||||
loc: declaration.loc.end,
|
||||
});
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (!translator.testCases || translator.testCases.error) return; // regular js or no test cases
|
||||
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',
|
||||
});
|
||||
}
|
||||
|
||||
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 nodes = declaration.declarations[0].init.elements;
|
||||
if (!Array.isArray(nodes)) {
|
||||
context.report({
|
||||
node: declaration,
|
||||
message: 'testCases must be an array',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
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({
|
||||
message: `${prefix} has invalid type "${testCase.type}"`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case has invalid type "${testCase.type}"`,
|
||||
});
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Array.isArray(testCase.items) || (testCase.type === 'web' && testCase.items === 'multiple'))) {
|
||||
context.report({
|
||||
message: `${prefix} of type "${testCase.type}" needs items`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs items`,
|
||||
});
|
||||
}
|
||||
|
||||
if (testCase.type === 'web' && typeof testCase.url !== 'string') {
|
||||
context.report({
|
||||
message: `${prefix} of type "${testCase.type}" test needs url`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" test needs url`,
|
||||
});
|
||||
}
|
||||
|
||||
if (['import', 'search'].includes(testCase.type) && !testCase.input) {
|
||||
context.report({
|
||||
message: `${prefix} of type "${testCase.type}" needs a string input`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs a string input`,
|
||||
});
|
||||
}
|
||||
else if (testCase.type === 'import' && typeof testCase.input !== 'string') {
|
||||
context.report({
|
||||
message: `${prefix} of type "${testCase.type}" needs input`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" needs input`,
|
||||
});
|
||||
}
|
||||
else if (testCase.type === 'search') {
|
||||
// console.log(JSON.stringify(testCase.input))
|
||||
const expected = ['DOI', 'ISBN', 'PMID', 'identifiers', 'contextObject', 'adsBibcode'];
|
||||
if (!Object.keys(testCase.input).every(key => expected.includes(key))) {
|
||||
let invalidKey = Object.keys(testCase.input).find(key => !expected.includes(key));
|
||||
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));
|
||||
context.report({
|
||||
message: `${prefix} of type "${testCase.type}" has invalid search term '${invalidKey}' - expected one of ${expected.join(', ')}`,
|
||||
loc,
|
||||
node,
|
||||
message: `test case of type "${testCase.type}" has invalid search term '${invalidKey}' - expected one of ${expected.join(', ')}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(testCase.items)) {
|
||||
let itemsNode = testCases[caseNo].properties
|
||||
.find(prop => prop.key.type == 'Literal' && prop.key.value == 'items')
|
||||
.value;
|
||||
for (let [itemIndex, item] of testCase.items.entries()) {
|
||||
let itemNode = itemsNode.elements[itemIndex];
|
||||
let itemLoc = itemNode.loc;
|
||||
|
||||
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',
|
||||
loc: itemLoc,
|
||||
node,
|
||||
});
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
for (let [creatorIndex, creator] of item.creators.entries()) {
|
||||
let creatorLoc = itemNode.properties
|
||||
.find(prop => prop.key.type == 'Literal' && prop.key.value == 'creators')
|
||||
.value
|
||||
.elements[creatorIndex]
|
||||
.loc;
|
||||
|
||||
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',
|
||||
loc: creatorLoc,
|
||||
});
|
||||
}
|
||||
else if (creator.fieldMode === 1 && (creator.firstName || !creator.lastName)) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator with fieldMode == 1 should have lastName and no firstName',
|
||||
loc: creatorLoc,
|
||||
});
|
||||
}
|
||||
else if (!creator.firstName && !creator.lastName) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator has no name',
|
||||
loc: creatorLoc,
|
||||
});
|
||||
}
|
||||
|
||||
if (!creator.creatorType) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'creator has no creatorType',
|
||||
loc: creatorLoc,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const translators = require('../translators');
|
||||
const { parsed } = require('../../processor').support;
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
|
|
@ -14,19 +14,14 @@ module.exports = {
|
|||
|
||||
create: function (context) {
|
||||
return {
|
||||
Program: function (node) {
|
||||
const header = translators.getHeaderFromAST(node);
|
||||
if (!header.body) return; // if there's no file header, assume it's not a translator
|
||||
Program: function (_node) {
|
||||
const translator = parsed(context.getFilename());
|
||||
if (!translator || !translator.FW) return; // regular js source, or no FW present
|
||||
|
||||
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'
|
||||
});
|
||||
}
|
||||
}
|
||||
context.report({
|
||||
loc: translator.FW.loc,
|
||||
message: 'uses deprecated Translator Framework'
|
||||
});
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
'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()}"`)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
'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`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
'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
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
'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,41 +19,11 @@ get_translator_id() {
|
|||
}
|
||||
|
||||
get_translators_to_check() {
|
||||
# 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
|
||||
# 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,8 @@ dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||
|
||||
. "$dir/helper.sh"
|
||||
|
||||
get_translators_to_check
|
||||
npm run lint -- "$TRANSLATORS_TO_CHECK"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
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,6 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "::group::Setup"
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ROOT_DIR="$( dirname "$DIR" )"
|
||||
|
||||
|
|
@ -28,11 +29,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 ..
|
||||
|
||||
npm explore chromedriver -- npm run install --detect_chromedriver_version
|
||||
echo "::endgroup::"
|
||||
|
||||
get_translators_to_check
|
||||
./selenium-test.js "$TRANSLATORS_TO_CHECK"
|
||||
node browser-test.mjs "$(get_translators_to_check)"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,150 +0,0 @@
|
|||
#!/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: 'btn-extensions-value'}), 60*1000);
|
||||
// Chrome 89+ has the extension list expanded by default
|
||||
try {
|
||||
let extBtn = await driver.findElement({css: '#btn-extensions-value'});
|
||||
await extBtn.click();
|
||||
} catch (e) {}
|
||||
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 @@
|
|||
const http = require("http");
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
import http from 'http';
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const host = 'localhost';
|
||||
const port = 8085;
|
||||
|
|
@ -9,7 +9,7 @@ var server;
|
|||
var translators = [];
|
||||
var idToTranslator = {};
|
||||
var filenameToTranslator = {};
|
||||
const rootPath = path.join(__dirname, '../..');
|
||||
const rootPath = path.join(import.meta.dirname, '../..');
|
||||
const infoRe = /^\s*{[\S\s]*?}\s*?[\r\n]/;
|
||||
|
||||
async function loadTranslators() {
|
||||
|
|
@ -19,11 +19,17 @@ 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 translatorInfo = JSON.parse(infoRe.exec(content)[0]);
|
||||
let translator = { metadata: translatorInfo, content };
|
||||
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 };
|
||||
}
|
||||
translators.push(translator);
|
||||
filenameToTranslator[file] = translator;
|
||||
idToTranslator[translatorInfo.translatorID] = translator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,17 +62,16 @@ async function requestListener(req, res) {
|
|||
res.end();
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
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 };
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
/usr/bin/xvfb-run /usr/bin/google-chrome $@
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#!/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();
|
||||
30
.eslintrc
30
.eslintrc
|
|
@ -1,11 +1,14 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2018": true
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"@zotero"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "2023"
|
||||
},
|
||||
"globals": {
|
||||
"Zotero": "readonly",
|
||||
"Z": "readonly",
|
||||
|
|
@ -23,23 +26,35 @@
|
|||
"error",
|
||||
{
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^detectWeb$|^doWeb$|^detectImport$|^doImport$|^doExport$|^detectSearch$|^doSearch$|^exports$"
|
||||
"varsIgnorePattern": "^testCases$|^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/translator-id": "error",
|
||||
"zotero-translator/last-updated": "warn",
|
||||
"zotero-translator/translator-type": "warn",
|
||||
"zotero-translator/header-translator-id": "error",
|
||||
"zotero-translator/header-last-updated": "warn",
|
||||
"zotero-translator/header-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",
|
||||
|
||||
|
|
@ -50,5 +65,6 @@
|
|||
},
|
||||
"plugins": [
|
||||
"zotero-translator"
|
||||
]
|
||||
],
|
||||
"processor": "zotero-translator/translator"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
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,6 +1,11 @@
|
|||
---
|
||||
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 regarding Zotero software.
|
||||
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.
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
|
@ -19,13 +19,8 @@ jobs:
|
|||
- name: Install Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 17
|
||||
|
||||
# Local via act
|
||||
- name: Install packages for act
|
||||
if: env.ACT == 'true'
|
||||
run: apt update && apt install -y xvfb git rsync
|
||||
|
||||
node-version: 22
|
||||
|
||||
- name: Get current connector hash
|
||||
id: get-connector-hash
|
||||
run: |
|
||||
|
|
@ -34,21 +29,19 @@ jobs:
|
|||
|
||||
- name: Cache connector code
|
||||
id: connector-cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
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: Debugging with tmate
|
||||
# uses: mxschmitt/action-tmate@v3.1
|
||||
|
||||
|
||||
- name: Install Chromium
|
||||
run: npx playwright install chromium
|
||||
|
||||
- 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
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-03-16 04:39:27"
|
||||
"lastUpdated": "2024-07-30 05:19:59"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -167,7 +167,7 @@ function scrape(doc) {
|
|||
item.abstractNote = ZU.trimInternal(abstract);
|
||||
}
|
||||
|
||||
let pdfElement = doc.querySelector('a[title=PDF]');
|
||||
let pdfElement = doc.querySelector('a[title="View PDF"]');
|
||||
if (pdfElement) {
|
||||
item.attachments.push({
|
||||
url: pdfElement.href,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,391 @@
|
|||
{
|
||||
"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,76 +2,81 @@
|
|||
"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/)?10\\.|action/doSearch\\?)",
|
||||
"target": "^https?://pubs\\.acs\\.org/(toc/|journal/|topic/|isbn/\\d|doi/(full/|abs/|epdf/|book/)?10\\.|action/(doSearch\\?|showCitFormats\\?.*doi))",
|
||||
"minVersion": "4.0.5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2019-10-07 09:04:25"
|
||||
"lastUpdated": "2024-09-30 13:50:18"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
function getSearchResults(doc, checkOnly, itemOpts) {
|
||||
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) {
|
||||
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 (!href || !title || !doi) continue;
|
||||
if (!doi) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
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;
|
||||
}
|
||||
*/
|
||||
items[href] = title;
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
let urlObj = new URL(url);
|
||||
let doi = decodeURIComponent(urlObj.pathname).match(/^\/doi\/(?:.+\/)?(10\.\d{4,}\/.+)$/);
|
||||
if (doi) {
|
||||
doi = doi[1];
|
||||
}
|
||||
return false;
|
||||
else {
|
||||
doi = urlObj.searchParams.get("doi");
|
||||
}
|
||||
return doi;
|
||||
}
|
||||
|
||||
/** ***************************
|
||||
* 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',
|
||||
|
|
@ -79,28 +84,33 @@ var suppTypeMap = {
|
|||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
return supplements;
|
||||
}
|
||||
|
||||
/** *************************
|
||||
|
|
@ -111,7 +121,28 @@ 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";
|
||||
|
|
@ -123,160 +154,117 @@ function detectWeb(doc, url) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var opts = {};
|
||||
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;
|
||||
// reduce some overhead by fetching these only once
|
||||
if (Z.getHiddenPref) {
|
||||
opts.attachSupp = Z.getHiddenPref("attachSupplementary");
|
||||
opts.attachAsLink = Z.getHiddenPref("supplementaryAsLink");
|
||||
attachSupplement = Z.getHiddenPref("attachSupplementary");
|
||||
supplementAsLink = Z.getHiddenPref("supplementaryAsLink");
|
||||
}
|
||||
|
||||
var itemOpts = {};
|
||||
if (detectWeb(doc, url) == "multiple") { // search
|
||||
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
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
// single article
|
||||
await scrape(attachSupplement && doc, url, supplementAsLink);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(items, opts) {
|
||||
for (var i = 0, n = items.length; i < n; i++) {
|
||||
processCallback(items[i], opts);
|
||||
}
|
||||
function delay(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
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 = [];
|
||||
async function scrape(doc, url, supplementAsLink) {
|
||||
let doi = getDoi(url);
|
||||
|
||||
// standard pdf and snapshot
|
||||
if (fetchItem.opts.pdf) {
|
||||
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: "Full Text PDF",
|
||||
url: fetchItem.opts.pdf,
|
||||
mimeType: "application/pdf"
|
||||
title: "Snapshot",
|
||||
url: url,
|
||||
mimeType: "text/html"
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// standard pdf
|
||||
item.attachments.push({
|
||||
title: "ACS Full Text Snapshot",
|
||||
url: '/doi/full/' + doi,
|
||||
mimeType: "text/html"
|
||||
title: "Full Text PDF",
|
||||
url: `/doi/pdf/${doi}`,
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
|
||||
// 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();
|
||||
}
|
||||
// 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();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
|
|
@ -320,10 +308,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -362,7 +346,6 @@ 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",
|
||||
|
|
@ -374,10 +357,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -435,10 +414,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "ACS Full Text Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -447,11 +422,6 @@ var testCases = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/isbn/9780841239999",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://pubs.acs.org/journal/acbcct",
|
||||
|
|
@ -461,6 +431,203 @@ 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 **/
|
||||
|
|
|
|||
493
ADS Bibcode.js
493
ADS Bibcode.js
|
|
@ -3,12 +3,12 @@
|
|||
"label": "ADS Bibcode",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "",
|
||||
"minVersion": "4.0",
|
||||
"minVersion": "6.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 8,
|
||||
"lastUpdated": "2023-06-09 17:04:40"
|
||||
"lastUpdated": "2025-04-29 03:02:00"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -34,9 +34,23 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
const preprintType = ZU.fieldIsValidForType('title', 'preprint')
|
||||
? 'preprint'
|
||||
: 'report';
|
||||
// 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.:]$/;
|
||||
|
|
@ -45,10 +59,10 @@ function detectSearch(items) {
|
|||
return !!filterQuery(items).length;
|
||||
}
|
||||
|
||||
function doSearch(items) {
|
||||
async function doSearch(items) {
|
||||
let bibcodes = filterQuery(items);
|
||||
if (!bibcodes.length) return;
|
||||
scrape(bibcodes);
|
||||
await scrape(bibcodes);
|
||||
}
|
||||
|
||||
function filterQuery(items) {
|
||||
|
|
@ -70,95 +84,93 @@ function filterQuery(items) {
|
|||
}
|
||||
|
||||
function extractId(url) {
|
||||
return /\/abs\/([^/]+)/.exec(url)[1];
|
||||
}
|
||||
|
||||
function getTypeFromId(id) {
|
||||
// bibcodes always start with 4 digit year, then bibstem
|
||||
const bibstem = id.slice(4);
|
||||
if (bibstem.startsWith("MsT") || bibstem.startsWith("PhDT")) {
|
||||
return "thesis";
|
||||
}
|
||||
else if (bibstem.startsWith("arXiv")) {
|
||||
return preprintType;
|
||||
}
|
||||
else {
|
||||
// now scan past the bibstem and find the volume number/type abbrev.
|
||||
const volume = bibstem.substring(5, 9);
|
||||
if (volume == "conf" || volume == "meet" || volume == "coll"
|
||||
|| volume == "proc" || volume == "book") {
|
||||
return "book";
|
||||
}
|
||||
else if (volume == "rept") {
|
||||
return "report";
|
||||
}
|
||||
}
|
||||
return "journalArticle";
|
||||
let m = url.match(/\/abs\/([^/]+)/);
|
||||
return m && decodeURIComponent(m[1]);
|
||||
}
|
||||
|
||||
function makePdfUrl(id) {
|
||||
return "https://ui.adsabs.harvard.edu/link_gateway/" + id + "/ARTICLE";
|
||||
}
|
||||
|
||||
function scrape(ids) {
|
||||
ZU.doGet('https://api.adsabs.harvard.edu/v1/accounts/bootstrap', function (respText) {
|
||||
let json = JSON.parse(respText);
|
||||
let token = json.access_token;
|
||||
// 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;
|
||||
}
|
||||
|
||||
let exportUrl = "https://ui.adsabs.harvard.edu/v1/export/ris";
|
||||
let body = JSON.stringify({
|
||||
bibcode: ids,
|
||||
sort: ['date desc, bibcode desc']
|
||||
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"
|
||||
});
|
||||
|
||||
ZU.doPost(exportUrl, body, function (respText) {
|
||||
let json = JSON.parse(respText);
|
||||
if (item.journalAbbreviation == item.publicationTitle) {
|
||||
delete item.journalAbbreviation;
|
||||
}
|
||||
|
||||
const translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7"); // RIS
|
||||
translator.setString(json.export);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
const id = extractId(item.url);
|
||||
let detectedType = getTypeFromId(id);
|
||||
if (detectedType != item.itemType) {
|
||||
Z.debug(`Changing item type: ${item.itemType} -> ${detectedType}`);
|
||||
item.itemType = detectedType;
|
||||
}
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
|
||||
item.extra = (item.extra || '') + `\nADS Bibcode: ${id}`;
|
||||
item.libraryCatalog = 'NASA ADS';
|
||||
|
||||
if (id.slice(4).startsWith('arXiv')) {
|
||||
if (preprintType == "report") {
|
||||
item.extra += '\nType: article'; // will map to preprint
|
||||
}
|
||||
}
|
||||
|
||||
if (item.pages && item.pages.startsWith('arXiv:')) {
|
||||
// not sure why this ends up in the SP tag
|
||||
delete item.pages;
|
||||
}
|
||||
|
||||
item.attachments.push({
|
||||
url: makePdfUrl(id),
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
|
||||
if (item.journalAbbreviation == item.publicationTitle) {
|
||||
item.journalAbbreviation = '';
|
||||
}
|
||||
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
|
||||
item.libraryCatalog = 'NASA ADS';
|
||||
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
}, { Authorization: 'Bearer:' + token });
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
|
|
@ -253,6 +265,7 @@ var testCases = [
|
|||
"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": [
|
||||
{
|
||||
|
|
@ -415,121 +428,67 @@ var testCases = [
|
|||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"adsBibcode": "2023arXiv230604024S"
|
||||
"adsBibcode": "2020jsrs.conf..209S"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "preprint",
|
||||
"title": "The FLAMINGO project: cosmological hydrodynamical simulations for large-scale structure and galaxy cluster surveys",
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Atmospheric angular momentum related to Earth rotation studies: history and modern developments",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Schaye",
|
||||
"firstName": "Joop",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Kugel",
|
||||
"firstName": "Roi",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Schaller",
|
||||
"firstName": "Matthieu",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Helly",
|
||||
"firstName": "John C.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Braspenning",
|
||||
"firstName": "Joey",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Elbers",
|
||||
"firstName": "Willem",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "McCarthy",
|
||||
"firstName": "Ian G.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "van Daalen",
|
||||
"firstName": "Marcel P.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Vandenbroucke",
|
||||
"firstName": "Bert",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Frenk",
|
||||
"firstName": "Carlos S.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Kwan",
|
||||
"firstName": "Juliana",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Salcido",
|
||||
"firstName": "Jaime",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Bahé",
|
||||
"firstName": "Yannick M.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Borrow",
|
||||
"firstName": "Josh",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Chaikin",
|
||||
"firstName": "Evgenii",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Hahn",
|
||||
"firstName": "Oliver",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Huško",
|
||||
"firstName": "Filip",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Jenkins",
|
||||
"firstName": "Adrian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Lacey",
|
||||
"firstName": "Cedric G.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Nobels",
|
||||
"firstName": "Folkert S. J.",
|
||||
"lastName": "Salstein",
|
||||
"firstName": "D.",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-06-01",
|
||||
"DOI": "10.48550/arXiv.2306.04024",
|
||||
"abstractNote": "We introduce the Virgo Consortium's FLAMINGO suite of hydrodynamical simulations for cosmology and galaxy cluster physics. To ensure the simulations are sufficiently realistic for studies of large-scale structure, the subgrid prescriptions for stellar and AGN feedback are calibrated to the observed low-redshift galaxy stellar mass function and cluster gas fractions. The calibration is performed using machine learning, separately for three resolutions. This approach enables specification of the model by the observables to which they are calibrated. The calibration accounts for a number of potential observational biases and for random errors in the observed stellar masses. The two most demanding simulations have box sizes of 1.0 and 2.8 Gpc and baryonic particle masses of $1\\times10^8$ and $1\\times10^9 \\text{M}_\\odot$, respectively. For the latter resolution the suite includes 12 model variations in a 1 Gpc box. There are 8 variations at fixed cosmology, including shifts in the stellar mass function and/or the cluster gas fractions to which we calibrate, and two alternative implementations of AGN feedback (thermal or jets). The remaining 4 variations use the unmodified calibration data but different cosmologies, including different neutrino masses. The 2.8 Gpc simulation follows $3\\times10^{11}$ particles, making it the largest ever hydrodynamical simulation run to $z=0$. Lightcone output is produced on-the-fly for up to 8 different observers. We investigate numerical convergence, show that the simulations reproduce the calibration data, and compare with a number of galaxy, cluster, and large-scale structure observations, finding very good agreement with the data for converged predictions. Finally, by comparing hydrodynamical and `dark-matter-only' simulations, we confirm that baryonic effects can suppress the halo mass function and the matter power spectrum by up to $\\approx20$ per cent.",
|
||||
"extra": "ADS Bibcode: 2023arXiv230604024S",
|
||||
"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",
|
||||
"shortTitle": "The FLAMINGO project",
|
||||
"url": "https://ui.adsabs.harvard.edu/abs/2023arXiv230604024S",
|
||||
"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",
|
||||
|
|
@ -538,10 +497,162 @@ var testCases = [
|
|||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Astrophysics - Astrophysics of Galaxies"
|
||||
"tag": "53C"
|
||||
},
|
||||
{
|
||||
"tag": "Astrophysics - Cosmology and Nongalactic Astrophysics"
|
||||
"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": [],
|
||||
|
|
|
|||
235
AEA Web.js
235
AEA Web.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2016-08-27 10:23:44"
|
||||
"lastUpdated": "2025-05-08 17:43:18"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -93,6 +93,13 @@ 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();
|
||||
});
|
||||
|
|
@ -102,7 +109,7 @@ function scrape(doc, url) {
|
|||
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
|
|
@ -133,6 +140,7 @@ 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",
|
||||
|
|
@ -142,12 +150,46 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
|
|
@ -177,6 +219,7 @@ 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",
|
||||
|
|
@ -186,12 +229,43 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
|
|
@ -221,6 +295,7 @@ 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",
|
||||
|
|
@ -230,16 +305,146 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,313 @@
|
|||
{
|
||||
"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,45 +1,61 @@
|
|||
{
|
||||
"translatorID": "a354331-981b-43de-a61-bc26dd1be3a9",
|
||||
"translatorID": "16f2936d-a059-40e8-a48e-f0acbb1e93e0",
|
||||
"label": "AMS MathSciNet",
|
||||
"creator": "Simon Kornblith",
|
||||
"target": "^https?://(mathscinet\\.)?ams\\.[^/]*/mathscinet(\\-getitem\\?|/search/(publications\\.html|publdoc\\.html))",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://mathscinet\\.ams\\.[^/]*/mathscinet/(article\\?|publications-search\\?|author\\?)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2017-10-20 16:08:00"
|
||||
"lastUpdated": "2023-07-14 11:04:37"
|
||||
}
|
||||
|
||||
/*
|
||||
***** 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"
|
||||
} 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";
|
||||
}
|
||||
return "multiple";
|
||||
}
|
||||
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;
|
||||
//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"]')
|
||||
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);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
|
|
@ -48,74 +64,51 @@ 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) {
|
||||
return true;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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
|
||||
});
|
||||
translator.translate();
|
||||
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-getitem?mr=3004573",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=3004573",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -139,18 +132,18 @@ var testCases = [
|
|||
],
|
||||
"date": "2013",
|
||||
"DOI": "10.1016/j.jmva.2012.11.004",
|
||||
"ISSN": "0047-259X",
|
||||
"ISSN": "0047-259X,1095-7243",
|
||||
"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": "MathSciNet Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -161,12 +154,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"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-getitem?mr=2767535",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=2767535",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -189,16 +177,17 @@ 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": "MathSciNet Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -206,10 +195,10 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=2663710",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=2663710",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -233,10 +222,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": "MathSciNet Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -251,7 +240,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://mathscinet.ams.org/mathscinet-getitem?mr=1346201",
|
||||
"url": "https://mathscinet.ams.org/mathscinet/article?mr=1346201",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -272,11 +261,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": "MathSciNet Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -284,6 +273,16 @@ 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 **/
|
||||
|
|
|
|||
302
APA PsycNET.js
302
APA PsycNET.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-11-02 16:50:48"
|
||||
"lastUpdated": "2025-03-10 19:48:42"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -52,12 +52,12 @@ function detectWeb(doc, url) {
|
|||
|| url.includes('/fulltext/')
|
||||
|| url.includes('/buy/')
|
||||
|| url.includes('/doiLanding?doi=')) {
|
||||
if (doc.getElementById('bookchapterstoc')) {
|
||||
return "book";
|
||||
}
|
||||
else if (attr(doc, 'meta[property="og:type"]', 'content') == 'Chapter') {
|
||||
if (attr(doc, 'meta[name="og:type"]', 'content') == 'Chapter') {
|
||||
return "bookSection";
|
||||
}
|
||||
else if (doc.getElementById('bookchapterstoc')) {
|
||||
return "book";
|
||||
}
|
||||
else {
|
||||
return "journalArticle";
|
||||
}
|
||||
|
|
@ -91,9 +91,9 @@ async function doWeb(doc, url) {
|
|||
if (!items) {
|
||||
return;
|
||||
}
|
||||
await Promise.all(
|
||||
Object.keys(items).map(async url => scrape(await requestDocument(url), url))
|
||||
);
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url), url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc, url);
|
||||
|
|
@ -132,7 +132,7 @@ async function scrape(doc, url) {
|
|||
var postData = JSON.stringify({
|
||||
api: "record.exportRISFile",
|
||||
params: {
|
||||
UIDList: [{UID: uid, ProductCode: productCode}],
|
||||
UIDList: [{ UID: uid, ProductCode: productCode }],
|
||||
exportType: "zotero"
|
||||
}
|
||||
});
|
||||
|
|
@ -151,7 +151,7 @@ async function scrape(doc, url) {
|
|||
// 2. Download the requested data (after step 1)
|
||||
let data = await requestText('/ris/download');
|
||||
if (data.includes('Content: application/x-research-info-systems')) {
|
||||
processRIS(data, doc);
|
||||
await processRIS(data, doc);
|
||||
}
|
||||
else {
|
||||
// sometimes (e.g. during testing) the data is not loaded
|
||||
|
|
@ -165,7 +165,34 @@ async function scrape(doc, url) {
|
|||
}
|
||||
|
||||
|
||||
function processRIS(text, doc) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
|
|
@ -176,10 +203,12 @@ function processRIS(text, doc) {
|
|||
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,
|
||||
|
|
@ -187,19 +216,21 @@ function processRIS(text, doc) {
|
|||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
await 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)
|
||||
Z.debug('Finding IDs in ' + url);
|
||||
// try to extract uid from the table
|
||||
var uid = text(doc, '#uid + dd') || text(doc, '#bookUID');
|
||||
if (uid) {
|
||||
|
|
@ -207,8 +238,8 @@ async function getIds(doc, url) {
|
|||
}
|
||||
|
||||
// try to extract uid from the url
|
||||
if (url.includes('/record/')) {
|
||||
let m = url.match(/\/record\/([\d-]*)/);
|
||||
if (url.includes('/record/') || url.includes('/fulltext/')) {
|
||||
let m = url.match(/\/(?:record|fulltext)\/([\d-]*)/);
|
||||
if (m && m[1]) {
|
||||
return m[1];
|
||||
}
|
||||
|
|
@ -313,7 +344,7 @@ function cleanTitle(title) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/record/2004-16644-010",
|
||||
"url": "https://psycnet.apa.org/record/2004-16644-010",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -337,17 +368,18 @@ var testCases = [
|
|||
],
|
||||
"date": "2004",
|
||||
"DOI": "10.1037/0894-4105.18.3.485",
|
||||
"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)",
|
||||
"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)",
|
||||
"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"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -364,7 +396,7 @@ var testCases = [
|
|||
"tag": "Experimentation"
|
||||
},
|
||||
{
|
||||
"tag": "Hyperkinesis"
|
||||
"tag": "Hyperactivity"
|
||||
},
|
||||
{
|
||||
"tag": "Inhibition (Personality)"
|
||||
|
|
@ -386,7 +418,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/record/1956-05944-001",
|
||||
"url": "https://psycnet.apa.org/record/1956-05944-001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -405,16 +437,17 @@ var testCases = [
|
|||
],
|
||||
"date": "1955",
|
||||
"DOI": "10.1037/h0043965",
|
||||
"ISSN": "0022-1015(Print)",
|
||||
"ISSN": "0022-1015",
|
||||
"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"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -441,7 +474,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/record/1992-98221-010",
|
||||
"url": "https://psycnet.apa.org/record/1992-98221-010",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -460,9 +494,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) 2016 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) 2022 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",
|
||||
|
|
@ -470,7 +504,8 @@ var testCases = [
|
|||
"shortTitle": "Catatonia",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -506,7 +541,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/record/2004-16329-000?doi=1",
|
||||
"url": "https://psycnet.apa.org/record/2004-16329-000?doi=1",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -519,9 +555,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) 2016 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) 2022 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",
|
||||
|
|
@ -529,7 +565,8 @@ var testCases = [
|
|||
"shortTitle": "The abnormal personality",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -542,9 +579,99 @@ 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",
|
||||
|
|
@ -585,7 +712,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/buy/2010-19350-001",
|
||||
"url": "https://psycnet.apa.org/record/2010-19350-001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -619,16 +746,17 @@ var testCases = [
|
|||
],
|
||||
"date": "2010",
|
||||
"DOI": "10.1037/a0020280",
|
||||
"ISSN": "1939-2222(Electronic),0096-3445(Print)",
|
||||
"ISSN": "1939-2222",
|
||||
"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"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -658,7 +786,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://psycnet.apa.org/record/2010-09295-002",
|
||||
"url": "https://psycnet.apa.org/record/2010-09295-002",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -672,17 +801,18 @@ 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) 2017 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) 2024 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": "Snapshot"
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -700,6 +830,86 @@ 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 **/
|
||||
|
|
|
|||
228
APS.js
228
APS.js
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"translatorID": "2c310a37-a4dd-48d2-82c9-bd29c53c1c76",
|
||||
"label": "APS",
|
||||
"creator": "Aurimas Vinckevicius",
|
||||
"creator": "Aurimas Vinckevicius and Abe Jellinek",
|
||||
"target": "^https?://journals\\.aps\\.org/([^/]+/(abstract|supplemental|references|cited-by|issues)/|search(\\?|/))",
|
||||
"minVersion": "3.0.12",
|
||||
"maxVersion": "",
|
||||
|
|
@ -9,24 +9,52 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2017-01-14 21:44:41"
|
||||
"lastUpdated": "2024-11-21 18:50:09"
|
||||
}
|
||||
|
||||
/*
|
||||
***** 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) {
|
||||
var title = doc.getElementById('title');
|
||||
if (title && ZU.xpath(title, './/a[@id="export-article-link"]').length) {
|
||||
if (doc.querySelector('#article-body #export-article-dialog')
|
||||
|| doc.querySelector('main#main') && /^\/[^/]+\/(abstract|supplemental|references|cited-by)\//.test(new URL(url).pathname)) {
|
||||
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 = ZU.xpath(doc, '//div[contains(@class, "search-results")]//div[contains(@class, "row")]//h5/a');
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
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 href = rows[i].href;
|
||||
var title = ZU.trimInternal(cleanMath(rows[i].textContent));
|
||||
if (!href || !title) continue;
|
||||
|
|
@ -42,7 +70,7 @@ function doWeb(doc, url) {
|
|||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
|
|
@ -50,7 +78,8 @@ function doWeb(doc, url) {
|
|||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
|
@ -58,13 +87,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 = [
|
||||
|
|
@ -75,20 +104,20 @@ var dontDownload = [
|
|||
function scrape(doc, url) {
|
||||
url = url.replace(/[?#].*/, '');
|
||||
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
if (!url.includes('/abstract/')) {
|
||||
// Go to Abstract page first so we can scrape the abstract
|
||||
url = url.replace(/\/(?:supplemental|references|cited-by)\//, '/abstract/');
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
if (!url.includes('/abstract/')) {
|
||||
Zotero.debug('Unrecognized URL ' + url);
|
||||
return;
|
||||
}
|
||||
|
||||
ZU.processDocuments(url, function(doc, url) {
|
||||
if (url.indexOf('/abstract/') == -1) {
|
||||
ZU.processDocuments(url, function (doc, url) {
|
||||
if (!url.includes('/abstract/')) {
|
||||
Zotero.debug('Redirected when trying to go to abstract page. ' + url);
|
||||
return;
|
||||
}
|
||||
scrape(doc, url)
|
||||
scrape(doc, url);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -97,26 +126,23 @@ function scrape(doc, url) {
|
|||
|
||||
// fetch RIS
|
||||
var risUrl = url.replace('{REPLACE}', 'export')
|
||||
+ '?type=ris&download=true';
|
||||
ZU.doGet(risUrl, function(text) {
|
||||
text = text.replace(/^ID\s+-\s+/mg, 'DO - ');
|
||||
+ '?type=ris&download=true';
|
||||
ZU.doGet(risUrl, function (risText) {
|
||||
risText = risText.replace(/^ID\s+-\s+/mg, 'DO - ');
|
||||
var trans = Zotero.loadTranslator('import');
|
||||
trans.setTranslator('32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7'); //RIS
|
||||
trans.setString(text);
|
||||
trans.setHandler('itemDone', function(obj, item) {
|
||||
trans.setString(risText);
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
// scrape abstract from page
|
||||
item.abstractNote = ZU.trimInternal(cleanMath(
|
||||
ZU.xpathText(doc, '//section[contains(@class,"abstract")]/div[@class="content"]/p[1]')
|
||||
text(doc, '#abstract-section-content p')
|
||||
));
|
||||
|
||||
// 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: 'Full Text PDF',
|
||||
url: url.replace('{REPLACE}', 'pdf'),
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
|
||||
item.attachments.push({
|
||||
title: "APS Snapshot",
|
||||
|
|
@ -124,38 +150,37 @@ function scrape(doc, url) {
|
|||
});
|
||||
|
||||
if (Z.getHiddenPref && Z.getHiddenPref('attachSupplementary')) {
|
||||
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
|
||||
});
|
||||
}
|
||||
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
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
Z.debug('Could not attach supplemental data');
|
||||
Z.debug(e);
|
||||
}
|
||||
}, function() { item.complete() });
|
||||
} else {
|
||||
item.complete();
|
||||
}
|
||||
catch (e) {
|
||||
Z.debug('Could not attach supplemental data');
|
||||
Z.debug(e);
|
||||
}
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
|
|
@ -165,6 +190,7 @@ 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 = [
|
||||
{
|
||||
|
|
@ -186,7 +212,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "October 21, 2011",
|
||||
"date": "2011-10-21",
|
||||
"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",
|
||||
|
|
@ -202,7 +228,8 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot"
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -260,9 +287,9 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "March 4, 2015",
|
||||
"date": "2015-03-04",
|
||||
"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 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.",
|
||||
"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.",
|
||||
"issue": "9",
|
||||
"journalAbbreviation": "Phys. Rev. Lett.",
|
||||
"libraryCatalog": "APS",
|
||||
|
|
@ -276,7 +303,8 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot"
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -319,7 +347,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "March 17, 2015",
|
||||
"date": "2015-03-17",
|
||||
"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",
|
||||
|
|
@ -335,7 +363,8 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot"
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -378,7 +407,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "March 17, 2015",
|
||||
"date": "2015-03-17",
|
||||
"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",
|
||||
|
|
@ -394,7 +423,8 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot"
|
||||
"title": "APS Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -437,7 +467,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "January 20, 2015",
|
||||
"date": "2015-01-20",
|
||||
"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",
|
||||
|
|
@ -453,7 +483,53 @@ var testCases = [
|
|||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "APS Snapshot"
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -463,4 +539,4 @@ var testCases = [
|
|||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "d120a8a7-9d45-446e-8c18-ad9ef0a6bf47",
|
||||
"label": "Access Engineering",
|
||||
"creator": "Vinoth K - highwirepress.com",
|
||||
"target": "^https?://www\\.accessengineeringlibrary\\.com/content/(book|chapter|case-study|video|calculator|tutorial)",
|
||||
"target": "^https?://www\\.accessengineeringlibrary\\.com/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-03-07 08:48:13"
|
||||
"lastUpdated": "2023-09-09 09:42:36"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -97,13 +97,16 @@ function scrape(doc, url) {
|
|||
if (edition) item.edition = edition;
|
||||
|
||||
// Author
|
||||
let author = ZU.xpath(doc, '//ul[@class="contributor-list"]//li//a');
|
||||
if (author.length > 0) {
|
||||
// Handled using data attribute
|
||||
for (let i = 0; i < author.length; i++) {
|
||||
item.creators[i].firstName = author[i].getAttribute('data-firstnames');
|
||||
item.creators[i].lastName = author[i].getAttribute('data-surname');
|
||||
}
|
||||
// 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
|
||||
|
|
@ -116,12 +119,7 @@ function scrape(doc, url) {
|
|||
translator.getTranslatorObject(function (trans) {
|
||||
// Detect web not get trigger for scape EM translator
|
||||
// - so wll fill those in manually.
|
||||
if (detectWeb(doc, url)) {
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
}
|
||||
trans.addCustomFields({
|
||||
citation_book_title: "bookTitle"
|
||||
});
|
||||
trans.itemType = detectWeb(doc, url);
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
|
@ -130,26 +128,51 @@ function scrape(doc, url) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860386/",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "3D Printer Projects for Makerspaces",
|
||||
"title": "Handbook of Environmental Engineering",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Lydia Sloan",
|
||||
"lastName": "Cline",
|
||||
"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": "2017",
|
||||
"ISBN": "9781259860386",
|
||||
"abstractNote": "Learn to model and print 3D designs—no experience required!This easy-to-follow guide features twenty 3D printing projects for makers of all skill levels to enjoy. Written in a tutorial, step-by-step manner, 3D Printer Projects for Makerspaces shows how to use Fusion 360, SketchUp, Meshmixer, Remake, and Inkscape to create fun and useful things. Scanning, slicers, silicone molds, settings, and build plate orientation are also covered, as well as post-processing methods that will make your prints really pop!Inside, you9ll learn to model, analyze, and print a:• Phone case• Coin bank• Art stencil• Cookie cutter• Cookie dunker• Personalized key fob• Lens cap holder• Lithophane night-light• Pencil cup with applied sketch• Business card with QR code• Bronze pendant• Soap mold• Hanging lampshade• Scanned Buddha charm• And more!",
|
||||
"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/9781259860386",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -164,28 +187,61 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860386/chapter/chapter12",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225/toc-chapter/chapter3/section/section1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "PROJECT 12: Lithophane Night-Light",
|
||||
"title": "CHAPTER PRELIMINARIES",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Lydia Sloan",
|
||||
"lastName": "Cline",
|
||||
"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": "2017",
|
||||
"ISBN": "9781259860386",
|
||||
"abstractNote": "Learn to model and print 3D designs—no experience required!This easy-to-follow guide features twenty 3D printing projects for makers of all skill levels to enjoy. Written in a tutorial, step-by-step manner, 3D Printer Projects for Makerspaces shows how to use Fusion 360, SketchUp, Meshmixer, Remake, and Inkscape to create fun and useful things. Scanning, slicers, silicone molds, settings, and build plate orientation are also covered, as well as post-processing methods that will make your prints really pop!Inside, you'll learn to model, analyze, and print a:• Phone case• Coin bank• Art stencil• Cookie cutter• Cookie dunker• Personalized key fob• Lens cap holder• Lithophane night-light• Pencil cup with applied sketch• Business card with QR code• Bronze pendant• Soap mold• Hanging lampshade• Scanned Buddha charm• And more!",
|
||||
"bookTitle": "3D Printer Projects for Makerspaces",
|
||||
"edition": "1st Edition",
|
||||
"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",
|
||||
"shortTitle": "PROJECT 12",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860386/chapter/chapter12",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/book/9781259860225/toc-chapter/chapter3/section/section1",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -200,24 +256,19 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/video/V4768153299001",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/video/V4005352521001",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "10% Infill and a Bridge",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Lydia",
|
||||
"lastName": "Cline",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2016",
|
||||
"abstractNote": "This video shows an item being printed with a 10% infill and includes a bridge.",
|
||||
"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/V4768153299001",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/video/V4005352521001",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -232,23 +283,23 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/calculator/S0018_Analysis_of_AC_and_DC_Circuits_Basic_Calculations",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/calculator/S0071_Basic_Transformer_Calculations",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Analysis of A.C. and D.C. Circuits - Basic Calculations",
|
||||
"title": "Basic Transformer Calculations",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "William",
|
||||
"lastName": "Prudhomme",
|
||||
"firstName": "Bhagyalakshmi",
|
||||
"lastName": "Kerekare",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018/12/13/",
|
||||
"abstractNote": "Software simulation programs are generally used for modeling and designing complex electronic circuits and applications, but frequently only a basic calculation is needed to solve an immediate design problem or to calculate the value of a specific circuit element. This Excel workbook addresses this need by automating the calculation of over 70 basic electronics formulas in direct current (d.c.) and alternating current (a.c.) circuits and applications.",
|
||||
"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/S0018_Analysis_of_AC_and_DC_Circuits_Basic_Calculations",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/calculator/S0071_Basic_Transformer_Calculations",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -295,23 +346,23 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/tutorial/T0002_Open_Channel_Flow_Calculations_with_the_Manning_Equation",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/tutorial/T0004_Partially_Full_Pipe_Flow_Calculations_Using_Excel_Spreadsheets",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Open Channel Flow Calculations with the Manning Equation using Excel Spreadsheets",
|
||||
"title": "Partially Full Pipe Flow Calculations Using Excel Spreadsheets",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Harlan",
|
||||
"lastName": "H. Bengtson",
|
||||
"firstName": "Harlan H.",
|
||||
"lastName": "Bengtson",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2014-02-01",
|
||||
"abstractNote": "This tutorial teaches the Manning equation and its use for uniform open channel flow calculations, including the hydraulic radius, Manning roughness coefficient, and normal depth. There are example problems and illustrations show how to use spreadsheets for the calculations.",
|
||||
"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/T0002_Open_Channel_Flow_Calculations_with_the_Manning_Equation",
|
||||
"url": "https://www.accessengineeringlibrary.com/content/tutorial/T0004_Partially_Full_Pipe_Flow_Calculations_Using_Excel_Spreadsheets",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,391 @@
|
|||
{
|
||||
"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 **/
|
||||
78
Alsharekh.js
78
Alsharekh.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-04 18:27:28"
|
||||
"lastUpdated": "2023-07-24 02:21:59"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -43,7 +43,11 @@ function detectWeb(doc, url) {
|
|||
if (urlRe.test(url)) {
|
||||
return "magazineArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
let appElem = doc.querySelector("app-root");
|
||||
if (appElem) {
|
||||
Z.monitorDOMChanges(appElem);
|
||||
}
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
|
|
@ -52,11 +56,9 @@ function detectWeb(doc, url) {
|
|||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('td > a[href*="/Articles/"]');
|
||||
var rows = doc.querySelectorAll('td > a[href^="/Articles/"], th > a[href^="/Articles/"]');
|
||||
for (let row of rows) {
|
||||
// TODO: check and maybe adjust
|
||||
let href = row.href;
|
||||
// TODO: check and maybe adjust
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
|
|
@ -66,45 +68,47 @@ function getSearchResults(doc, checkOnly) {
|
|||
return found ? items : false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (items) ZU.processDocuments(Object.keys(items), scrape);
|
||||
});
|
||||
let items = await Z.selectItems(getSearchResults(doc));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(null, url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
async function scrape(doc, url) {
|
||||
let item = new Zotero.Item('magazineArticle');
|
||||
|
||||
let [, MID, IID, AID] = url.match(urlRe);
|
||||
ZU.doGet(`${apiBase}/Search/IssueHInfo?MID=${MID}&IID=${IID}`, function (respText) {
|
||||
let issue = JSON.parse(respText);
|
||||
ZU.doGet(`${apiBase}/Search/ArticleHInfo?AID=${AID}`, function (respText) {
|
||||
let article = JSON.parse(respText);
|
||||
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;
|
||||
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
item.complete();
|
||||
});
|
||||
});
|
||||
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
|
||||
|
|
@ -226,6 +230,12 @@ var testCases = [
|
|||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
11
Amazon.js
11
Amazon.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-12-15 05:18:20"
|
||||
"lastUpdated": "2025-03-20 15:38:12"
|
||||
}
|
||||
|
||||
function detectWeb(doc, _url) {
|
||||
|
|
@ -279,8 +279,10 @@ 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")]'))
|
||||
.replace(/\s*\([^)]+\)/, '').replace(/,\s*$/, '');
|
||||
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*$/, '');
|
||||
if (item.itemType == 'audioRecording') {
|
||||
item.creators.push({
|
||||
lastName: name,
|
||||
|
|
@ -464,7 +466,6 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -869,7 +870,7 @@ var testCases = [
|
|||
"numPages": 1328,
|
||||
"publisher": "Vintage",
|
||||
"shortTitle": "1Q84",
|
||||
"place": "London",
|
||||
"place": "London",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Amazon.com Link",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,382 @@
|
|||
{
|
||||
"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 **/
|
||||
|
|
@ -0,0 +1,390 @@
|
|||
{
|
||||
"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 **/
|
||||
|
|
@ -2,21 +2,21 @@
|
|||
"translatorID": "5ed5ab01-899f-4a3b-a74c-290fb2a1c9a4",
|
||||
"label": "AustLII and NZLII",
|
||||
"creator": "Justin Warren, Philipp Zumstein",
|
||||
"target": "^https?://www\\d?\\.(austlii\\.edu\\.au|nzlii\\.org)",
|
||||
"target": "^https?://(www\\d?|classic)\\.(austlii\\.edu\\.au|nzlii\\.org)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2018-03-02 09:46:09"
|
||||
"lastUpdated": "2024-11-21 18:54:11"
|
||||
}
|
||||
|
||||
/*
|
||||
***** 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,15 +35,9 @@
|
|||
***** 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";
|
||||
}
|
||||
|
|
@ -59,9 +53,13 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -69,7 +67,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;
|
||||
|
|
@ -82,49 +80,111 @@ function getSearchResults(doc, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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 jurisdiction = text(doc, 'li.ribbon-jurisdiction>a>span');
|
||||
if (jurisdiction) {
|
||||
newItem.extra = "jurisdiction: " + jurisdiction;
|
||||
var fullJurisdiction = text(doc, 'li.ribbon-jurisdiction > a > span');
|
||||
var jurisdiction = jurisdictionAbbrev[fullJurisdiction] || fullJurisdiction;
|
||||
if (jurisdiction && ZU.fieldIsValidForType('code', type)) {
|
||||
newItem.code = jurisdiction;
|
||||
}
|
||||
var citation = text(doc, 'li.ribbon-citation>a>span');
|
||||
|
||||
|
||||
var voliss;
|
||||
var m;
|
||||
|
||||
if (text(doc, '#ribbon')) {
|
||||
if (type == "case") {
|
||||
var voliss = text(doc, 'head>title');
|
||||
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');
|
||||
}
|
||||
newItem.court = text(doc, 'li.ribbon-database>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');
|
||||
}
|
||||
if (citation) {
|
||||
var lastNumber = citation.match(/(\d+)$/);
|
||||
if (lastNumber) {
|
||||
|
|
@ -133,49 +193,56 @@ function scrape(doc, url) {
|
|||
}
|
||||
}
|
||||
if (type == "statute") {
|
||||
// title
|
||||
newItem.nameOfAct = citation.trim();
|
||||
// All AustLII Act titles end in the year the Act was passed
|
||||
const actInfo = parseActName(citation);
|
||||
newItem.nameOfAct = actInfo.actName;
|
||||
newItem.dateEnacted = actInfo.actYear;
|
||||
// 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');
|
||||
var m = title.match(/(.*) --- "([^"]*)"/);
|
||||
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 {
|
||||
var voliss = text(doc, 'head>title');
|
||||
}
|
||||
else {
|
||||
voliss = text(doc, 'head>title');
|
||||
// e.g. C & M [2006] FamCA 212 (20 January 2006)
|
||||
var m = voliss.match(/^([^[]*)\[(\d+)\](.*)\(([^\)]*)\)$/);
|
||||
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;
|
||||
|
||||
newItem.url = url
|
||||
.replace(/^http:\/\//, 'https://')
|
||||
.replace(/^(https:\/\/www)\d/, '$1');
|
||||
newItem.attachments = [{
|
||||
document: doc,
|
||||
title: "Snapshot",
|
||||
mimeType:"text/html"
|
||||
mimeType: "text/html"
|
||||
}];
|
||||
newItem.complete();
|
||||
}
|
||||
|
|
@ -184,17 +251,16 @@ function scrape(doc, url) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www7.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"url": "http://www.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": "Family Court of Australia",
|
||||
"court": "FamCA",
|
||||
"docketNumber": "212",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www7.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FamCA/2006/212.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -209,17 +275,16 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"url": "http://www.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": "Federal Court of Australia",
|
||||
"court": "FCA",
|
||||
"docketNumber": "1",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/FCA/2010/1.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -243,7 +308,7 @@ var testCases = [
|
|||
"dateDecided": "2008-02-08",
|
||||
"court": "NZSC",
|
||||
"docketNumber": "1",
|
||||
"url": "http://www.nzlii.org/nz/cases/NZSC/2008/1.html",
|
||||
"url": "https://www.nzlii.org/nz/cases/NZSC/2008/1.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -258,22 +323,21 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewtoc/au/cases/act/ACTSC/2010/",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewtoc/au/cases/act/ACTSC/2010/",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"url": "http://www.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": "Australian Information Commissioner",
|
||||
"court": "AICmr",
|
||||
"docketNumber": "134",
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/134.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -288,15 +352,16 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Freedom of Information Act 1982",
|
||||
"nameOfAct": "Freedom of Information Act",
|
||||
"creators": [],
|
||||
"extra": "jurisdiction: Commonwealth",
|
||||
"dateEnacted": "1982",
|
||||
"code": "Cth",
|
||||
"section": "24AB",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/foia1982222/s24ab.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -311,14 +376,15 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"url": "http://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Freedom of Information Act 1982",
|
||||
"nameOfAct": "Freedom of Information Act",
|
||||
"creators": [],
|
||||
"extra": "jurisdiction: CTH",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"dateEnacted": "1982",
|
||||
"code": "Cth",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/foia1982222/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -333,7 +399,53 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www9.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"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",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -353,7 +465,7 @@ var testCases = [
|
|||
"date": "2010",
|
||||
"libraryCatalog": "AustLII and NZLII",
|
||||
"publicationTitle": "Administrative Review Council - Admin Review",
|
||||
"url": "http://www9.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"url": "https://www.austlii.edu.au/cgi-bin/viewdoc/au/journals/AdminRw//2010/9.html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -368,12 +480,12 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"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",
|
||||
"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",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/sinodisp/au/cases/cth/AICmr/2017/20.html",
|
||||
"url": "http://www6.austlii.edu.au/cgi-bin/viewdoc/au/cases/cth/AICmr/2017/20.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
|
|
@ -382,7 +494,100 @@ var testCases = [
|
|||
"dateDecided": "2017-03-10",
|
||||
"court": "AICmr",
|
||||
"docketNumber": "20",
|
||||
"url": "http://www8.austlii.edu.au/cgi-bin/sinodisp/au/cases/cth/AICmr/2017/20.html",
|
||||
"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",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-06-07 16:44:19"
|
||||
"lastUpdated": "2024-06-18 20:46:45"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -41,13 +41,7 @@ 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
|
||||
|
|
@ -57,12 +51,15 @@ 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
|
||||
const authorName = getMetaTag(doc, "property", "cXenseParse:author", "content");
|
||||
let authorName = attr(doc, "meta[name='lead:author']", "content");
|
||||
if (!authorName) {
|
||||
authorName = text(doc, '.info-opinion .columnnist-name a');
|
||||
}
|
||||
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 = getMetaTag(doc, "name", "cXenseParse:recs:publishtime", "content");
|
||||
const date = attr(doc, "meta[name='lead:published_at']", "content");
|
||||
if (date) {
|
||||
item.date = date.substr(0, 10);
|
||||
}
|
||||
|
|
@ -73,7 +70,9 @@ function scrape(doc, _url) {
|
|||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
}/** BEGIN TEST CASES **/
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
|
|
@ -91,6 +90,7 @@ 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/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"url": "https://www.bangkokpost.com/life/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
|
|
@ -135,9 +135,10 @@ 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/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"url": "https://www.bangkokpost.com/life/tech/1979315/air-force-satellite-napa-1-launched",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -181,7 +182,8 @@ 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's GDP and approximately one in 10 people are employed within and around it, according to the World Travel and Tourism Council (WTTC).",
|
||||
"abstractNote": "Southeast Asia relies heavily on tourism. In 2019, the travel and tourism industry contributed 12.1% of the region",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.bangkokpost.com",
|
||||
"publicationTitle": "Bangkok Post",
|
||||
"url": "https://www.bangkokpost.com/opinion/opinion/1981587/tech-is-key-to-rebooting-tourism",
|
||||
|
|
|
|||
14
BibLaTeX.js
14
BibLaTeX.js
|
|
@ -1,13 +1,11 @@
|
|||
{
|
||||
"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": "null",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"configOptions": {
|
||||
"getCollections": true
|
||||
},
|
||||
|
|
@ -17,7 +15,9 @@
|
|||
"exportFileData": false,
|
||||
"useJournalAbbreviation": false
|
||||
},
|
||||
"lastUpdated": "2022-10-12 19:26:00"
|
||||
"inRepository": true,
|
||||
"translatorType": 2,
|
||||
"lastUpdated": "2024-03-25 14:49:42"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -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'|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'|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 citeKeyConversionsRe = /%([a-zA-Z])/;
|
||||
|
||||
var citeKeyConversions = {
|
||||
|
|
@ -882,3 +882,7 @@ function doExport() {
|
|||
|
||||
Zotero.write("\n");
|
||||
}
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
37
BibTeX.js
37
BibTeX.js
|
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"inRepository": true,
|
||||
"translatorType": 3,
|
||||
"lastUpdated": "2023-04-09 18:35:07"
|
||||
"lastUpdated": "2024-03-25 14:51:02"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1242,7 +1242,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\'|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\'|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 citeKeyConversionsRe = /%([a-zA-Z])/;
|
||||
|
||||
var citeKeyConversions = {
|
||||
|
|
@ -2896,8 +2896,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
|
||||
|
|
@ -4202,6 +4202,35 @@ var testCases = [
|
|||
"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 **/
|
||||
|
|
|
|||
|
|
@ -9,26 +9,31 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-28 15:50:57"
|
||||
"lastUpdated": "2024-01-09 03:40:58"
|
||||
}
|
||||
|
||||
/*
|
||||
* Bibliothèque nationale de France Translator
|
||||
* Copyright (C) 2010 Florian Ziche, ziche@noos.fr
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2010-2024 Florian Ziche, Sylvain Machefert
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
|
||||
/* Bnf namespace. */
|
||||
|
|
@ -472,12 +477,8 @@ var BnfClass = function () {
|
|||
for (var i = 0; i < rows.length; i++) {
|
||||
var title = "";
|
||||
var href = attr(rows[i], 'div[class="notice-synthese"] a', "href");
|
||||
try {
|
||||
title = ZU.trim(text(rows[i], 'div[class="notice-synthese"] a h2'));
|
||||
}
|
||||
catch (x) {
|
||||
title = ZU.trim(text(rows[i], 'div[class="notice-synthese"] a'));
|
||||
}
|
||||
title = ZU.trim(text(rows[i], 'div[class="notice-synthese"] a'));
|
||||
|
||||
var documentYear = text(rows[i], 'span[class="notice-ordre"]');
|
||||
if (documentYear.length == 6) {
|
||||
title += " / " + documentYear;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
{
|
||||
"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 **/
|
||||
283
Boston Review.js
283
Boston Review.js
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,496 @@
|
|||
{
|
||||
"translatorID": "b2d07a2a-c8c6-4426-ba6b-35f094a4d916",
|
||||
"label": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"creator": "Zoë C. Ma",
|
||||
"target": "^https://bosworthtoller\\.com/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-08-18 07:39:58"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Zoë C. Ma
|
||||
|
||||
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) {
|
||||
// The logic is that "a page's type is determined by its content", because
|
||||
// the current implementation of the dictionary web app may not be able to
|
||||
// sync URL correctly all the time.
|
||||
if (getSearchResults(doc, true/* checkOnly */)) {
|
||||
return "multiple";
|
||||
}
|
||||
|
||||
if (doc.querySelector("#btd--entry-single")) {
|
||||
return "dictionaryEntry";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly = false) {
|
||||
let items = {};
|
||||
let found = false;
|
||||
let rows = doc.querySelectorAll(".btd--search-entry");
|
||||
for (let row of rows) {
|
||||
// Don't retrieve the "similar entry" links
|
||||
let href = attr(row, ".btd--search-entry-header a", "href");
|
||||
let title = ZU.trimInternal(text(row, ".btd--entry-grammar").trim());
|
||||
if (!title) {
|
||||
title = text(row, ".btd--search-entry-header a"); // fallback
|
||||
}
|
||||
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) === 'multiple') {
|
||||
let items = await Z.selectItems(getSearchResults(doc));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
const BOSWORTH_TOLLER_INFO = {
|
||||
dictionaryTitle: "An Anglo-Saxon Dictionary Online",
|
||||
language: "en",
|
||||
place: "Prague",
|
||||
publisher: "Faculty of Arts, Charles University",
|
||||
date: "2014",
|
||||
creators: [
|
||||
{ firstName: "Joseph", lastName: "Bosworth", creatorType: "author" },
|
||||
{ firstName: "Thomas Northcote", lastName: "Toller", creatorType: "editor" },
|
||||
{ firstName: "Christ", lastName: "Sean", creatorType: "editor" },
|
||||
{ firstName: "Ondřej", lastName: "Tichy", creatorType: "editor" },
|
||||
],
|
||||
};
|
||||
|
||||
function scrape(doc, url = doc.location.href) {
|
||||
let item = new Z.Item("dictionaryEntry");
|
||||
|
||||
// "Constant" fields
|
||||
Object.assign(item, BOSWORTH_TOLLER_INFO);
|
||||
|
||||
// Page-specific data
|
||||
item.url = url;
|
||||
|
||||
// Word entry
|
||||
item.title = normalizeLemma(doc) || "[Unknown entry]";
|
||||
|
||||
// Original publication and page number in it, if any, as extra
|
||||
item.extra = getExtraInfo(doc);
|
||||
|
||||
// Snapshot
|
||||
item.attachments = [{
|
||||
document: doc,
|
||||
title: "Snapshot",
|
||||
mimeType: "text/html"
|
||||
}];
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
// See https://bosworthtoller.com/images-dictionary/frontback_matter.pdf
|
||||
var BOOK_ORIG_INFO = {
|
||||
b: "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth, D.D., F.R.S.\nOriginal Date: 1898\nOriginal Publisher: Oxford University Press\nOriginal Place: London",
|
||||
d: "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth; Supplement\nOriginal Date: 1921\nOriginal Publisher: Oxford University Press\nOriginal Place: London",
|
||||
};
|
||||
|
||||
// Get the extra info including original volume info and page number by parsing
|
||||
// the URL of the scanned page linked to the article. Returns a string where
|
||||
// each extra entry occupies one line in `key: value` format, or empty string
|
||||
// if the original book and page cannot be determined.
|
||||
function getExtraInfo(doc) {
|
||||
let imageURL = attr(doc, ".btd--image-pin-pan > img", "src");
|
||||
if (!imageURL) {
|
||||
return "";
|
||||
}
|
||||
// "b" for main book (1898), "d" for supplement (1912)
|
||||
let pageMatch = imageURL.match(/^\/images-dictionary\/bt_([bd])(\d+)\..+$/);
|
||||
if (!pageMatch) {
|
||||
return "";
|
||||
}
|
||||
let [, bookKey, page] = pageMatch;
|
||||
return BOOK_ORIG_INFO[bookKey] // static original publication info
|
||||
+ "\nOriginal Page: " + page.replace(/^0*/, ""); // trim leading zero
|
||||
}
|
||||
|
||||
// Normalize the lemma's vowel display-form, following the original book's
|
||||
// orthography (acute for long vowel).
|
||||
// Why is this necessary? Because the lemma prominently displayed on the page
|
||||
// main body can be configured by the user (by clicking on the icons: acute,
|
||||
// macron, and none). But we want the form used in our item data normalized, no
|
||||
// matter the display option, in order to not lose information and avoid
|
||||
// duplication.
|
||||
// NOTE that the letter case is not normalized -- the display on the page
|
||||
// corresponds to the lemma in the original book.
|
||||
function normalizeLemma(doc) {
|
||||
// The key is to apply the correct vowel length even if the user disables
|
||||
// its display. This "canonical" form (which corresponds to the original
|
||||
// form in the print book) can be found either in the metadata or in the
|
||||
// "citation" block under "entry information" in the doc, no matter the
|
||||
// citation style in use on the page.
|
||||
let titleRaw = text(doc, "#btd--entry-lemma").trim();
|
||||
let titleNormalized = removeDiacritics(titleRaw);
|
||||
|
||||
// lemma from the meta field, not normally amenable to client-side
|
||||
// modification
|
||||
let metaTitle = attr(doc, 'meta[property="og:title"]', "content").trim();
|
||||
let metaTitleNormalized = removeDiacritics(metaTitle);
|
||||
|
||||
if (metaTitle && titleNormalized === metaTitleNormalized) {
|
||||
return metaTitle;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
|
||||
// Remove the acute accent and macron if any.
|
||||
function removeDiacritics(str) {
|
||||
return str.normalize("NFD").replace(/[\u0301\u0304]/g, "");
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/search?q=heorte",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/search/advanced?q=%7B%22minFields%22%3A1,%22fields%22%3A%5B%7B%22query%22%3A%22diacon%22,%22field%22%3A%22headword%22,%22is_regex%22%3Afalse%7D,%7B%22query%22%3A%22%22,%22field%22%3A%22headword%22,%22condition%22%3A%22and%22,%22is_regex%22%3Afalse%7D%5D,%22wordclass%22%3A%7B%22include%22%3A%5B%221%22%5D,%22exclude%22%3A%5B%5D%7D,%22gender%22%3A%7B%22include%22%3A%5B%221%22%5D,%22exclude%22%3A%5B%5D%7D,%22subcategory%22%3A%7B%22include%22%3A%5B%5D,%22exclude%22%3A%5B%5D%7D,%22volume%22%3Anull%7D",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/23205",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "mucg-wyrt",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth, D.D., F.R.S.\nOriginal Date: 1898\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 700",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/23205",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/7096",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "CYN",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth, D.D., F.R.S.\nOriginal Date: 1898\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 183",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/7096",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/27305",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "secgan",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth, D.D., F.R.S.\nOriginal Date: 1898\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 855",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/27305",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/23035",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "mód-c-wánig",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth, D.D., F.R.S.\nOriginal Date: 1898\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 694",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/23035",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/53107",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "hrǽw",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth; Supplement\nOriginal Date: 1921\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 562",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/53107",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bosworthtoller.com/42878",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dictionaryEntry",
|
||||
"title": "dón",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Joseph",
|
||||
"lastName": "Bosworth",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Thomas Northcote",
|
||||
"lastName": "Toller",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Christ",
|
||||
"lastName": "Sean",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Ondřej",
|
||||
"lastName": "Tichy",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"dictionaryTitle": "An Anglo-Saxon Dictionary Online",
|
||||
"extra": "Original Dictionary Title: An Anglo-Saxon Dictionary, Based on the Manuscript Collections of the Late Joseph Bosworth; Supplement\nOriginal Date: 1921\nOriginal Publisher: Oxford University Press\nOriginal Place: London\nOriginal Page: 154",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Bosworth Toller's Anglo-Saxon Dictionary Online",
|
||||
"place": "Prague",
|
||||
"publisher": "Faculty of Arts, Charles University",
|
||||
"url": "https://bosworthtoller.com/42878",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
151
Brill.js
151
Brill.js
|
|
@ -9,13 +9,13 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-10-21 04:55:10"
|
||||
"lastUpdated": "2024-06-14 15:36:55"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2021 Abe Jellinek
|
||||
Copyright © 2024 Abe Jellinek
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
|
@ -41,15 +41,15 @@ function detectWeb(doc, url) {
|
|||
if (url.includes('/journals/')) {
|
||||
return 'journalArticle';
|
||||
}
|
||||
else if (url.includes('referenceworks.brillonline.com/entries/')) {
|
||||
return 'encyclopediaArticle';
|
||||
}
|
||||
else {
|
||||
return 'book';
|
||||
}
|
||||
}
|
||||
else if (url.includes('bibliographies.brillonline.com/entries/')
|
||||
&& doc.querySelector('#export-form')) {
|
||||
else if (url.includes('referenceworks.brill.com/display/')) {
|
||||
return 'encyclopediaArticle';
|
||||
}
|
||||
else if (url.includes('bibliographies.brill.com/items/')
|
||||
&& doc.querySelector('form.export-item')) {
|
||||
return 'journalArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
|
|
@ -62,9 +62,12 @@ function getSearchResults(doc, checkOnly) {
|
|||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('#searchContent .text-headline a, .type-article .text-headline a, .result-item .book-title a');
|
||||
if (!rows.length) {
|
||||
rows = doc.querySelectorAll('#bibliography a.item-container');
|
||||
}
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
let title = ZU.trimInternal(text(row, '.item-title span:last-child') || row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
|
|
@ -85,20 +88,11 @@ function doWeb(doc, url) {
|
|||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
if (url.includes('bibliographies.brillonline.com/entries/')) {
|
||||
scrapeBibliography(doc, url);
|
||||
if (url.includes('bibliographies.brill.com/items/')) {
|
||||
scrapeBibliography(doc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc.querySelector('body > meta')) {
|
||||
// Brill's HTML is structured incorrectly, and it causes some parsers
|
||||
// to interpret the <meta> tags as being in the body, which breaks EM.
|
||||
// We'll fix it here.
|
||||
for (let meta of doc.querySelectorAll('body > meta')) {
|
||||
doc.head.appendChild(meta);
|
||||
}
|
||||
}
|
||||
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
|
|
@ -116,15 +110,38 @@ function scrape(doc, url) {
|
|||
if (item.itemType == 'book' && item.publicationTitle) {
|
||||
delete item.publicationTitle;
|
||||
}
|
||||
|
||||
if (item.itemType == 'encyclopediaArticle' && !item.encyclopediaTitle) {
|
||||
item.encyclopediaTitle = text(doc, '.source-link a');
|
||||
}
|
||||
|
||||
if (item.abstractNote && item.abstractNote.endsWith('by Brill.')) {
|
||||
delete item.abstractNote;
|
||||
}
|
||||
|
||||
if (!item.publisher) {
|
||||
item.publisher = 'Brill';
|
||||
}
|
||||
|
||||
if (!item.creators.length) {
|
||||
// editors often don't make it into the EM
|
||||
for (let editor of doc.querySelectorAll('.content-contributor-editor a')) {
|
||||
item.creators.push(ZU.cleanAuthor(editor.textContent, 'editor'));
|
||||
let creatorNames = [];
|
||||
let creatorType = 'author';
|
||||
let line = doc.querySelector('.contributor-line');
|
||||
if (line) {
|
||||
switch (text(line, '.creator-type-label').trim()) {
|
||||
case 'Author:':
|
||||
case 'Authors:':
|
||||
creatorType = 'author';
|
||||
break;
|
||||
case 'Editor:':
|
||||
case 'Editors:':
|
||||
creatorType = 'editor';
|
||||
break;
|
||||
}
|
||||
creatorNames = line.querySelectorAll('.contributor-details .contributor-unlinked, .contributor-details .contributor-details-link');
|
||||
}
|
||||
for (let creatorName of creatorNames) {
|
||||
item.creators.push(ZU.cleanAuthor(creatorName.textContent, creatorType));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,21 +154,30 @@ function scrape(doc, url) {
|
|||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
if (url.includes('referenceworks.brillonline.com/entries/')) {
|
||||
if (url.includes('referenceworks.brill.com/display/entries/')) {
|
||||
trans.itemType = 'encyclopediaArticle';
|
||||
}
|
||||
|
||||
else if (url.includes('brill.com/edcollbook/')) {
|
||||
// Delete citation_inbook_title if this is actually a book, not a book section
|
||||
// Prevents EM from mis-detecting as a bookSection in a way that even setting
|
||||
// trans.itemType can't override
|
||||
let bookTitleMeta = doc.querySelector('meta[name="citation_inbook_title"]');
|
||||
if (bookTitleMeta) {
|
||||
bookTitleMeta.remove();
|
||||
}
|
||||
trans.itemType = 'book';
|
||||
}
|
||||
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
||||
function scrapeBibliography(doc, url) {
|
||||
function scrapeBibliography(doc) {
|
||||
let params = new URLSearchParams({
|
||||
entryId: attr(doc, 'input[name="entryId"]', 'value'),
|
||||
dest: attr(doc, 'input[name="dest"]', 'value')
|
||||
keys: attr(doc, 'input[name="keys"]', 'value'),
|
||||
}).toString();
|
||||
|
||||
ZU.doPost('/export/exportRis', params, function (ris) {
|
||||
ZU.doGet('/BSLO/export/?' + params, function (ris) {
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7"); // RIS
|
||||
translator.setString(ris);
|
||||
|
|
@ -256,7 +282,7 @@ var testCases = [
|
|||
"ISSN": "0085-2376, 1570-064x",
|
||||
"abstractNote": "Abstract The Marquis de Fénelon’s internationally popular didactic narrative, Les aventures de Télémaque, went through a remarkable number of metamorphoses in the Nahḍah, the Arab world’s cultural revival movement of the long nineteenth century. This article examines two early manuscript translations by Syrian Christian writers in the 1810s, the rhymed prose version by Rifāʿah Rāfiʿ al-Ṭahṭāwī in the 1860s; its rewriting by Shāhīn ʿAṭiyyah in 1885; and Saʿdallāh al-Bustānī’s musical drama of 1869, the basis for performances later in the century by the famous actor Salāmah Ḥijāzī. Placing Télémaque’s Arabic trajectory within its global vogue in the Enlightenment suggests ways of reading the Nahḍah between theories of world literature and ‘transnational mass-texts’, and more specific local histories of translation and literary adaptation. The ambiguity of Télémaque, its hybrid and transitional form, was important to its success in milieux facing analogous kinds of hybridity and transition—among them those of the Arab Nahḍah.",
|
||||
"issue": "3",
|
||||
"language": "en",
|
||||
"language": "eng",
|
||||
"libraryCatalog": "brill.com",
|
||||
"pages": "171-203",
|
||||
"publicationTitle": "Journal of Arabic Literature",
|
||||
|
|
@ -305,7 +331,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://brill.com/view/title/58302",
|
||||
"url": "https://brill.com/edcollbook/title/58302",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -342,7 +368,7 @@ var testCases = [
|
|||
"language": "en",
|
||||
"libraryCatalog": "brill.com",
|
||||
"publisher": "Brill",
|
||||
"url": "https://brill.com/view/title/58302",
|
||||
"url": "https://brill.com/edcollbook/title/58302",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -369,7 +395,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://referenceworks.brillonline.com/entries/encyclopaedia-iranica-online/abaev-vasilii-ivanovich-COM_362360",
|
||||
"url": "https://referenceworks.brill.com/display/entries/EIRO/COM-362360.xml",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
|
|
@ -381,12 +407,11 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-05-10",
|
||||
"encyclopediaTitle": "Encyclopaedia Iranica Online",
|
||||
"extra": "DOI: 10.1163/2330-4804_EIRO_COM_362360",
|
||||
"language": "en",
|
||||
"libraryCatalog": "referenceworks.brillonline.com",
|
||||
"publisher": "Brill",
|
||||
"url": "https://referenceworks.brillonline.com/entries/encyclopaedia-iranica-online/abaev-vasilii-ivanovich-COM_362360",
|
||||
"libraryCatalog": "referenceworks.brill.com",
|
||||
"url": "https://referenceworks.brill.com/display/entries/EIRO/COM-362360.xml",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -401,58 +426,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://referenceworks.brillonline.com/browse/encyclopaedia-iranica-online/alpha/e",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bibliographies.brillonline.com/entries/bibliography-of-slavic-linguistics/perspektive-proucavanja-alhamijado-pismenosti-projekt-transkripcije-i-transliteracije-alhamijado-tekstova-lb900000427509?s.num=0&s.f.s2_parent=s.f.book.bibliography-of-slavic-linguistics&s.keywords=%22Abjad%22",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Perspektive proučavanja alhamijado pismenosti : projekt transkripcije i transliteracije alhamijado tekstova",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Kalajdžija",
|
||||
"firstName": "Alen",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2014",
|
||||
"language": "English",
|
||||
"libraryCatalog": "Brill",
|
||||
"pages": "421-430",
|
||||
"publicationTitle": "Prilozi za orijentalnu filologiju = Contributions to Oriental Philology = Revue de Philologie Orientale",
|
||||
"shortTitle": "Perspektive proučavanja alhamijado pismenosti",
|
||||
"url": "https://bibliographies.brillonline.com/entries/bibliography-of-slavic-linguistics/perspektive-proucavanja-alhamijado-pismenosti-projekt-transkripcije-i-transliteracije-alhamijado-tekstova-lb900000427509",
|
||||
"volume": "64",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Abjad"
|
||||
},
|
||||
{
|
||||
"tag": "Script, orthography"
|
||||
},
|
||||
{
|
||||
"tag": "Serbo-Croatian (Serbian, Croatian, Bosnian)"
|
||||
},
|
||||
{
|
||||
"tag": "Transliteration"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<p>E. ab.</p>"
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://bibliographies.brillonline.com/search?s.num=0&s.f.s2_parent=s.f.book.bibliography-of-slavic-linguistics&s.keywords=%22Abjad%22",
|
||||
"url": "https://bibliographies.brill.com/BSLO/items/",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"translatorID": "6c94ba9a-8639-4f58-bea3-076f774cf3a1",
|
||||
"label": "Brukerhåndboken",
|
||||
"creator": "Sondre Bogen-Straume",
|
||||
"target": "https://brukerhandboken\\.miraheze\\.org/",
|
||||
"minVersion": "5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-06-27 16:03:43"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Sondre Bogen-Straume
|
||||
|
||||
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('/wiki/') && doc.querySelector('.printfooter a[href*="oldid="]')) {
|
||||
return 'encyclopediaArticle';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
await scrape(doc, url);
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
let translator = Zotero.loadTranslator('web');
|
||||
// Wikipedia
|
||||
translator.setTranslator('e5dc9733-f8fc-4c00-8c40-e53e0bb14664');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.encyclopediaTitle = 'Brukerhåndboken';
|
||||
item.rights = 'Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International';
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Brukermedvirkning",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "Brukermedvirkning",
|
||||
"creators": [],
|
||||
"date": "2024-05-01T08:31:53Z",
|
||||
"abstractNote": "Informasjon om brukermedvirkning her.",
|
||||
"encyclopediaTitle": "Brukerhåndboken",
|
||||
"extra": "Page Version ID: 912",
|
||||
"language": "nb",
|
||||
"libraryCatalog": "Brukerhåndboken",
|
||||
"rights": "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Brukermedvirkning?oldid=912",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Forside",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "Forside",
|
||||
"creators": [],
|
||||
"date": "2024-05-04T17:20:37Z",
|
||||
"encyclopediaTitle": "Brukerhåndboken",
|
||||
"extra": "Page Version ID: 933",
|
||||
"language": "nb",
|
||||
"libraryCatalog": "Brukerhåndboken",
|
||||
"rights": "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Forside?oldid=933",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Ord_og_forkortelser",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "Ord og forkortelser",
|
||||
"creators": [],
|
||||
"date": "2024-06-13T18:54:19Z",
|
||||
"abstractNote": "Databaseoppføring: Ord og forkortelser - For brukerrepresentanter i helsetjenesten (Q1)\nOrd og forkortelser er en ordbok for brukerrepresentanter i helsetjenesten. Den inneholder ord og forkortelser som brukes hyppig i helsevesenet, og som er som er nyttig å kunne for brukerrepresentanter i helse- og omsorgstjenesten. Innholdet er kurert fra ulike nettsider, dokumenter og liknende. Det er altså ikke jeg som har skrevet alle forklaringene. Henvisning til kildene for tekstene (hvor de er hentet fra) ble når jeg startet på listen ikke tatt med da jeg ikke planla å gjøre den offentlig. Jeg tar nå med kilde i nye oppføringer der det er relevant.\n\nListen er sortert alfabetisk og ment brukt elektronisk da det finnes lenker i tekstene.\nVed forslag til nye ord og forkortelser bruk dette skjemaet: Send inn nytt ord (Airtable) eller e-post. \nVed forslag til endringer eller du har spørsmål ta gjerne kontakt med meg på e-post.\n\nLista er sortert alfabetisk og ment brukt elektronisk da det finnes lenker i tekstene. Noen forkortelser er det brukt punktum.\nLast ned som PDF her.\n\n{{#unlinkedwikibase| id=Q1 }}\n\nOpprettet:\nMal:History-user",
|
||||
"encyclopediaTitle": "Brukerhåndboken",
|
||||
"extra": "Page Version ID: 1640",
|
||||
"language": "nb",
|
||||
"libraryCatalog": "Brukerhåndboken",
|
||||
"rights": "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International",
|
||||
"url": "https://brukerhandboken.miraheze.org/wiki/Ord_og_forkortelser?oldid=1640",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -0,0 +1,439 @@
|
|||
{
|
||||
"translatorID": "03c4b906-8cb2-4850-a771-697cbd92c2a1",
|
||||
"label": "CBC",
|
||||
"creator": "Geoff Banh",
|
||||
"target": "^https?:\\/\\/www\\.cbc\\.ca/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-03-14 20:55:10"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Geoff Banh
|
||||
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 path = new URL(url).pathname;
|
||||
if (path.includes("/search?") && getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
else if ((/(news|sports|radio|books|arts|music|life|television|archives)\//.test(path)) && getLD(doc)) {
|
||||
return "newspaperArticle";
|
||||
}
|
||||
else if (path.includes("/player/")) {
|
||||
return "videoRecording";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
// Adjust the CSS Selectors
|
||||
var rows = doc.querySelectorAll('.card.cardListing');
|
||||
for (const row of rows) {
|
||||
var href = row.href;
|
||||
var title = text(row, 'h3.headline');
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
function getLD(doc) {
|
||||
let ldScript = text(doc, "script[type='application/ld+json']");
|
||||
if (ldScript) return JSON.parse(ldScript);
|
||||
return null;
|
||||
}
|
||||
|
||||
function getMetaContent(doc, attribute, text) {
|
||||
return attr(doc.head, 'meta[' + attribute + '="' + text + '"]', 'content');
|
||||
}
|
||||
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
let translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.language = "en-CA";
|
||||
let ld = getLD(doc);
|
||||
|
||||
// only do processing if page has ld
|
||||
if (ld) {
|
||||
item.url = getMetaContent(doc, 'property', "og:url");
|
||||
|
||||
item.title = ld.headline ? ld.headline : ld.name;
|
||||
if (item.itemType == "videoRecording") {
|
||||
item.date = ZU.strToISO(ld.uploadDate);
|
||||
}
|
||||
else {
|
||||
item.date = ZU.strToISO(ld.datePublished);
|
||||
}
|
||||
item.abstractNote = ld.description;
|
||||
|
||||
item.creators = []; // clear existing authors
|
||||
// ignore organization authors
|
||||
if (ld.hasOwnProperty("author") && ld.author[0]['@type'] != "Organization") {
|
||||
// either single author or multiple comma separated in one entry
|
||||
if (ld.author.length == 1) {
|
||||
let authors = ld.author[0].name;
|
||||
if (authors.includes(',')) {
|
||||
let authorsList = authors.split(',');
|
||||
for (const a of authorsList) {
|
||||
item.creators.push(ZU.cleanAuthor(a, "author"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
item.creators.push(ZU.cleanAuthor(authors, "author"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const a of ld.author) {
|
||||
item.creators.push(ZU.cleanAuthor(a.name, "author"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let siteName = "CBC";
|
||||
if (item.itemType != "videoRecording") {
|
||||
// get department (e.g. News, Sports, Radio)
|
||||
// remove .ca/ manually, as regex lookbehind doesn't seem to work
|
||||
let dept = (/\.ca\/\w+(?=\/)/.exec(item.url))[0].replace(".ca/", "");
|
||||
// capitalize department
|
||||
dept = dept[0].toUpperCase() + dept.slice(1);
|
||||
siteName += " " + dept;
|
||||
}
|
||||
item.publicationTitle = siteName;
|
||||
item.libraryCatalog = "CBC.ca";
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
|
||||
let em = await translator.getTranslatorObject();
|
||||
em.itemType = detectWeb(doc, url);
|
||||
await em.doWeb(doc, url);
|
||||
}
|
||||
|
||||
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://www.cbc.ca/news/canada/online-groups-pressuring-youth-self-harm-1.7107885",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Violent online groups are pressuring youth into harming themselves, authorities warn",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ioanna",
|
||||
"lastName": "Roumeliotis",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Laurence",
|
||||
"lastName": "Mathieu-Leger",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Andrew",
|
||||
"lastName": "Culbert",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-02-09",
|
||||
"abstractNote": "Authorities in Canada and the U.S. are warning the public about violent online groups that deliberately target vulnerable minors and pressure them into recording or livestreaming self-harm and producing child sexual abuse material.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC News",
|
||||
"url": "https://www.cbc.ca/news/canada/online-groups-pressuring-youth-self-harm-1.7107885",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/sports/hockey/nhl/elias-pettersson-contract-extension-canucks-nhl-1.7132138",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Canucks star forward Elias Pettersson signs 8-year contract extension",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Nick",
|
||||
"lastName": "Wells",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-03-02",
|
||||
"abstractNote": "The Vancouver Canucks and star centre Elias Pettersson have agreed to an eight-year contract extension, the team announced Saturday. He is second in team scoring this season with 75 points on 29 goals and 46 assists.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC Sports",
|
||||
"url": "https://www.cbc.ca/sports/hockey/nhl/elias-pettersson-contract-extension-canucks-nhl-1.7132138",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/player/play/2313671747656",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "videoRecording",
|
||||
"title": "If you get pulled over by police this month in Regina, expect to take a breathalyzer test",
|
||||
"creators": [],
|
||||
"date": "2024-03-02",
|
||||
"abstractNote": "Everyone who gets pulled over for any reason will get a test. SGI and police are telling people about the plan because not everyone is aware of a 2018 federal law that allows it. CBC's Darla Ponace has more on what you need to know about mandatory roadside alcohol tests.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"runningTime": "82.849",
|
||||
"url": "https://www.cbc.ca/player/play/2313671747656",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/radio/thecurrent/airport-facial-recognition-biometrics-1.7130000",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Airports want to scan your face to make travelling easier. Privacy experts caution it's not ready for takeoff",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jason",
|
||||
"lastName": "Vermes",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-03-03",
|
||||
"abstractNote": "While airlines and airports say facial recognition can make air travel — an often tedious experience — more efficient and seamless, privacy advocates argue the use of biometric data is fraught and open to abuse.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC Radio",
|
||||
"url": "https://www.cbc.ca/radio/thecurrent/airport-facial-recognition-biometrics-1.7130000",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/radio/frequency",
|
||||
"detectedItemType": false,
|
||||
"items": []
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/news/politics/trudeau-meloni-pro-palestinian-protesters-toronto-1.7132378",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Trudeau's Toronto event with Italy PM Meloni cancelled due to pro-Palestinian protest",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Justin",
|
||||
"lastName": "Li",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Christian",
|
||||
"lastName": "Paas-Lang",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-03-03",
|
||||
"abstractNote": "A Toronto event where Canadian Prime Minister Justin Trudeau was scheduled to host his Italian counterpart was cancelled on Saturday due to security concerns as hundreds of pro-Palestinian protesters gathered outside the venue, a spokesperson for the Prime Minister's Office said.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC News",
|
||||
"url": "https://www.cbc.ca/news/politics/trudeau-meloni-pro-palestinian-protesters-toronto-1.7132378",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/music/canadian-reggae-songs-record-labels-1.7116717",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "Canadian reggae's past, present and future",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Kelsey",
|
||||
"lastName": "Adams",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-02-23",
|
||||
"abstractNote": "From the 1st recording on Canadian soil to the newcomers pushing the genre forward today.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC Music",
|
||||
"url": "https://www.cbc.ca/music/canadian-reggae-songs-record-labels-1.7116717",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/life/culture/the-best-card-games-to-play-with-a-standard-deck-1.5836447",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "The best card games to play with a standard deck",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sebastian",
|
||||
"lastName": "Yūe",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2020-12-10",
|
||||
"abstractNote": "This list will have you suggesting card night every chance you get!",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC Life",
|
||||
"url": "https://www.cbc.ca/life/culture/the-best-card-games-to-play-with-a-standard-deck-1.5836447",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/television/he-landed-a-sitcom-role-on-his-first-audition-i-was-really-hyped-says-scarborough-teen-1.7101522",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "newspaperArticle",
|
||||
"title": "He landed a sitcom role on his first audition. 'I was really hyped,' says Scarborough teen",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Russ",
|
||||
"lastName": "Martin",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024-02-05",
|
||||
"abstractNote": "The new CBC workplace comedy One More Time follows the manager of a second-hand sporting goods shop, DJ, played by comedian D.J. Demers, and the hijinks of his beloved gang of oddball employees. Among the motley crew is Keeran Devkar, a very green first-time associate played by 15-year-old Seran Sathiyaseelan.",
|
||||
"language": "en-CA",
|
||||
"libraryCatalog": "CBC.ca",
|
||||
"publicationTitle": "CBC Television",
|
||||
"url": "https://www.cbc.ca/television/he-landed-a-sitcom-role-on-his-first-audition-i-was-really-hyped-says-scarborough-teen-1.7101522",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cbc.ca/search?q=Windows%2011§ion=arts&sortOrder=relevance&media=all",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
{
|
||||
"translatorID": "99A6641F-A8C2-4923-9BBB-0DA87F1E5187",
|
||||
"label": "CFF References",
|
||||
"creator": "Sebastian Karcher, Dave Bunten",
|
||||
"target": "cff",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 2,
|
||||
"lastUpdated": "2024-05-17 20:02:13"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Sebastian Karcher, Dave Bunten
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
// set a global for spacing purposes under the references key of a citation.cff file
|
||||
var referencesSpacing = ' ';
|
||||
|
||||
function writeArray(array) {
|
||||
if (!array.length) return false;
|
||||
let output = "\n";
|
||||
for (let elem of array) {
|
||||
if (!elem) continue;
|
||||
output += referencesSpacing + " - " + elem + "\n";
|
||||
}
|
||||
return output.replace(/\n$/, "");
|
||||
}
|
||||
|
||||
function writeDOI(itemDOI) {
|
||||
if (!itemDOI) return false;
|
||||
let doi = "\n" + referencesSpacing + " - type: doi\n" + referencesSpacing + " value: " + itemDOI;
|
||||
return doi;
|
||||
}
|
||||
|
||||
function writeCreators(itemCreators, creatorType="") {
|
||||
let itemAuthors = [];
|
||||
for (let creator of itemCreators) {
|
||||
if (creatorType != "" && ZU.getCreatorsForType(creator.itemType)[0] == creatorType) {
|
||||
itemAuthors.push(creator);
|
||||
}
|
||||
else {
|
||||
itemAuthors.push(creator);
|
||||
}
|
||||
}
|
||||
if (!itemAuthors.length) return false;
|
||||
let authors = "\n";
|
||||
for (let author of itemAuthors) {
|
||||
authors += referencesSpacing + " - family-names: " + author.lastName + "\n";
|
||||
if (author.firstName) {
|
||||
authors += referencesSpacing + " given-names: " + author.firstName + "\n";
|
||||
}
|
||||
}
|
||||
return authors.replace(/\n$/, "");
|
||||
}
|
||||
|
||||
function doExport() {
|
||||
var item;
|
||||
|
||||
Zotero.write('# This CITATION.cff reference content was generated from Zotero.\n');
|
||||
Zotero.write('references:\n');
|
||||
|
||||
while ((item = Zotero.nextItem())) {
|
||||
var cff = {};
|
||||
cff.title = ">-\n" + referencesSpacing + " " + item.title + "\n";
|
||||
cff.abstract = item.abstractNote;
|
||||
cff.type = item.itemType;
|
||||
cff.license = item.rights;
|
||||
cff.version = item.versionNumber;
|
||||
|
||||
cff.collection_title = item.proceedingsTitle;
|
||||
cff.conference = item.conferenceName;
|
||||
cff.copyright = item.rights;
|
||||
cff.database = item.libraryCatalog;
|
||||
cff.date_accessed = item.accessDate;
|
||||
cff.edition = item.edition;
|
||||
cff.editors_series = item.series
|
||||
cff.format = item.format;
|
||||
cff.institution = item.institution;
|
||||
cff.isbn = item.ISBN;
|
||||
cff.issn = item.ISSN;
|
||||
cff.issue = item.issue;
|
||||
cff.issue_date = item.issueDate;
|
||||
cff.journal = item.journalAbbreviation;
|
||||
cff.languages = writeArray([item.language]);
|
||||
cff.location = item.archiveLocation;
|
||||
cff.medium = item.medium;
|
||||
cff.number = item.number;
|
||||
cff.number_volumes = item.numberOfVolumes;
|
||||
cff.pages = item.pages;
|
||||
// match for pmcid within extras content
|
||||
if (item.extra && /^pmcid:/i.test(item.extra)) {
|
||||
cff.pmcid = item.extra.match(/pmcid:\s*(\S+)/);
|
||||
}
|
||||
cff.publisher = item.publisher;
|
||||
cff.repository = item.repository;
|
||||
cff.section = item.section;
|
||||
cff.thesis_type = item.thesisType;
|
||||
cff.volume = item.volume;
|
||||
cff.url = item.url;
|
||||
cff.keywords = writeArray(item.tags.map(tag => tag.tag || tag));
|
||||
if (["letter", "email", "instantMessage"].includes(item.itemType)) {
|
||||
cff.senders = writeCreators(item.creators, "author");
|
||||
}
|
||||
else {
|
||||
cff.authors = writeCreators(item.creators, ZU.getCreatorsForType(item.itemType)[0]);
|
||||
}
|
||||
cff.editors = writeCreators(item.creators, "editor");
|
||||
cff.recipients = writeCreators(item.creators, "recipient");
|
||||
cff.translators = writeCreators(item.creators, "translator");
|
||||
|
||||
if (item.date) {
|
||||
// if we have a dataset or software, use date-released field
|
||||
if (item.itemType == "dataset" || item.itemType == "computerProgram") {
|
||||
cff["date-released"] = ZU.strToISO(item.date);
|
||||
}
|
||||
// include date published for any item types
|
||||
cff["date-published"] = ZU.strToISO(item.date);
|
||||
}
|
||||
// get DOI from Extra for software; this will stop running automatically once software supports DOI
|
||||
if (!ZU.fieldIsValidForType('DOI', item.itemType) && /^doi:/im.test(item.extra)) {
|
||||
item.DOI = ZU.cleanDOI(item.extra);
|
||||
}
|
||||
cff.identifiers = writeDOI(item.DOI);
|
||||
|
||||
// prep the entry as a new item
|
||||
Zotero.write(' - ');
|
||||
|
||||
// loop through the cff elements and write output
|
||||
for (let field in cff) {
|
||||
if (!cff[field]) continue;
|
||||
if (field == "title") {
|
||||
// rely on prep dash for item start above for titles
|
||||
Zotero.write(field + ": " + cff[field]);
|
||||
}
|
||||
else if (field == "abstract") {
|
||||
// multiline
|
||||
Zotero.write(referencesSpacing + field + ": |" + cff[field].replace(/^|\n/g, "\n" + referencesSpacing + " ") + "\n");
|
||||
}
|
||||
else {
|
||||
Zotero.write(referencesSpacing + field.replace("_", "-") + ": " + cff[field] + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
388
CNKI.js
388
CNKI.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-03-08 12:33:13"
|
||||
"lastUpdated": "2023-11-27 05:30:22"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -38,47 +38,35 @@
|
|||
|
||||
// Fetches RefWorks records for provided IDs and calls onDataAvailable with resulting text
|
||||
// ids should be in the form [{dbname: "CDFDLAST2013", filename: "1013102302.nh"}]
|
||||
function getRefWorksByID(ids, onDataAvailable) {
|
||||
if (!ids.length) return;
|
||||
var { dbname, filename, url } = ids.shift();
|
||||
let postData = "filename=" + filename +
|
||||
"&displaymode=Refworks&orderparam=0&ordertype=desc&selectfield=&dbname=" +
|
||||
dbname + "&random=0.2111567532240084";
|
||||
|
||||
ZU.doPost('https://kns.cnki.net/KNS8/manage/ShowExport', postData,
|
||||
function (text) {
|
||||
let data = text
|
||||
.replace("<ul class='literature-list'><li>", "")
|
||||
.replace("<br></li></ul>", "")
|
||||
.replace("</li><li>", "") // divide results
|
||||
.replace(/<br>|\r/g, "\n")
|
||||
.replace(/vo (\d+)\n/, "VO $1\n") // Divide VO and IS to different line
|
||||
.replace(/IS 0(\d+)\n/g, "IS $1\n") // Remove leading 0
|
||||
.replace(/VO 0(\d+)\n/g, "VO $1\n")
|
||||
.replace(/\n+/g, "\n")
|
||||
.replace(/\n([A-Z][A-Z1-9]\s)/g, "<br>$1")
|
||||
.replace(/\n/g, "")
|
||||
.replace(/<br>/g, "\n")
|
||||
.replace(/\t/g, "") // \t in abstract
|
||||
.replace(
|
||||
/^RT\s+Conference Proceeding/gim,
|
||||
"RT Conference Proceedings"
|
||||
)
|
||||
.replace(/^RT\s+Dissertation\/Thesis/gim, "RT Dissertation")
|
||||
.replace(/^(A[1-4]|U2)\s*([^\r\n]+)/gm, function (m, tag, authors) {
|
||||
authors = authors.split(/\s*[;,,]\s*/); // that's a special comma
|
||||
if (!authors[authors.length - 1].trim()) authors.pop();
|
||||
return tag + " " + authors.join("\n" + tag + " ");
|
||||
})
|
||||
.trim();
|
||||
// Z.debug(data);
|
||||
onDataAvailable(data, url);
|
||||
// If more results, keep going
|
||||
if (ids.length) {
|
||||
getRefWorksByID(ids, onDataAvailable);
|
||||
}
|
||||
}
|
||||
);
|
||||
function toStdRef(reftext) {
|
||||
return reftext
|
||||
.body
|
||||
.replace("<ul class='literature-list'><li>", "")
|
||||
.replace("<br></li></ul>", "")
|
||||
.replace("</li><li>", "") // divide results
|
||||
.replace(/<br>|\r/g, "\n")
|
||||
.replace(/vo (\d+)\n/, "VO $1\n") // Divide VO and IS to different line
|
||||
.replace(/IS (\d+)\nvo/, "IS $1\nVO")// Uppercase VO
|
||||
.replace(/IS 0(\d+)\n/g, "IS $1\n")// Remove leading 0
|
||||
.replace(/VO 0(\d+)\n/g, "VO $1\n")
|
||||
.replace(/\n+/g, "\n")
|
||||
.replace(/\n([A-Z][A-Z1-9]\s)/g, "<br>$1")
|
||||
.replace(/\n/g, "")
|
||||
.replace(/<br>/g, "\n")
|
||||
.replace(/(K1 .*[\u4e00-\u9fa5]) ([a-zA-Z])/g, "$1;$2")// cn keywwords and en keywords
|
||||
.replace(/\t/g, "") // \t in abstract
|
||||
.replace(
|
||||
/^RT\s+Conference Proceeding/gim,
|
||||
"RT Conference Proceedings"
|
||||
)
|
||||
.replace(/^RT\s+Dissertation\/Thesis/gim, "RT Dissertation")
|
||||
.replace(/^(A[1-4]|U2)\s*([^\r\n]+)/gm, function (m, tag, authors) {
|
||||
authors = authors.split(/\s*[;,,]\s*/); // that's a special comma
|
||||
if (!authors[authors.length - 1].trim()) authors.pop();
|
||||
return tag + " " + authors.join("\n" + tag + " ");
|
||||
})
|
||||
.replace(/LA 中文;?/g, "LA zh-CN")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function getIDFromURL(url) {
|
||||
|
|
@ -96,7 +84,12 @@ function getIDFromURL(url) {
|
|||
function getIDFromRef(doc, url) {
|
||||
let database = attr(doc, '#paramdbname', 'value');
|
||||
let filename = attr(doc, '#paramfilename', 'value');
|
||||
return { dbname: database, filename: filename, url: url };
|
||||
if (database && filename) {
|
||||
return { dbname: database, filename: filename, url: url };
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get dbname and filename from the link target on the "take note" button in
|
||||
|
|
@ -107,7 +100,7 @@ function getIDFromRef(doc, url) {
|
|||
// required info. The note-taking button appears more stable across the CNKI
|
||||
// domains.
|
||||
function getIDFromNoteTakerLink(doc, url) {
|
||||
const noteURLString = doc.querySelector("li.btn-note a").href;
|
||||
const noteURLString = attr(doc, "li.btn-note a", "href");
|
||||
if (!noteURLString) return false;
|
||||
|
||||
const urlParams = new URLSearchParams(new URL(noteURLString).search);
|
||||
|
|
@ -119,6 +112,17 @@ function getIDFromNoteTakerLink(doc, url) {
|
|||
return { dbname: dbnameValue, filename: filenameValue, url: url };
|
||||
}
|
||||
|
||||
function getIDFromSearchRow(row) {
|
||||
var dbcode = attr(row, "a.icon-collect", "data-dbname");
|
||||
var filename = attr(row, "a.icon-collect", "data-filename");
|
||||
if (dbcode && filename) {
|
||||
return { dbcode: dbcode, dbname: dbcode, filename: filename };
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getIDFromPage(doc, url) {
|
||||
return getIDFromURL(url)
|
||||
|| getIDFromRef(doc, url)
|
||||
|
|
@ -130,14 +134,21 @@ function getTypeFromDBName(dbname) {
|
|||
CJFQ: "journalArticle",
|
||||
CJFD: "journalArticle",
|
||||
CAPJ: "journalArticle",
|
||||
SJES: "journalArticle",
|
||||
SJPD: "journalArticle",
|
||||
SSJD: "journalArticle",
|
||||
CCJD: "journalArticle",
|
||||
CDMD: "journalArticle",
|
||||
CYFD: "journalArticle",
|
||||
CDFD: "thesis",
|
||||
CMFD: "thesis",
|
||||
CLKM: "thesis",
|
||||
CCND: "newspaperArticle",
|
||||
CPFD: "conferencePaper",
|
||||
IPFD: "conferencePaper",
|
||||
SCPD: "patent"
|
||||
};
|
||||
var db = dbname.substr(0, 4).toUpperCase();
|
||||
var db = dbname.substring(0, 4).toUpperCase();
|
||||
if (dbType[db]) {
|
||||
return dbType[db];
|
||||
}
|
||||
|
|
@ -161,7 +172,6 @@ function getItemsFromSearchResults(doc, url, itemInfo) {
|
|||
links = ZU.xpath(doc, '//table[@class="GridTableContent"]/tbody/tr[./td[2]/a]');
|
||||
aXpath = './td[2]/a';
|
||||
}
|
||||
|
||||
if (!links.length) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -171,7 +181,7 @@ function getItemsFromSearchResults(doc, url, itemInfo) {
|
|||
var a = ZU.xpath(links[i], aXpath)[0];
|
||||
var title = ZU.xpathText(a, './node()[not(name()="SCRIPT")]', null, '');
|
||||
if (title) title = ZU.trimInternal(title);
|
||||
var id = getIDFromURL(a.href);
|
||||
var id = getIDFromURL(a.href) || getIDFromSearchRow(links[i]);
|
||||
// pre-released item can not get ID from URL, try to get ID from element.value
|
||||
if (!id) {
|
||||
var td1 = ZU.xpath(links[i], './td')[0];
|
||||
|
|
@ -191,6 +201,10 @@ function detectWeb(doc, url) {
|
|||
// Z.debug(doc);
|
||||
var id = getIDFromPage(doc, url);
|
||||
var items = getItemsFromSearchResults(doc, url);
|
||||
var searchResult = doc.querySelector("#ModuleSearchResult");
|
||||
if (searchResult) {
|
||||
Z.monitorDOMChanges(searchResult, { childList: true, subtree: true });
|
||||
}
|
||||
if (id) {
|
||||
return getTypeFromDBName(id.dbname);
|
||||
}
|
||||
|
|
@ -202,99 +216,96 @@ function detectWeb(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var itemInfo = {};
|
||||
var items = getItemsFromSearchResults(doc, url, itemInfo);
|
||||
Z.selectItems(items, function (selectedItems) {
|
||||
if (!selectedItems) return;
|
||||
|
||||
var itemInfoByTitle = {};
|
||||
var ids = [];
|
||||
for (var url in selectedItems) {
|
||||
ids.push(itemInfo[url].id);
|
||||
itemInfoByTitle[selectedItems[url]] = itemInfo[url];
|
||||
itemInfoByTitle[selectedItems[url]].url = url;
|
||||
let selectItems = await Z.selectItems(items);
|
||||
if (selectItems) {
|
||||
for (let url in selectItems) {
|
||||
await scrape(itemInfo[url].id, doc, { url: url });
|
||||
}
|
||||
scrape(ids, doc, url, itemInfoByTitle);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
scrape([getIDFromPage(doc, url)], doc, url);
|
||||
await scrape(getIDFromPage(doc, url), doc);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(ids, doc, url, itemInfo) {
|
||||
getRefWorksByID(ids, function (text) {
|
||||
var translator = Z.loadTranslator('import');
|
||||
translator.setTranslator('1a3506da-a303-4b0a-a1cd-f216e6138d86'); // RefWorks Tagged
|
||||
text = text.replace(/IS (\d+)\nvo/, "IS $1\nVO");
|
||||
translator.setString(text);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, newItem) {
|
||||
// split names
|
||||
for (var i = 0, n = newItem.creators.length; i < n; i++) {
|
||||
var creator = newItem.creators[i];
|
||||
if (creator.firstName) continue;
|
||||
|
||||
var lastSpace = creator.lastName.lastIndexOf(' ');
|
||||
var lastMiddleDot = creator.lastName.lastIndexOf('·');
|
||||
if (creator.lastName.search(/[A-Za-z]/) !== -1 && lastSpace !== -1) {
|
||||
// western name. split on last space
|
||||
creator.firstName = creator.lastName.substr(0, lastSpace);
|
||||
creator.lastName = creator.lastName.substr(lastSpace + 1);
|
||||
}
|
||||
else if (lastMiddleDot !== -1) {
|
||||
// translated western name with · as separator
|
||||
creator.firstName = creator.lastName.substr(0, lastMiddleDot);
|
||||
creator.lastName = creator.lastName.substr(lastMiddleDot + 1);
|
||||
}
|
||||
else {
|
||||
// Chinese name. first character is last name, the rest are first name
|
||||
creator.firstName = creator.lastName.substr(1);
|
||||
creator.lastName = creator.lastName.charAt(0);
|
||||
}
|
||||
async function scrape(id, doc, extraData) {
|
||||
var { dbname, filename } = id;
|
||||
var postData = `FileName=${dbname}!${filename}!1!0&DisplayMode=Refworks&OrderParam=0&OrderType=desc&SelectField=&PageIndex=1&PageSize=20&language=&uniplatform=NZKPT&random=0.30585230060685187`;
|
||||
var refer = `https://kns.cnki.net/dm/manage/export.html?filename=${dbname}!${filename}!1!0&displaymode=NEW&uniplatform=NZKPT`;
|
||||
var reftext = await request(
|
||||
'https://kns.cnki.net/dm/api/ShowExport',
|
||||
{
|
||||
method: "POST",
|
||||
body: postData,
|
||||
headers: {
|
||||
Referer: refer
|
||||
}
|
||||
}
|
||||
);
|
||||
var translator = Z.loadTranslator('import');
|
||||
translator.setTranslator('1a3506da-a303-4b0a-a1cd-f216e6138d86'); // RefWorks Tagged
|
||||
translator.setString(toStdRef(reftext));
|
||||
|
||||
translator.setHandler('itemDone', function (obj, newItem) {
|
||||
// split names
|
||||
for (var i = 0, n = newItem.creators.length; i < n; i++) {
|
||||
var creator = newItem.creators[i];
|
||||
if (creator.firstName) continue;
|
||||
|
||||
if (newItem.abstractNote) {
|
||||
newItem.abstractNote = newItem.abstractNote.replace(/\s*[\r\n]\s*/g, '\n');
|
||||
var lastSpace = creator.lastName.lastIndexOf(' ');
|
||||
var lastMiddleDot = creator.lastName.lastIndexOf('·');
|
||||
if (/[A-Za-z]/.test(creator.lastName) && lastSpace !== -1) {
|
||||
// western name. split on last space
|
||||
creator.firstName = creator.lastName.substring(0, lastSpace);
|
||||
creator.lastName = creator.lastName.substring(lastSpace + 1);
|
||||
}
|
||||
|
||||
// clean up tags. Remove numbers from end
|
||||
for (var j = 0, l = newItem.tags.length; j < l; j++) {
|
||||
newItem.tags[j] = newItem.tags[j].replace(/:\d+$/, '');
|
||||
}
|
||||
|
||||
newItem.title = ZU.trimInternal(newItem.title);
|
||||
if (itemInfo) {
|
||||
var info = itemInfo[newItem.title];
|
||||
if (!info) {
|
||||
Z.debug('No item info for "' + newItem.title + '"');
|
||||
}
|
||||
else {
|
||||
newItem.url = info.url;
|
||||
}
|
||||
else if (lastMiddleDot !== -1) {
|
||||
// translated western name with · as separator
|
||||
creator.firstName = creator.lastName.substring(0, lastMiddleDot);
|
||||
creator.lastName = creator.lastName.substring(lastMiddleDot + 1);
|
||||
}
|
||||
else {
|
||||
newItem.url = url;
|
||||
// Chinese name. first character is last name, the rest are first name
|
||||
creator.firstName = creator.lastName.substring(1);
|
||||
creator.lastName = creator.lastName.charAt(0);
|
||||
}
|
||||
|
||||
// CN 中国刊物编号,非refworks中的callNumber
|
||||
// CN in CNKI refworks format explains Chinese version of ISSN
|
||||
if (newItem.callNumber) {
|
||||
// newItem.extra = 'CN ' + newItem.callNumber;
|
||||
newItem.callNumber = "";
|
||||
}
|
||||
// don't download PDF/CAJ on searchResult(multiple)
|
||||
var webType = detectWeb(doc, url);
|
||||
if (webType && webType != 'multiple') {
|
||||
newItem.attachments = getAttachments(doc, newItem);
|
||||
}
|
||||
newItem.complete();
|
||||
});
|
||||
}
|
||||
|
||||
translator.translate();
|
||||
if (newItem.abstractNote) {
|
||||
newItem.abstractNote = newItem.abstractNote.replace(/\s*[\r\n]\s*/g, '\n');
|
||||
}
|
||||
|
||||
// clean up tags. Remove numbers from end
|
||||
for (var j = 0, l = newItem.tags.length; j < l; j++) {
|
||||
newItem.tags[j] = newItem.tags[j].replace(/:\d+$/, '');
|
||||
}
|
||||
|
||||
newItem.title = ZU.trimInternal(newItem.title);
|
||||
if (extraData) {
|
||||
newItem.url = extraData.url;
|
||||
}
|
||||
else {
|
||||
newItem.url = id.url;
|
||||
}
|
||||
|
||||
// CN 中国刊物编号,非refworks中的callNumber
|
||||
// CN in CNKI refworks format explains Chinese version of ISSN
|
||||
if (newItem.callNumber) {
|
||||
// newItem.extra = 'CN ' + newItem.callNumber;
|
||||
newItem.callNumber = "";
|
||||
}
|
||||
// don't download PDF/CAJ on searchResult(multiple)
|
||||
var webType = detectWeb(doc, id.url);
|
||||
if (webType && webType != 'multiple') {
|
||||
newItem.attachments = getAttachments(doc, newItem);
|
||||
}
|
||||
newItem.complete();
|
||||
});
|
||||
translator.translate();
|
||||
}
|
||||
|
||||
// get pdf download link
|
||||
|
|
@ -351,6 +362,7 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2015&filename=SPZZ201412003&v=MTU2MzMzcVRyV00xRnJDVVJMS2ZidVptRmkva1ZiL09OajNSZExHNEg5WE5yWTlGWjRSOGVYMUx1eFlTN0RoMVQ=",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -391,29 +403,19 @@ var testCases = [
|
|||
"ISSN": "1000-8713",
|
||||
"abstractNote": "来自中药的水溶性多糖具有广谱治疗和低毒性特点,是天然药物及保健品研发中的重要组成部分。针对中药多糖结构复杂、难以表征的问题,本文以中药黄芪中的多糖为研究对象,采用\"自下而上\"法完成对黄芪多糖的表征。首先使用部分酸水解方法水解黄芪多糖,分别考察了水解时间、酸浓度和温度的影响。在适宜条件(4 h、1.5mol/L三氟乙酸、80℃)下,黄芪多糖被水解为特征性的寡糖片段。接下来,采用亲水作用色谱与质谱联用对黄芪多糖部分酸水解产物进行分离和结构表征。结果表明,提取得到的黄芪多糖主要为1→4连接线性葡聚糖,水解得到聚合度4~11的葡寡糖。本研究对其他中药多糖的表征具有一定的示范作用。",
|
||||
"issue": "12",
|
||||
"language": "中文;",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"pages": "1306-1312",
|
||||
"publicationTitle": "色谱",
|
||||
"url": "https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFDLAST2015&filename=SPZZ201412003&v=MTU2MzMzcVRyV00xRnJDVVJMS2ZidVptRmkva1ZiL09OajNSZExHNEg5WE5yWTlGWjRSOGVYMUx1eFlTN0RoMVQ=",
|
||||
"volume": "32",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Astragalus"
|
||||
},
|
||||
{
|
||||
"tag": "characterization"
|
||||
},
|
||||
{
|
||||
"tag": "hydrophilic interaction liquid chromatography(HILIC)mass spectrometry(MS)"
|
||||
},
|
||||
{
|
||||
"tag": "partial acid hydrolysis"
|
||||
},
|
||||
{
|
||||
"tag": "polysaccharides"
|
||||
},
|
||||
{
|
||||
"tag": "亲水作用色谱"
|
||||
},
|
||||
|
|
@ -441,6 +443,7 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CMFD&dbname=CMFD201701&filename=1017045605.nh&v=MDc3ODZPZVorVnZGQ3ZrV3JyT1ZGMjZHYk84RzlmTXFwRWJQSVI4ZVgxTHV4WVM3RGgxVDNxVHJXTTFGckNVUkw=",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "thesis",
|
||||
|
|
@ -452,27 +455,15 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015",
|
||||
"abstractNote": "黄瓜(Cucumis sativus L.)是我国最大的保护地栽培蔬菜作物,也是植物性别发育和维管束运输研究的重要模式植物。黄瓜基因组序列图谱已经构建完成,并且在此基础上又完成了全基因组SSR标记开发和涵盖330万个变异位点变异组图谱,成为黄瓜功能基因研究的重要平台和工具,相关转录组研究也有很多报道,不过共表达网络研究还是空白。本实验以温室型黄瓜9930为研究对象,选取10个不同组织,进行转录组测序,获得10份转录组原始数据。在对原始数据去除接头与低质量读段后,将高质量读段用Tophat2回贴到已经发表的栽培黄瓜基因组序列上。用Cufflinks对回贴后的数据计算FPKM值,获得10份组织的2...",
|
||||
"language": "中文;",
|
||||
"date": "2017",
|
||||
"abstractNote": "黄瓜(Cucumis sativus L.)是我国最大的保护地栽培蔬菜作物,也是植物性别发育和维管束运输研究的重要模式植物。黄瓜基因组序列图谱已经构建完成,并且在此基础上又完成了全基因组SSR标记开发和涵盖330万个变异位点变异组图谱,成为黄瓜功能基因研究的重要平台和工具,相关转录组研究也有很多报道,不过共表达网络研究还是空白。本实验以温室型黄瓜9930为研究对象,选取10个不同组织,进行转录组测序,获得10份转录组原始数据。在对原始数据去除接头与低质量读段后,将高质量读段用Tophat2回贴到已经发表的栽培黄瓜基因组序列上。用Cufflinks对回贴后的数据计算FPKM值,获得10份组织的24274基因的表达量数据。计算结果中的回贴率比较理想,不过有些基因的表达量过低。为了防止表达量低的基因对结果的影响,将10份组织中表达量最大小于5的基因去除,得到16924个基因,进行下一步分析。共表达网络的构建过程是将上步获得的表达量数据,利用R语言中WGCNA(weighted gene co-expression network analysis)包构建共表达网络。结果得到的共表达网络包括1134个模块。这些模块中的基因表达模式类似,可以认为是共表达关系。不过结果中一些模块内基因间相关性同其他模块相比比较低,在分析过程中,将模块中基因相关性平均值低于0.9的模块都去除,最终得到839个模块,一共11,844个基因。共表达的基因因其表达模式类似而聚在一起,这些基因可能与10份组织存在特异性关联。为了计算模块与组织间的相关性,首先要对每个模块进行主成分分析(principle component analysis,PCA),获得特征基因(module eigengene,ME),特征基因可以表示这个模块所有基因共有的表达趋势。通过计算特征基因与组织间的相关性,从而挑选出组织特异性模块,这些模块一共有323个。利用topGO功能富集分析的结果表明这些特异性模块所富集的功能与组织相关。共表达基因在染色体上的物理位置经常是成簇分布的。按照基因间隔小于25kb为标准。分别对839个模块进行分析,结果发现在71个模块中共有220个cluster,这些cluster 一般有2~5个基因,cluster中的基因在功能上也表现出一定的联系。共表达基因可能受到相同的转录调控,这些基因在启动子前2kb可能会存在有相同的motif以供反式作用元...",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"thesisType": "硕士",
|
||||
"university": "南京农业大学",
|
||||
"url": "https://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CMFD&dbname=CMFD201701&filename=1017045605.nh&v=MDc3ODZPZVorVnZGQ3ZrV3JyT1ZGMjZHYk84RzlmTXFwRWJQSVI4ZVgxTHV4WVM3RGgxVDNxVHJXTTFGckNVUkw=",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "co-expression"
|
||||
},
|
||||
{
|
||||
"tag": "cucumber"
|
||||
},
|
||||
{
|
||||
"tag": "network"
|
||||
},
|
||||
{
|
||||
"tag": "transcriptome"
|
||||
},
|
||||
{
|
||||
"tag": "共表达"
|
||||
},
|
||||
|
|
@ -494,6 +485,7 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CCJD&dbname=CCJDLAST2&filename=ZKSF202002010&uniplatform=NZKPT&v=RM9dl7WiC7a9v7FVB6ov3OwJSXCWzsWIng_BWXok2rj4YFWz9tZ20FRZxDaeDPCm",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -511,16 +503,21 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2020",
|
||||
"abstractNote": "<正>一、简介近来再次对俄罗斯(1993)和西班牙(1995)陪审团审判模式进行介绍的原因有两个方面。第一,在废除传统陪审团审判的情况下,要么采取仅由职业法官组成的法院审理案件,要么由职业法官和审讯顾问合议来判断所有的事实问题、法律问题并作出相应判决,这是一种令人惊闻的倒退。",
|
||||
"issue": "02",
|
||||
"language": "中文;",
|
||||
"abstractNote": "<正>一、简介近来再次对俄罗斯(1993)和西班牙(1995)陪审团审判模式进行介绍的原因有两个方面。第一,在废除传统陪审团审判的情况下,要么采取仅由职业法官组成的法院审理案件,要么由职业法官和审讯顾问合议来判断所有的事实问题、法律问题并作出相应判决,这是一种令人惊闻的倒退。",
|
||||
"issue": "2",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"pages": "193-212",
|
||||
"publicationTitle": "司法智库",
|
||||
"shortTitle": "欧洲陪审团制度新发展",
|
||||
"url": "https://kns.cnki.net/kcms/detail/detail.aspx?dbcode=CCJD&dbname=CCJDLAST2&filename=ZKSF202002010&uniplatform=NZKPT&v=RM9dl7WiC7a9v7FVB6ov3OwJSXCWzsWIng_BWXok2rj4YFWz9tZ20FRZxDaeDPCm",
|
||||
"volume": "3",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "俄罗斯"
|
||||
|
|
@ -545,7 +542,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=3uoqIhG8C44YLTlOAiTRKibYlV5Vjs7ioT0BO4yQ4m_mOgeS2ml3UHGnAz_wirMwf-b2NsjH_IkCCqUvvwsK8DOvNyxMAxbu&uniplatform=NZKPT",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcAi0XeGEjt5HeH9QvBBKaMwsES4SuFJjIdiexE2qhU8bX2aGBIHriUe6WrMOFyCz6TIuYJGlA_YQUO9h2FJwGt_gZfkHkLHnqVgNK8uMWo5lKYMqxvBPfO6_0Zy21140lIwEFrUw-cJtw==&uniplatform=NZKPT",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -559,31 +557,21 @@ var testCases = [
|
|||
],
|
||||
"date": "2022",
|
||||
"ISSN": "1001-2397",
|
||||
"abstractNote": "我国绿色产品认证标识制度框架已初步形成。作为一项法律制度,绿色产品标识及认证中形成了两组法律关系:一是就产品认可认证,在行政主体、认证机构与申请人之间构成公私混合的规制关系;二是就绿色产品标识授权使用,在上述法律关系主体间构成的商业许可关系。两组法律关系的搭建,形成了我国绿色产品认证标识制度的基本格局。制度的具体完善路径是将现行同类环保产品认证标识纳入绿色产品标识与绿色属性产品标识的二元框架内,或吸收,或拆解,或由市场逐步淘汰,最终形成统一的绿色产品认证标识体系。在制度构建过程中,对第三方认证机构的规制成为制度有效运行的关键。参考域外经验,我国应当通过强化认证机构的独立性,平衡认证机构与申请人...",
|
||||
"issue": "06",
|
||||
"language": "中文;",
|
||||
"abstractNote": "我国绿色产品认证标识制度框架已初步形成。作为一项法律制度,绿色产品标识及认证中形成了两组法律关系:一是就产品认可认证,在行政主体、认证机构与申请人之间构成公私混合的规制关系;二是就绿色产品标识授权使用,在上述法律关系主体间构成的商业许可关系。两组法律关系的搭建,形成了我国绿色产品认证标识制度的基本格局。制度的具体完善路径是将现行同类环保产品认证标识纳入绿色产品标识与绿色属性产品标识的二元框架内,或吸收,或拆解,或由市场逐步淘汰,最终形成统一的绿色产品认证标识体系。在制度构建过程中,对第三方认证机构的规制成为制度有效运行的关键。参考域外经验,我国应当通过强化认证机构的独立性,平衡认证机构与申请人之间的制约关系,以及通过加强行政监管与社会监督,防止认证权力寻租,充分发挥绿色产品认证标识制度的实践效果。",
|
||||
"issue": "6",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"pages": "133-145",
|
||||
"publicationTitle": "现代法学",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=3uoqIhG8C44YLTlOAiTRKibYlV5Vjs7ioT0BO4yQ4m_mOgeS2ml3UHGnAz_wirMwf-b2NsjH_IkCCqUvvwsK8DOvNyxMAxbu&uniplatform=NZKPT",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcAi0XeGEjt5HeH9QvBBKaMwsES4SuFJjIdiexE2qhU8bX2aGBIHriUe6WrMOFyCz6TIuYJGlA_YQUO9h2FJwGt_gZfkHkLHnqVgNK8uMWo5lKYMqxvBPfO6_0Zy21140lIwEFrUw-cJtw==&uniplatform=NZKPT",
|
||||
"volume": "44",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "certification trade mark"
|
||||
},
|
||||
{
|
||||
"tag": "green product certification"
|
||||
},
|
||||
{
|
||||
"tag": "green product identification"
|
||||
},
|
||||
{
|
||||
"tag": "green products"
|
||||
},
|
||||
{
|
||||
"tag": "third party certification"
|
||||
},
|
||||
{
|
||||
"tag": "第三方认证"
|
||||
},
|
||||
|
|
@ -607,7 +595,8 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=ARuSRxW-FQHH_OEY6X72RuJIsrP2RHAQAacVbC9CGuvOv08ETIP-MqQO5E296beGN9e8BXVfYGR6l0qfpFxS9gdAPZ5URHqiAY8WVPwSYoF6MXeqOgFQfX5vrMMS_wZaK3j5TPxvx-nDGPfIMtrXBlDrWr9SVlAl&uniplatform=NZKPT",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcCQMiRSLWzbqHFLmF0YiAvOI33I1RqvSIDdZeLKl7q3QL7ioYjCbxuMHo1CSBSG2LYUjI9r30yPonoox-iGbCfgn-YF7W2h79KqPswOTOxrzPV94p2evWa1-zchF2wLCag2WcjSEGNUdSNYdPlVmcGt&uniplatform=NZKPT",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -621,15 +610,20 @@ var testCases = [
|
|||
],
|
||||
"date": "2022",
|
||||
"ISSN": "1671-7287",
|
||||
"abstractNote": "我国对常规污染物的治理取得了显著成效,但以有毒有害化学物质的生产和使用为主要来源的新污染物的环境风险仍然较为严峻。当前我国相关环境法律法规和标准中缺乏对新污染物环境风险管控的要求,对于现有化学物质的环境风险管控还存在较为严重的不足。未来环境法典中新污染物环境风险管控立法应当坚持风险预防原则,但风险预防原则并不以追求“零风险”为目标。新污染物环境风险管控立法总体上应当遵循“风险筛查→风险评估→风险管控”的思路。环境风险评估应当聚焦于从科学角度评估新污染物对公众健康和生态环境带来的“风险”本身,不考虑与环境风险无关的经济、社会等因素。确定什么是“不合理的风险”,除了科学判断之外,也需要“正当程序”...",
|
||||
"issue": "05",
|
||||
"language": "中文;",
|
||||
"abstractNote": "我国对常规污染物的治理取得了显著成效,但以有毒有害化学物质的生产和使用为主要来源的新污染物的环境风险仍然较为严峻。当前我国相关环境法律法规和标准中缺乏对新污染物环境风险管控的要求,对于现有化学物质的环境风险管控还存在较为严重的不足。未来环境法典中新污染物环境风险管控立法应当坚持风险预防原则,但风险预防原则并不以追求“零风险”为目标。新污染物环境风险管控立法总体上应当遵循“风险筛查→风险评估→风险管控”的思路。环境风险评估应当聚焦于从科学角度评估新污染物对公众健康和生态环境带来的“风险”本身,不考虑与环境风险无关的经济、社会等因素。确定什么是“不合理的风险”,除了科学判断之外,也需要“正当程序”的加持。风险无法确定时,比照“存在不合理风险”进行管控。在选择风险管控措施时,应当考虑新污染物对公众健康和生态环境的影响程度以及经济、社会等因素。对于新化学物质,应当秉承“除非能证明无害,否则都应当进行适当风险管控”的理念。",
|
||||
"issue": "5",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"pages": "18-30+115",
|
||||
"publicationTitle": "南京工业大学学报(社会科学版)",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=ARuSRxW-FQHH_OEY6X72RuJIsrP2RHAQAacVbC9CGuvOv08ETIP-MqQO5E296beGN9e8BXVfYGR6l0qfpFxS9gdAPZ5URHqiAY8WVPwSYoF6MXeqOgFQfX5vrMMS_wZaK3j5TPxvx-nDGPfIMtrXBlDrWr9SVlAl&uniplatform=NZKPT",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcCQMiRSLWzbqHFLmF0YiAvOI33I1RqvSIDdZeLKl7q3QL7ioYjCbxuMHo1CSBSG2LYUjI9r30yPonoox-iGbCfgn-YF7W2h79KqPswOTOxrzPV94p2evWa1-zchF2wLCag2WcjSEGNUdSNYdPlVmcGt&uniplatform=NZKPT",
|
||||
"volume": "21",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "新污染物风险管控"
|
||||
|
|
@ -654,11 +648,12 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://kns.cnki.net/kcms/detail/detail.aspx?doi=10.13863/j.issn1001-4454.2022.01.030",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcBuyOSvEQLm_QauzuszuNvOETrZkPfTUVjXy6wyG6-n2nHmyA70y6TC3IN6i68HMAN2clvthsV7F1ypcjao4RepuYmOZSEVhLK8lN1UAkOxmQkqtJdHoHI1N1gKQDPjuaEbdR6APIJ1sA==&uniplatform=NZKPT&language=CHS",
|
||||
"defer": true,
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Box-Behnken Design-响应面法优化碱水解人参茎叶三醇皂苷制备人参皂苷Rg_2工艺研究",
|
||||
"title": "Box-Behnken Design-响应面法优化碱水解人参茎叶三醇皂苷制备人参皂苷Rg2工艺研究",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "史",
|
||||
|
|
@ -699,21 +694,26 @@ var testCases = [
|
|||
"date": "2022",
|
||||
"DOI": "10.13863/j.issn1001-4454.2022.01.030",
|
||||
"ISSN": "1001-4454",
|
||||
"abstractNote": "目的:利用Box-Behnken Design-响应面法优选制备人参皂苷Rg_2的最佳工艺参数。方法:以碱解反应的碱度、温度、时间作为考察因素,人参茎叶三醇皂苷中人参皂苷Rg_2含量作为评价指标,运用Design-Expert 8.0.5b软件对工艺参数进行优化并获得最佳工艺参数。结果:经优化得到碱水解人参茎叶三醇皂苷制备人参皂苷Rg_2的最佳工艺参数:反应碱度7.4%、反应温度187℃、反应时间5 h。验证试验表明,在此工艺参数下可将人参皂苷Rg_2含量提高至9.84%,且工艺稳定。结论:经过优化的工艺可有效提高人参茎叶三醇皂苷中人参皂苷Rg_2含量。",
|
||||
"issue": "01",
|
||||
"language": "中文;",
|
||||
"abstractNote": "目的:利用Box-Behnken Design-响应面法优选制备人参皂苷Rg<sub>2</sub>的最佳工艺参数。方法:以碱解反应的碱度、温度、时间作为考察因素,人参茎叶三醇皂苷中人参皂苷Rg<sub>2</sub>含量作为评价指标,运用Design-Expert 8.0.5b软件对工艺参数进行优化并获得最佳工艺参数。结果:经优化得到碱水解人参茎叶三醇皂苷制备人参皂苷Rg<sub>2</sub>的最佳工艺参数:反应碱度7.4%、反应温度187℃、反应时间5 h。验证试验表明,在此工艺参数下可将人参皂苷Rg<sub>2</sub>含量提高至9.84%,且工艺稳定。结论:经过优化的工艺可有效提高人参茎叶三醇皂苷中人参皂苷Rg<sub>2</sub>含量。",
|
||||
"issue": "1",
|
||||
"language": "zh-CN",
|
||||
"libraryCatalog": "CNKI",
|
||||
"pages": "173-176",
|
||||
"publicationTitle": "中药材",
|
||||
"url": "https://kns.cnki.net/kcms/detail/detail.aspx?doi=10.13863/j.issn1001-4454.2022.01.030",
|
||||
"url": "https://kns.cnki.net/kcms2/article/abstract?v=aGn3Ey0ZxcBuyOSvEQLm_QauzuszuNvOETrZkPfTUVjXy6wyG6-n2nHmyA70y6TC3IN6i68HMAN2clvthsV7F1ypcjao4RepuYmOZSEVhLK8lN1UAkOxmQkqtJdHoHI1N1gKQDPjuaEbdR6APIJ1sA==&uniplatform=NZKPT&language=CHS",
|
||||
"volume": "45",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Box-Behnken Design-响应面法"
|
||||
},
|
||||
{
|
||||
"tag": "人参皂苷Rg_2"
|
||||
"tag": "人参皂苷Rg2"
|
||||
},
|
||||
{
|
||||
"tag": "人参茎叶三醇皂苷"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-05-31 18:42:02"
|
||||
"lastUpdated": "2023-10-23 08:08:57"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -80,11 +80,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
async function doWeb(doc, url) {
|
||||
if (await detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (items) {
|
||||
await Promise.all(
|
||||
Object.keys(items)
|
||||
.map(url => requestDocument(url).then(scrape))
|
||||
);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -125,7 +123,7 @@ async function scrape(doc) {
|
|||
|
||||
if (pdfLink) {
|
||||
item.attachments.push({
|
||||
url: pdfLink.href,
|
||||
url: pdfLink,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,842 @@
|
|||
{
|
||||
"translatorID": "cdb5c893-ab69-4e96-9b5c-f4456d49ddd8",
|
||||
"label": "Câmara Brasileira do Livro ISBN",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 98,
|
||||
"inRepository": true,
|
||||
"translatorType": 8,
|
||||
"lastUpdated": "2023-09-26 16:11:18"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 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 detectSearch(items) {
|
||||
items = cleanData(items);
|
||||
return !!items.length;
|
||||
}
|
||||
|
||||
async function doSearch(items) {
|
||||
items = cleanData(items);
|
||||
for (let { ISBN } of items) {
|
||||
let search = ISBN;
|
||||
if (ISBN.length == 10) {
|
||||
search += ' OR ' + ZU.toISBN13(ISBN);
|
||||
}
|
||||
let body = {
|
||||
count: true,
|
||||
facets: [],
|
||||
filter: '',
|
||||
orderby: null,
|
||||
queryType: 'full',
|
||||
search,
|
||||
searchFields: 'FormattedKey,RowKey',
|
||||
searchMode: 'any',
|
||||
select: '*',
|
||||
skip: 0,
|
||||
top: 1
|
||||
};
|
||||
let response = await requestJSON('https://isbn-search-br.search.windows.net/indexes/isbn-index/docs/search?api-version=2016-09-01', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
'api-key': '100216A23C5AEE390338BBD19EA86D29',
|
||||
Origin: 'https://www.cblservicos.org.br',
|
||||
Referer: 'https://www.cblservicos.org.br/'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
let results = response.value;
|
||||
for (let result of results) {
|
||||
translateResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function translateResult(result) {
|
||||
Z.debug(result)
|
||||
let item = new Zotero.Item('book');
|
||||
item.title = result.Title;
|
||||
if (result.Subtitle && !item.title.includes(':') && !result.Subtitle.includes(':')) {
|
||||
item.title += ': ' + result.Subtitle;
|
||||
}
|
||||
item.title = fixCase(item.title);
|
||||
item.abstractNote = result.Sinopse;
|
||||
item.series = fixCase(result.Colection);
|
||||
// TODO: Need example data for:
|
||||
// item.seriesNumber
|
||||
// item.volume
|
||||
// item.numberOfVolumes
|
||||
item.edition = result.Edicao;
|
||||
if (item.edition == '1') {
|
||||
item.edition = '';
|
||||
}
|
||||
item.place = (result.Cidade || '') + (result.UF ? ', ' + result.UF : '');
|
||||
item.publisher = fixCase(result.Imprint);
|
||||
item.date = ZU.strToISO(result.Date);
|
||||
item.numPages = result.Paginas;
|
||||
if (item.numPages == '0') {
|
||||
item.numPages = '';
|
||||
}
|
||||
item.language = (result.IdiomasObra && result.IdiomasObra[0]) || 'pt-BR';
|
||||
if (item.language == 'português (Brasil)') {
|
||||
item.language = 'pt-BR';
|
||||
}
|
||||
item.ISBN = ZU.cleanISBN(result.FormattedKey);
|
||||
for (let [i, author] of result.Authors.entries()) {
|
||||
if (author == author.toUpperCase()) {
|
||||
author = ZU.capitalizeName(author);
|
||||
}
|
||||
let creatorType;
|
||||
if (result.Profissoes && result.Profissoes.length === result.Authors.length) {
|
||||
switch (result.Profissoes[i]) {
|
||||
case 'Coordenador':
|
||||
case 'Autor':
|
||||
case 'Roteirista':
|
||||
creatorType = 'author';
|
||||
break;
|
||||
case 'Revisor':
|
||||
case 'Organizador':
|
||||
case 'Editor':
|
||||
creatorType = 'editor';
|
||||
break;
|
||||
case 'Tradutor':
|
||||
creatorType = 'translator';
|
||||
break;
|
||||
case 'Ilustrador': // TODO: Used?
|
||||
case 'Projeto Gráfico':
|
||||
creatorType = 'illustrator';
|
||||
break;
|
||||
default:
|
||||
// First creator is probably an author,
|
||||
// even if the Profissoes string is something weird
|
||||
creatorType = i == 0 ? 'author' : 'contributor';
|
||||
break;
|
||||
}
|
||||
}
|
||||
// No/mismatched-length Profissoes array, so we have to guess that this non-primary creator
|
||||
// is a contributor
|
||||
else if (i > 0) {
|
||||
creatorType = 'contributor';
|
||||
}
|
||||
// No/mismatched-length Profissoes array, so we have to guess that this primary creator
|
||||
// is an author
|
||||
else {
|
||||
creatorType = 'author';
|
||||
}
|
||||
// Brazilian names often contain many surnames, but determining which names are surnames
|
||||
// and which are given names is outside the scope of this translator.
|
||||
// Chicago indexes by the final element of the name alone, and so will we:
|
||||
// https://en.wikipedia.org/wiki/Portuguese_name#Indexing
|
||||
let creator = ZU.cleanAuthor(author, creatorType, author.includes(','));
|
||||
if (!creator.firstName) creator.fieldMode = 1;
|
||||
|
||||
// That said, we will handle name suffixes, which should be combined with the last "middle"
|
||||
// name particle in the last name
|
||||
if (creator.firstName && creator.lastName
|
||||
&& ['filho', 'junior', 'neto', 'sobrinho', 'segundo', 'terceiro']
|
||||
.includes(ZU.removeDiacritics(creator.lastName.toLowerCase()))) {
|
||||
let firstNameSplit = creator.firstName.split(/\s+/);
|
||||
if (firstNameSplit.length) {
|
||||
let lastParticleFirstName = firstNameSplit[firstNameSplit.length - 1];
|
||||
creator.lastName = lastParticleFirstName + ' ' + creator.lastName;
|
||||
creator.firstName = firstNameSplit.slice(0, firstNameSplit.length - 1).join(' ');
|
||||
}
|
||||
}
|
||||
item.creators.push(creator);
|
||||
}
|
||||
if (result.Subject) {
|
||||
item.tags.push({ tag: result.Subject });
|
||||
}
|
||||
for (let tag of result.PalavrasChave) {
|
||||
item.tags.push({ tag });
|
||||
}
|
||||
item.complete();
|
||||
}
|
||||
|
||||
function fixCase(s) {
|
||||
if (s && s == s.toUpperCase()) {
|
||||
s = ZU.capitalizeTitle(s, true);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function cleanData(items) {
|
||||
if (!Array.isArray(items)) {
|
||||
items = [items];
|
||||
}
|
||||
return items
|
||||
.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
item = { ISBN: item };
|
||||
}
|
||||
if (item.ISBN) {
|
||||
item.ISBN = ZU.cleanISBN(item.ISBN);
|
||||
}
|
||||
return item;
|
||||
})
|
||||
.filter(item => item.ISBN && (
|
||||
item.ISBN.startsWith('97865')
|
||||
|| item.ISBN.startsWith('65')
|
||||
|| item.ISBN.startsWith('97885')
|
||||
|| item.ISBN.startsWith('85')));
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786599594755"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Mercadores da Insegurança: conjuntura e riscos do hacking governamental no Brasil",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "André",
|
||||
"lastName": "Ramiro",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Pedro",
|
||||
"lastName": "Amaral",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Mariana",
|
||||
"lastName": "Canto",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Marcos César M.",
|
||||
"lastName": "Pereira",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Raquel",
|
||||
"lastName": "Saraiva",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Clara",
|
||||
"lastName": "Guimarães",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2022-10-11",
|
||||
"ISBN": "9786599594755",
|
||||
"abstractNote": "Em políticas públicas, o debate sobre como as técnicas de investigações criminais devem responder à digitalização das dinâmicas sociais tem se sobressaído e caminha em uma linha tênue entre otimização dos processos administrativos e possíveis transgressões em relação aos direitos fundamentais. Nesse sentido, técnicas de hacking governamental, ou seja, de superação de recursos de segurança em dispositivos pessoais, vem ganhando uma escalabilidade crescente e envolve a ampliação de fabricantes, revendedores e contratos com a administração pública, ao passo em que seus efeitos colaterais aos direitos fundamentais, sobretudo em relação à sociedade civil, vêm sendo denunciados internacionalmente.",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"place": "Recife, PE",
|
||||
"publisher": "IP.rec",
|
||||
"shortTitle": "Mercadores da Insegurança",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Digital"
|
||||
},
|
||||
{
|
||||
"tag": "Direito"
|
||||
},
|
||||
{
|
||||
"tag": "Governamental"
|
||||
},
|
||||
{
|
||||
"tag": "Insegurança"
|
||||
},
|
||||
{
|
||||
"tag": "dados"
|
||||
},
|
||||
{
|
||||
"tag": "hacking"
|
||||
},
|
||||
{
|
||||
"tag": "vazamento"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "8532511015"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Harry Potter E a Pedra Filosofal",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "J. K.",
|
||||
"lastName": "Rowling",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2000-05-29",
|
||||
"ISBN": "9788532511010",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"publisher": "Rocco",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Biblioteconomia e ciência da informação"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786555320275"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Harry Potter e o Prisioneiro de Azkaban",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "J. K.",
|
||||
"lastName": "Rowling",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Lia",
|
||||
"lastName": "Wyler",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Arch",
|
||||
"lastName": "Apolar",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2020-03-04",
|
||||
"ISBN": "9786555320275",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"publisher": "Rocco",
|
||||
"series": "Harry Potter",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Harry-Potter"
|
||||
},
|
||||
{
|
||||
"tag": "Literatura infanto-juvenil"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786587233956"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Einstein Socialista: Entrevistas, manifestos e artigos do maior cientista do século XX",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Albert",
|
||||
"lastName": "Einstein",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Hugo",
|
||||
"lastName": "Albuquerque",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"firstName": "Lígia Magalhães",
|
||||
"lastName": "Marinho",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"date": "2023-04-12",
|
||||
"ISBN": "9786587233956",
|
||||
"abstractNote": "Por serem supostamente purgadas da “ideologia”, as ciências exatas alcançaram entre nós um status de demasiada confiabilidade, objetividade e verdade, Entretanto, Albert Einstein, o maior físico do século XX, não compactuava com essa crença e defendia abertamente os valores socialistas, colocando a própria narrativa cientificista, quase sempre favorável à ordem capitalista, em curto-circuito.\n\nEinstein era um militante e não se calou diante das falaciosas equiparações entre a Alemanha Nazista e a União Soviética. Nem se calou, como judeu, diante das violências cometidas contra os palestinos, pouco depois do Holocausto, pelos colonos judeus no nascente Estado de Israel. Tampouco poupou críticas à segregação racial nos Estados Unidos, onde foi lecionar em seus últimos anos.\n\nQuando a Guerra Fria estava a todo vapor, Einstein escreveu “Por que o Socialismo?” –, um de seus artigos mais conhecidos sobre política e frequentemente esquecido e dissociado de sua imagem. Não à toa, este texto, vez ou outra, é apresentado como “novidade” e não cansa de surpreender geração após geração. E que não se diga que era uma forma atenuada de socialismo que Einstein estava falando:\n\n“Numa economia planificada, em que a produção é ajustada às necessidades da comunidade, o trabalho a ser feito seria distribuído entre todas as pessoas aptas ao trabalho e garantiria condições de vida a todo homem, mulher e criança.”\n\nOu mesmo que, especificamente sobre a Revolução Russa, ele tenha confessado a Viereck que: \n\n“O bolchevismo é uma experiência extraordinária. Não é impossível que a deriva da evolução social daqui para a frente seja em direção ao comunismo. O experimento bolchevista talvez valha a pena.”\n\nCom uma certa dose de utopismo e um enorme enigma de como o socialismo pode ser alcançado e mantido, Einstein Socialista nos apresenta uma série de artigos, entrevistas e manifestos que revelam um lado muitas vezes negligenciado e “esquecido” de um dos maiores cientistas do mundo.",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "96",
|
||||
"place": "São Paulo, SP",
|
||||
"publisher": "Autonomia Literaria",
|
||||
"shortTitle": "Einstein Socialista",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Ciências sociais"
|
||||
},
|
||||
{
|
||||
"tag": "einstein"
|
||||
},
|
||||
{
|
||||
"tag": "nazismo"
|
||||
},
|
||||
{
|
||||
"tag": "relatividade"
|
||||
},
|
||||
{
|
||||
"tag": "socialismo"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9788565053082"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "State of the Art in Health and Knowledge",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sociedade Beneficente Israelita Brasileira Albert",
|
||||
"lastName": "Einstein",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Juliana",
|
||||
"lastName": "Samel",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"date": "2023-02-02",
|
||||
"ISBN": "9788565053082",
|
||||
"abstractNote": "The book presents the Albert Einstein Teaching and Research Center - Campus Cecilia and Abram Szajman, an architectural work in the city of São Paulo, created to be one of the most advanced teaching and research centers in the world. Students and researchers interact in this building to generate knowledge, with the aim of boosting Brazilian research and all this in an environment integrated with greenery, with the use of natural light and renewable energy technology.",
|
||||
"language": "Inglês (EUA)",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "58",
|
||||
"place": "São Paulo, SP",
|
||||
"publisher": "Sociedade Beneficente Israelita Brasileira Albert Einstein",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Arquitetura"
|
||||
},
|
||||
{
|
||||
"tag": "Landscaping"
|
||||
},
|
||||
{
|
||||
"tag": "architecture"
|
||||
},
|
||||
{
|
||||
"tag": "health"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786580341221"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Filipson: Memórias de uma menina na primeira colônia judaica no Rio Grande do Sul (1904-1920)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Frida",
|
||||
"lastName": "Alexandr",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Regina",
|
||||
"lastName": "Zilberman",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2023-05-11",
|
||||
"ISBN": "9786580341221",
|
||||
"abstractNote": "“Já ouviram falar de Filipson? Um nome esquisito. Nem parece brasileiro. Mas, dentro do Brasil imenso, constituía um pontinho minúsculo que ficava lá nas bandas do Sul, perdido no meio de diversas colônias prósperas compostas em sua maioria de imigrantes espanhóis, italianos e alemães e uma ou outra fazenda de brasileiros.”\n\nDesde a primeira linha, Frida Alexandr surpreende o leitor, interpelando-o com uma pergunta. Mesmo em 1967, quando suas memórias foram publicadas em edição restrita, provavelmente poucos responderiam afirmativamente à sua questão.\n\nFilipson foi a primeira colônia judaica oficial do Brasil, formada por imigrantes judeus provenientes da Bessarábia (na região onde atualmente se localiza a Moldávia). Os pais e irmãos mais velhos de Frida chegaram ao Brasil com o grupo pioneiro, em 1904, e em \"Filipson: memórias de uma menina na primeira colônia judaica no Rio Grande do Sul (1904-1920)\". Frida deixa um registro que vai dos primeiros dias da colônia à melancólica despedida, em 1920, quando sua família decide partir novamente.\n\nEntre os dois pontos, desliza a memória de Frida, que organiza os fatos sem a preocupação de ordená-los no tempo. O importante é como essas cenas — que envolvem seus familiares, sua passagem pela escola, as dificuldades financeiras da família, as ameaças representadas por uma natureza nem sempre hospitaleira — repercutem em sua sensibilidade. Frida se vale da linguagem para transmitir a emoção na forma como a vivenciou.\n\n\"Filipson\", com posfácio da pesquisadora e escritora Regina Zilberman, é um testemunho de uma etapa do processo de adaptação e preservação dos judeus do leste da Europa no Brasil. Mas esse caráter documental é acompanhado pela recuperação sensível daqueles momentos fundadores, como se a autora, à maneira de Proust, fosse em busca das vivências daquele tempo, para transmiti-lo a um leitor que pouco conhece sobre o período.",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "360",
|
||||
"place": "SÃO PAULO, SP",
|
||||
"publisher": "Chão Editora",
|
||||
"shortTitle": "Filipson",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Biografias"
|
||||
},
|
||||
{
|
||||
"tag": "judeus"
|
||||
},
|
||||
{
|
||||
"tag": "memórias"
|
||||
},
|
||||
{
|
||||
"tag": "mulheres"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786555250053"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Ilíada = Ἰλιάς",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "",
|
||||
"lastName": "Homero",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
},
|
||||
{
|
||||
"firstName": "Trajano",
|
||||
"lastName": "Vieira",
|
||||
"creatorType": "translator"
|
||||
}
|
||||
],
|
||||
"date": "2020-03-23",
|
||||
"ISBN": "9786555250053",
|
||||
"abstractNote": "Composta no século VIII a.C., a Ilíada é considerada o marco inaugural da literatura ocidental. Tradicionalmente atribuída a Homero, a obra aborda o período de algumas semanas no último ano da Guerra de Troia, durante o cerco final dos contingentes gregos à cidadela do rei Príamo, na Ásia Menor. Com seus mais de 15 mil versos, a Ilíada ganha agora uma nova tradução — das mãos de Trajano Vieira, professor livre-docente da Unicamp e premiado tradutor da Odisseia —, rigorosamente metrificada, que busca recriar em nossa língua a excelência do original, com seus símiles e invenções vocabulares. A presente edição, bilíngue, traz ainda uma série de aparatos, como um índice onomástico completo, um posfácio do tradutor, excertos da crítica, e o célebre ensaio de Simone Weil, “A Ilíada ou o poema da força”.",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "1048",
|
||||
"place": "São Paulo, SP",
|
||||
"publisher": "Editora 34",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Literatura grega"
|
||||
},
|
||||
{
|
||||
"tag": "Literatura."
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786556752631"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Manual de Sentença Trabalhista: Compreendendo a técnica da setença trabalhista para concurso",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Aline",
|
||||
"lastName": "Leporaci",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Adriana Leandro de Sousa",
|
||||
"lastName": "Freitas",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2023-03-02",
|
||||
"ISBN": "9786556752631",
|
||||
"abstractNote": "Nesse livro sobre sentença trabalhista, fase tão concorrida do concurso para a Magistratura do Trabalho, procuramos trazer os aspectos mais importantes a serem observados pelo candidato. O leitor poderá verificar a ordem de julgamento a seguir e a importância da fixação da prejudicialidade entre as matérias a serem analisadas. Além disso, também aprenderá as técnicas de distribuição do ônus da prova, e suas diversas teorias, sempre ressaltando qual deva ser de aplicação preferencial pelo candidato. O livro traz diversos aspectos teóricos, que são essenciais para a preparação de todos os interessados em efetivamente aprender a técnica da elaboração da sentença trabalhista, sempre com leitura fácil e direta. E não nos esquecemos dos aspectos práticos, pois o leitor terá exercícios de fixação de jornada de trabalho, e sentenças inéditas elaboradas pelas Autoras, com os respectivos gabaritos e sugestão de redação.",
|
||||
"edition": "2",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "232",
|
||||
"place": "Rio de Janeiro, RJ",
|
||||
"publisher": "Freitas Bastos Editora",
|
||||
"shortTitle": "Manual de Sentença Trabalhista",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Direito"
|
||||
},
|
||||
{
|
||||
"tag": "Elaboração"
|
||||
},
|
||||
{
|
||||
"tag": "Jornada"
|
||||
},
|
||||
{
|
||||
"tag": "Magistratura"
|
||||
},
|
||||
{
|
||||
"tag": "Trabalhista"
|
||||
},
|
||||
{
|
||||
"tag": "Trabalho"
|
||||
},
|
||||
{
|
||||
"tag": "Técnica"
|
||||
},
|
||||
{
|
||||
"tag": "concurso"
|
||||
},
|
||||
{
|
||||
"tag": "juiz"
|
||||
},
|
||||
{
|
||||
"tag": "modelos"
|
||||
},
|
||||
{
|
||||
"tag": "sentença"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786559602513"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Batman",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Ridley",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "James Tynion",
|
||||
"lastName": "IV",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Dandara",
|
||||
"lastName": "Palankof",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Pedro",
|
||||
"lastName": "Catarino",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Travel",
|
||||
"lastName": "Foreman",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Riccardo",
|
||||
"lastName": "Federici",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Jorge",
|
||||
"lastName": "Jimenez",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2022-03-11",
|
||||
"ISBN": "9786559602513",
|
||||
"abstractNote": "Aventuras do Batman",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "100",
|
||||
"place": "Barueri, SP",
|
||||
"publisher": "Panini Comics",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Cartoons; caricaturas e quadrinhos"
|
||||
},
|
||||
{
|
||||
"tag": "quadrinhos"
|
||||
},
|
||||
{
|
||||
"tag": "super-herois"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9786559605101"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Superman",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sean",
|
||||
"lastName": "Lewis",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Phillip Kennedy",
|
||||
"lastName": "Johnson",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Gabriel",
|
||||
"lastName": "Faria",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Rodrigo",
|
||||
"lastName": "Barros",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Sami",
|
||||
"lastName": "Basri",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Phil",
|
||||
"lastName": "Hester",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Daniel",
|
||||
"lastName": "Sampere",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"date": "2022-03-10",
|
||||
"ISBN": "9786559605101",
|
||||
"abstractNote": "Aventuras do Superman",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"numPages": "100",
|
||||
"place": "Barueri, SP",
|
||||
"publisher": "Panini Comics",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Cartoons; caricaturas e quadrinhos"
|
||||
},
|
||||
{
|
||||
"tag": "quadrinhos"
|
||||
},
|
||||
{
|
||||
"tag": "super-herois"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "8576664984"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "A Religião Nos Limites Da Simples Razão",
|
||||
"creators": [],
|
||||
"date": "2006-01-02",
|
||||
"ISBN": "9788576664987",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"publisher": "Escala Educacional",
|
||||
"series": "Série Filosofar",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Literatura"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"ISBN": "9788591597512"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Visões da áfrica: angola e moçambiqueJorge Alves de Lima Filho",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jorge Alves de",
|
||||
"lastName": "Lima Filho",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-09-29",
|
||||
"ISBN": "9788591597512",
|
||||
"language": "pt-BR",
|
||||
"libraryCatalog": "Câmara Brasileira do Livro ISBN",
|
||||
"publisher": "Jorge Alves de Lima Filho",
|
||||
"shortTitle": "Visões da áfrica",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Coleções de obras diversas sem assunto específico"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -9,13 +9,13 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-04-17 08:48:37"
|
||||
"lastUpdated": "2024-11-20 15:43:05"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2016-2020 Sebastian Karcher
|
||||
Copyright © 2016-2024 Sebastian Karcher
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ function getSearchResults(doc, checkOnly) {
|
|||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll(
|
||||
'li.title a[href*="/article/"], li.title a[href*="/product/"], li.title a[href*="/books/"]'
|
||||
'li.title a[href*="/article/"], li.title a[href*="/product/"], li.title a[href*="/books/"], div.results .product-listing-with-inputs-content a[href*="/books/"]'
|
||||
);
|
||||
for (let row of rows) {
|
||||
var href = row.href;
|
||||
|
|
@ -82,28 +82,24 @@ function getSearchResults(doc, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, false), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
var articles = [];
|
||||
for (let i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
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 {
|
||||
scrape(doc, url);
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
// Book metadata is much better using RIS
|
||||
if (detectWeb(doc, url) == "book" || detectWeb(doc, url) == "bookSection") {
|
||||
let productID = url.replace(/[#?].+/, "").match(/\/([^/]+)$/)[1];
|
||||
let productID = url.replace(/[#?].*/, "").match(/\/([^/]+)$/)[1];
|
||||
let risURL
|
||||
= "/core/services/aop-easybib/export?exportType=ris&productIds="
|
||||
+ productID + "&citationStyle=apa";
|
||||
|
|
@ -112,39 +108,43 @@ function scrape(doc, url) {
|
|||
var pdfURL = ZU.xpathText(doc,
|
||||
'//meta[contains(@name, "citation_pdf_url")]/@content'
|
||||
);
|
||||
if (!pdfURL) {
|
||||
pdfURL = attr(doc, '.actions a[target="_blank"][href*=".pdf"]', 'href');
|
||||
}
|
||||
// Z.debug("pdfURL: " + pdfURL);
|
||||
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) {
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
var text = await requestText(risURL);
|
||||
var translator = Zotero.loadTranslator(
|
||||
"import");
|
||||
translator.setTranslator(
|
||||
"32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(text);
|
||||
translator.setHandler("itemDone", function (obj,
|
||||
item) {
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
// don't save Cambridge Core to archive
|
||||
item.archive = "";
|
||||
item.complete();
|
||||
}
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
translator.translate();
|
||||
// don't save Cambridge Core to archive
|
||||
item.archive = "";
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
// Some elements of journal citations look better with EM
|
||||
else {
|
||||
var translator = Zotero.loadTranslator('web');
|
||||
let translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.url = url;
|
||||
var abstract = ZU.xpathText(doc,
|
||||
'//div[@class="abstract"]');
|
||||
|
|
@ -152,6 +152,7 @@ function scrape(doc, url) {
|
|||
item.abstractNote = abstract;
|
||||
}
|
||||
item.title = ZU.unescapeHTML(item.title);
|
||||
item.publisher = ""; // don't grab the publisher
|
||||
item.libraryCatalog = "Cambridge University Press";
|
||||
if (item.date.includes("undefined")) {
|
||||
item.date = attr('meta[name="citation_online_date"]', "content");
|
||||
|
|
@ -161,18 +162,18 @@ function scrape(doc, url) {
|
|||
if (titleElem.querySelector('a:last-child')) {
|
||||
item.title = titleElem.firstChild.textContent;
|
||||
}
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
if (url.includes("/books")) {
|
||||
trans.itemType = "book";
|
||||
}
|
||||
else {
|
||||
trans.itemType = "journalArticle";
|
||||
}
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
let em = await translator.getTranslatorObject();
|
||||
// TODO map additional meta tags here, or delete completely
|
||||
if (url.includes("/books")) {
|
||||
em.itemType = "book";
|
||||
}
|
||||
else {
|
||||
em.itemType = "journalArticle";
|
||||
}
|
||||
await em.doWeb(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -208,10 +209,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
|
|
@ -258,10 +255,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -449,11 +442,6 @@ var testCases = [
|
|||
"url": "https://www.cambridge.org/core/what-we-publish/books/listing?sort=canonical.date%3Adesc&aggs%5BonlyShowAvailable%5D%5Bfilters%5D=true&aggs%5BproductTypes%5D%5Bfilters%5D=BOOK%2CELEMENT&searchWithinIds=0C5182F27A492FDC81EDF8D3C53266B5",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cambridge.org/core/journals/ajs-review/firstview",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cambridge.org/core/journals/ajs-review/latest-issue",
|
||||
|
|
@ -534,6 +522,59 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cambridge.org/core/journals/american-political-science-review/firstview",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.cambridge.org/core/books/foundations-of-probabilistic-programming/819623B1B5B33836476618AC0621F0EE",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Foundations of Probabilistic Programming",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Barthe",
|
||||
"firstName": "Gilles",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "Katoen",
|
||||
"firstName": "Joost-Pieter",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "Silva",
|
||||
"firstName": "Alexandra",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2020",
|
||||
"ISBN": "9781108488518",
|
||||
"abstractNote": "What does a probabilistic program actually compute? How can one formally reason about such probabilistic programs? This valuable guide covers such elementary questions and more. It provides a state-of-the-art overview of the theoretical underpinnings of modern probabilistic programming and their applications in machine learning, security, and other domains, at a level suitable for graduate students and non-experts in the field. In addition, the book treats the connection between probabilistic programs and mathematical logic, security (what is the probability that software leaks confidential information?), and presents three programming languages for different applications: Excel tables, program testing, and approximate computing. This title is also available as Open Access on Cambridge Core.",
|
||||
"extra": "DOI: 10.1017/9781108770750",
|
||||
"libraryCatalog": "Cambridge University Press",
|
||||
"place": "Cambridge",
|
||||
"publisher": "Cambridge University Press",
|
||||
"url": "https://www.cambridge.org/core/books/foundations-of-probabilistic-programming/819623B1B5B33836476618AC0621F0EE",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-12-08 18:55:55"
|
||||
"lastUpdated": "2023-10-23 08:35:07"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -52,7 +52,7 @@ function detectWeb(doc, url) {
|
|||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.MatchResult > a');
|
||||
var rows = doc.querySelectorAll('.MatchResult article a');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
|
||||
|
|
@ -68,11 +68,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (items) {
|
||||
await Promise.all(
|
||||
Object.keys(items)
|
||||
.map(url => requestDocument(url).then(scrape))
|
||||
);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -89,6 +87,9 @@ async function scrape(doc, url = doc.location.href) {
|
|||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.publisher = attr(doc, 'meta[property="og:site_name"]', 'content');
|
||||
item.libraryCatalog = "Cambridge Engage Preprints";
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://chemrxiv.org/engage/chemrxiv/search-dashboard?text=acid",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
|
|
@ -123,7 +125,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021/10/08",
|
||||
"date": "2021-10-08",
|
||||
"DOI": "10.26434/chemrxiv-2021-mjpkz",
|
||||
"abstractNote": "Conversion of readily available feedstocks to valuable platform chemicals via a sustainable catalytic pathway has always been one of the key focuses of synthetic chemists. Cheaper, less toxic, and more abundant base metals as a catalyst for performing such transformations provide an additional boost. In this context, herein, we report a reformation of readily available feedstock, ethylene glycol, to value-added platform molecules, glycolic acid, and lactic acid. A bench stable base metal complex {[HN(C2H4PPh2)2]Mn(CO)2Br}, Mn-I, known as Mn-PhMACHO, catalyzed the reformation of ethylene glycol to glycolic acid at 140 oC in high selectivity with a turnover number TON = 2400, surpassing previously used homogeneous catalysts for such a reaction. Pure hydrogen gas is evolved without the need for an acceptor. On the other hand, a bench stable Mn(I)-complex, {(iPrPN5P)Mn(CO)2Br}, Mn-III, with a triazine backbone, efficiently catalyzed the acceptorless dehydrogenative coupling of ethylene glycol and methanol for the synthesis of lactic acid, even at a ppm level of catalyst loading, reaching the TON of 11,500. Detailed mechanistic studies were performed to elucidate the involvements of different manganese(I)-species during the catalysis.",
|
||||
"language": "en",
|
||||
|
|
@ -180,7 +182,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2019/10/02",
|
||||
"date": "2019-10-03",
|
||||
"DOI": "10.33774/apsa-2019-if2he-v2",
|
||||
"abstractNote": "The discipline of political science has been engaged in discussion about when, why, and how to make scholarship more transparent for at least three decades. This piece argues that qualitative researchers can achieve transparency in diverse ways, using techniques and strategies that allow them to balance and optimize among competing considerations that affect the pursuit of transparency.. We begin by considering the “state of the debate,” briefly outlining the contours of the scholarship on transparency in political and other social sciences, which so far has focussed mostly on questions of “whether” and “what” to share. We investigate competing considerations that researchers have to consider when working towards transparent research. The heart of the piece considers various strategies, illustrated by exemplary applications, for making qualitative research more transparent.",
|
||||
"language": "en",
|
||||
|
|
@ -238,7 +240,7 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021/07/20",
|
||||
"date": "2021-07-20",
|
||||
"DOI": "10.33774/miir-2021-7cdx1",
|
||||
"abstractNote": "This report addresses the construction of carbon fibre wing boxes and the problems associated with using carbon fibre sheets rather than individual carbon fibre tapes. In the case that the wing boxes are developable surfaces the lay up of carbon fibre sheets is straightforward, since the fibres can follow the contours of the surface without any need for shearing or extension of the fibres. To further expand the potential design space for the wing boxes, this report investigates the lay up of sheets over non-developable surfaces where some shearing of the sheet is required to achieve the desired results. In this report, three analytical approaches are considered, driven by the results from numerical studies on different surface geometries. Each of the approaches offers insights as to the type of geometric perturbations achievable when constrained by a maximum shear angle.",
|
||||
"language": "en",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
{
|
||||
"translatorID": "d8a83346-164a-467d-8717-eb96d4dcce6f",
|
||||
"label": "ChatGPT",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https://chatgpt\\.com/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-10-27 15:38:43"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2025 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 *****
|
||||
*/
|
||||
|
||||
// Simple translator for ChatGPT that grabs the date and model info
|
||||
// for private and public chats.
|
||||
|
||||
// Please don't take any of the translator authorship advice that ChatGPT
|
||||
// gives in the test page. It's mostly wrong.
|
||||
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/c/') || url.includes('/share/')) {
|
||||
return 'webpage';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
let item = new Zotero.Item('webpage');
|
||||
item.title = doc.title;
|
||||
item.websiteTitle = 'ChatGPT';
|
||||
item.websiteType = 'Generative AI chat';
|
||||
|
||||
if (url.includes('/share/')) {
|
||||
item.url = url;
|
||||
}
|
||||
|
||||
item.creators.push({
|
||||
creatorType: 'author',
|
||||
lastName: 'OpenAI',
|
||||
fieldMode: 1
|
||||
});
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
|
||||
try {
|
||||
await enrichItemWithAPI(doc, url, item);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
}
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
async function enrichItemWithAPI(doc, url, item) {
|
||||
let dataScript = [...doc.querySelectorAll('script')]
|
||||
.find(script => script.textContent.startsWith('window.__reactRouterContext.streamController.enqueue('))
|
||||
.textContent;
|
||||
let extract = (key) => {
|
||||
let formattedKey = `\\"${key}\\",\\"`;
|
||||
let keyIndex = dataScript.indexOf(formattedKey);
|
||||
if (keyIndex === -1) return null;
|
||||
return dataScript.substring(keyIndex + formattedKey.length).split('\\"')[0];
|
||||
};
|
||||
|
||||
let language = extract('locale');
|
||||
let deviceID = extract('WebAnonymousCookieID');
|
||||
let accessToken = extract('accessToken');
|
||||
let clientVersion = doc.documentElement.dataset.build;
|
||||
|
||||
let id = url.match(/\/(?:c|share)\/([^#?/]+)/)[1];
|
||||
let apiSlug;
|
||||
if (url.includes('/c/')) {
|
||||
apiSlug = 'conversation/' + id;
|
||||
}
|
||||
else {
|
||||
apiSlug = 'share/' + id;
|
||||
}
|
||||
|
||||
let apiURL = '/backend-api/' + apiSlug;
|
||||
let headers = {
|
||||
'OAI-Language': language,
|
||||
'OAI-Device-Id': deviceID,
|
||||
'OAI-Client-Version': clientVersion,
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
}
|
||||
|
||||
let json = await requestJSON(apiURL, { headers });
|
||||
item.title = json.title;
|
||||
let date = new Date((json.update_time || json.create_time) * 1000);
|
||||
item.date = ZU.strToISO(date.toISOString());
|
||||
if (json.model) {
|
||||
item.websiteTitle += ` (${json.model.title})`;
|
||||
}
|
||||
|
||||
if (url.includes('/c/')) {
|
||||
// Private conversation: Add existing share URL if available
|
||||
try {
|
||||
let { items: shares }
|
||||
= await requestJSON('/backend-api/shared_conversations?order=created', { headers });
|
||||
let share = shares.find(share => share.conversation_id === id);
|
||||
if (share) {
|
||||
Zotero.debug('Conversation has been shared as ' + share.id);
|
||||
if (new Date(share.update_time) >= date) {
|
||||
Zotero.debug('Share is up to date');
|
||||
item.url = `https://chatgpt.com/share/${share.id}`;
|
||||
}
|
||||
else {
|
||||
Zotero.debug(`Out of date: ${share.update_time} < ${date}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Zotero.debug('Not yet shared');
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug('Unable to find share');
|
||||
Zotero.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://chatgpt.com/share/68fa640b-9fc8-8013-a803-3d5241df6556",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "Write Zotero translator",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"lastName": "OpenAI",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "2025-10-24",
|
||||
"url": "https://chatgpt.com/share/68fa640b-9fc8-8013-a803-3d5241df6556",
|
||||
"websiteTitle": "ChatGPT (GPT-5)",
|
||||
"websiteType": "Generative AI chat",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
{
|
||||
"translatorID": "1e2a9aba-eb04-4398-9e3a-630e6132db13",
|
||||
"label": "Chicago Journal of Theoretical Computer Science",
|
||||
"creator": "Morgan Shirley",
|
||||
"target": "^https?://cjtcs\\.cs\\.uchicago\\.edu/articles",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-05-14 00:10:19"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2025 Morgan Shirley
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
/**
|
||||
* Volumes are at articles/year/contents.html
|
||||
* Individual articles are at articles/year/#/contents.html
|
||||
* Special issues at articles/[issue name]/contents.html
|
||||
*/
|
||||
function detectWeb(doc, url) {
|
||||
var singleRe = /^https?:\/\/cjtcs\.cs\.uchicago\.edu\/articles\/\w+\/\d+\/contents.html/
|
||||
var multipleRe = /^https?:\/\/cjtcs\.cs\.uchicago\.edu\/articles\/\w+\/contents.html/
|
||||
if (multipleRe.test(url)) {
|
||||
return getMultiple(doc, true) && "multiple";
|
||||
}
|
||||
else if (singleRe.test(url)) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
function getMultiple(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
// We need to be specific to avoid navigating to special issues
|
||||
var rows = doc.querySelectorAll('ul > li > ul > li');
|
||||
for (let row of rows) {
|
||||
// Only the first link in a list item is an article
|
||||
let article_link = row.querySelector('a[href*="contents.html"]');
|
||||
let href = article_link.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(getMultiple(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 bibUrl = doc.querySelector('a[href*=".bib"]')
|
||||
let bibText = fixAuthorLine(await requestText(bibUrl.href));
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator('9cb70025-a888-4a29-a210-93ec52da40d4');
|
||||
translator.setString(bibText);
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
//DOI is listed on page
|
||||
let doiElement = doc.querySelector('a[href*="dx.doi.org"]');
|
||||
item.DOI = ZU.cleanDOI(doiElement.href);
|
||||
|
||||
//Download PDF, or Snapshot if unavailable
|
||||
let pdfElement = doc.querySelector('a[href*=".pdf"]');
|
||||
if (pdfElement) {
|
||||
item.attachments.push({
|
||||
url: pdfElement.href,
|
||||
title: 'Full Text PDF',
|
||||
mimeType: 'application/pdf'
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: 'Snapshot',
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
// Sometimes the bibtex will omit an equals sign after "author"
|
||||
function fixAuthorLine(input) {
|
||||
return input.split('\n').map(line => {
|
||||
return line.replace(/^(\s*author)(?!\s*=)/, '$1=');
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://cjtcs.cs.uchicago.edu/articles/2010/1/contents.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Quantum Boolean Functions",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Ashley",
|
||||
"lastName": "Montanaro",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Tobias J.",
|
||||
"lastName": "Osborne",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2010-01",
|
||||
"DOI": "10.4086/cjtcs.2010.001",
|
||||
"issue": "1",
|
||||
"itemID": "cj10-01",
|
||||
"libraryCatalog": "Chicago Journal of Theoretical Computer Science",
|
||||
"publicationTitle": "Chicago Journal of Theoretical Computer Science",
|
||||
"volume": "2010",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://cjtcs.cs.uchicago.edu/articles/2010/contents.html",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://cjtcs.cs.uchicago.edu/articles/CATS2009/1/contents.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "On Process Complexity",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Adam R.",
|
||||
"lastName": "Day",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2010-06",
|
||||
"DOI": "10.4086/cjtcs.2010.004",
|
||||
"issue": "4",
|
||||
"itemID": "cats9-1",
|
||||
"libraryCatalog": "Chicago Journal of Theoretical Computer Science",
|
||||
"publicationTitle": "Chicago Journal of Theoretical Computer Science",
|
||||
"volume": "2010",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
{
|
||||
"translatorID": "46291dc3-5cbd-47b7-8af4-d009078186f6",
|
||||
"label": "CiNii Research",
|
||||
"creator": "Michael Berkowitz, Mitsuo Yoshida and Satoshi Ando",
|
||||
"target": "^https?://cir\\.nii\\.ac\\.jp/",
|
||||
"minVersion": "1.0.0b4.r5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-09-26 14:22:20"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 Michael Berkowitz, Mitsuo Yoshida and Satoshi Ando
|
||||
|
||||
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("/crid/")) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (doc.evaluate('//a[contains(@href, "/crid/")]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var arts = [];
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var items = {};
|
||||
var links = doc.evaluate('//a[contains(@href, "/crid/")]', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var link;
|
||||
while ((link = links.iterateNext())) {
|
||||
items[link.href] = Zotero.Utilities.trimInternal(link.textContent);
|
||||
}
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
for (var i in items) {
|
||||
arts.push(i);
|
||||
}
|
||||
Zotero.Utilities.processDocuments(arts, scrape);
|
||||
});
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, _url) {
|
||||
var newurl = doc.location.href;
|
||||
var biblink = ZU.xpathText(doc, '//li/div/a[contains(text(), "BibTeX")]/@href');
|
||||
//Z.debug(biblink)
|
||||
var tags = [];
|
||||
if (doc.evaluate('//a[@rel="tag"]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var kws = doc.evaluate('//a[@rel="tag"]', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var kw;
|
||||
while ((kw = kws.iterateNext())) {
|
||||
tags.push(Zotero.Utilities.trimInternal(kw.textContent));
|
||||
}
|
||||
}
|
||||
//var abstractPath = '//div[@class="abstract"]/p[@class="entry-content"]';
|
||||
var abstractPath = '//div[contains(@class, "abstract")]/p[contains(@class, "entry-content")]';
|
||||
var abstractNote;
|
||||
if (doc.evaluate(abstractPath, doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
abstractNote = doc.evaluate(abstractPath, doc, null, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
}
|
||||
Zotero.Utilities.HTTP.doGet(biblink, function (text) {
|
||||
var trans = Zotero.loadTranslator("import");
|
||||
trans.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
trans.setString(text);
|
||||
trans.setHandler("itemDone", function (obj, item) {
|
||||
item.url = newurl;
|
||||
item.attachments = [{ url: item.url, title: item.title + " Snapshot", mimeType: "text/html" }];
|
||||
item.tags = tags;
|
||||
item.abstractNote = abstractNote;
|
||||
if (item.ISSN) {
|
||||
item.ISSN = ZU.cleanISSN(item.ISSN);
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://cir.nii.ac.jp/all?q=test&range=0&count=20&sortorder=1&type=0",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://cir.nii.ac.jp/crid/1390001204062164736",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "観測用既存鉄骨造モデル構造物を用いたオンライン応答実験",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "謙一",
|
||||
"lastName": "大井",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "與助",
|
||||
"lastName": "嶋脇",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "拓海",
|
||||
"lastName": "伊藤",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "玉順",
|
||||
"lastName": "李",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2002",
|
||||
"DOI": "10.11188/seisankenkyu.54.384",
|
||||
"ISSN": "1881-2058",
|
||||
"abstractNote": "特集 ERS(耐震構造学)",
|
||||
"issue": "6",
|
||||
"itemID": "1390001204062164736",
|
||||
"libraryCatalog": "CiNii Research",
|
||||
"pages": "384-387",
|
||||
"publicationTitle": "生産研究",
|
||||
"url": "https://cir.nii.ac.jp/crid/1390001204062164736",
|
||||
"volume": "54",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "観測用既存鉄骨造モデル構造物を用いたオンライン応答実験 Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
136
CiNii.js
136
CiNii.js
|
|
@ -1,136 +0,0 @@
|
|||
{
|
||||
"translatorID": "46291dc3-5cbd-47b7-8af4-d009078186f6",
|
||||
"label": "CiNii",
|
||||
"creator": "Michael Berkowitz and Mitsuo Yoshida",
|
||||
"target": "^https?://ci\\.nii\\.ac\\.jp/",
|
||||
"minVersion": "1.0.0b4.r5",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2012-11-24 13:12:41"
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.match(/naid/)) {
|
||||
return "journalArticle";
|
||||
} else if (doc.evaluate('//a[contains(@href, "/naid/")]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
return "multiple";
|
||||
}
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var arts = new Array();
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var items = new Object();
|
||||
var links = doc.evaluate('//a[contains(@href, "/naid/")]', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var link;
|
||||
while (link = links.iterateNext()) {
|
||||
items[link.href] = Zotero.Utilities.trimInternal(link.textContent);
|
||||
}
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
for (var i in items) {
|
||||
arts.push(i);
|
||||
}
|
||||
Zotero.Utilities.processDocuments(arts, scrape, function () {
|
||||
Zotero.done();
|
||||
});
|
||||
Zotero.wait();
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url)
|
||||
}
|
||||
}
|
||||
function scrape(doc, url){
|
||||
var newurl = doc.location.href;
|
||||
var biblink = ZU.xpathText(doc, '//li/div/a[contains(text(), "BibTeX")]/@href');
|
||||
//Z.debug(biblink)
|
||||
var tags = new Array();
|
||||
if (doc.evaluate('//a[@rel="tag"]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
var kws = doc.evaluate('//a[@rel="tag"]', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var kw;
|
||||
while (kw = kws.iterateNext()) {
|
||||
tags.push(Zotero.Utilities.trimInternal(kw.textContent));
|
||||
}
|
||||
}
|
||||
var abstractNote;
|
||||
if (doc.evaluate('//div[@class="abstract"]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
abstractNote = doc.evaluate('//div[@class="abstract"]', doc, null, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
}
|
||||
Zotero.Utilities.HTTP.doGet(biblink, function(text) {
|
||||
var trans = Zotero.loadTranslator("import");
|
||||
trans.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
trans.setString(text);
|
||||
trans.setHandler("itemDone", function(obj, item) {
|
||||
item.url = newurl;
|
||||
item.attachments = [{url:item.url, title:item.title + " Snapshot", mimeType:"text/html"}];
|
||||
item.tags = tags;
|
||||
item.abstractNote = abstractNote;
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
});
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://ci.nii.ac.jp/search?q=test&range=0&count=20&sortorder=1&type=0",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://ci.nii.ac.jp/naid/110000244188/ja/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "<研究速報>観測用既存鉄骨造モデル構造物を用いたオンライン応答実験=Pseudo-dynamic tests on existing steel model structure for seismic monitoring",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "謙一=Kenichi Ohi",
|
||||
"lastName": "大井",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "輿助=Yosuke Shimawaki",
|
||||
"lastName": "嶋脇",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "拓海=Takumi Ito",
|
||||
"lastName": "伊藤",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Li",
|
||||
"lastName": "Yushun",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "November 2002",
|
||||
"DOI": "10.11188/seisankenkyu.54.384",
|
||||
"ISSN": "0037105X",
|
||||
"issue": "6",
|
||||
"itemID": "110000244188",
|
||||
"libraryCatalog": "CiNii",
|
||||
"pages": "384-387",
|
||||
"publicationTitle": "生産研究",
|
||||
"url": "http://ci.nii.ac.jp/naid/110000244188/ja/",
|
||||
"volume": "54",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "<研究速報>観測用既存鉄骨造モデル構造物を用いたオンライン応答実験=Pseudo-dynamic tests on existing steel model structure for seismic monitoring Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
"inRepository": true,
|
||||
"translatorType": 1,
|
||||
"lastUpdated": "2022-08-18 11:23:00"
|
||||
"lastUpdated": "2025-01-04 01:03:00"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -124,6 +124,7 @@ async function importItems({ references, doc, citaviVersion, rememberTags, itemI
|
|||
item.numberOfVolumes = ZU.xpathText(references[i], './NumberOfVolumes');
|
||||
|
||||
addExtraLine(item, "PMID", ZU.xpathText(references[i], './PubMedID'));
|
||||
addExtraLine(item, "Citation Key", ZU.xpathText(references[i], './BibTeXKey'));
|
||||
|
||||
item.pages = extractPages(ZU.xpathText(references[i], './PageRange'));
|
||||
item.numPages = extractPages(ZU.xpathText(references[i], './PageCount'));
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-11-10 02:47:43"
|
||||
"lastUpdated": "2023-08-22 04:14:33"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -40,9 +40,16 @@ function detectWeb(doc, url) {
|
|||
if (url.includes('/index.cfm/detail/')) {
|
||||
return 'journalArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
|
||||
let appRoot = doc.querySelector("#app"); // Ajax app "mount point"
|
||||
if (appRoot) {
|
||||
// Watch for live filtering of search results)
|
||||
Z.monitorDOMChanges(appRoot);
|
||||
}
|
||||
if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -64,11 +71,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (items) {
|
||||
await Promise.all(
|
||||
Object.keys(items)
|
||||
.map(url => requestDocument(url).then(scrape))
|
||||
);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -76,7 +81,7 @@ async function doWeb(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
function scrape(doc) {
|
||||
async function scrape(doc) {
|
||||
var pmid = text(doc, 'li>a[href*="www.ncbi.nlm.nih.gov/pubmed"]');
|
||||
var doi = text(doc, 'li>a[href*="doi.org/10."]');
|
||||
var abstract = text(doc, '#cchh-detail-abstract');
|
||||
|
|
@ -185,6 +190,7 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://tools.niehs.nih.gov/cchhl/index.cfm/main/search#/params?searchTerm=heat%20pump&selectedFacets=&selectedResults=",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
{
|
||||
"translatorID": "07890a30-866e-452a-ac3e-c19fcb39b597",
|
||||
"label": "CourtListener",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://www\\.courtlistener\\.com/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-04-29 03:02:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2024 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('/opinion/')) {
|
||||
return 'case';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('article > h3 > 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(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(doc);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
var item = new Zotero.Item('case');
|
||||
|
||||
let citations = ZU.xpath(doc, '//li/strong[contains(text(), "Citations:")]/following-sibling::span')
|
||||
.map(el => el.textContent.trim());
|
||||
|
||||
let citation = text(doc, 'center b .citation');
|
||||
item.caseName = text(doc, '#caption');
|
||||
item.court = text(doc, '.case-court');
|
||||
item.reporter = text(doc, '.citation .reporter');
|
||||
item.reporterVolume = text(doc, '.citation .volume');
|
||||
item.firstPage = text(doc, '.citation .page');
|
||||
if (!item.reporter && !item.reporterVolume) {
|
||||
// the reporter elements aren't always tagged. We might have to parse them
|
||||
// the best version is in the top of the opinion (we always want that for history matching,
|
||||
// so getting that outside the conditional
|
||||
|
||||
// if that's not there, we're parsing from the title of the case
|
||||
if (!citation) {
|
||||
citation = citations[0];
|
||||
}
|
||||
let citeExpr = citation.trim().match(/^(\d+)\s((?:[A-Z][a-z]?\.\s?)+(?:[2-3]d)?(?:Supp\.)?)\s(\d{1,4})(,|$)/);
|
||||
if (citeExpr) {
|
||||
item.reporterVolume = citeExpr[1];
|
||||
item.reporter = citeExpr[2];
|
||||
item.firstPage = citeExpr[3];
|
||||
}
|
||||
else {
|
||||
// if we can't match the reporter elements properly, just write the whole thing to citation.
|
||||
item.history = citation;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.history) {
|
||||
item.history = citations.slice(1).join(', ');
|
||||
}
|
||||
|
||||
item.dateDecided = text(doc, ".case-date-new");
|
||||
// No good selectors for docket number and authors
|
||||
let docket = ZU.xpathText(doc, '//li[strong[contains(text(), "Docket Number:")]]/text()[1]');
|
||||
item.docketNumber = docket ? docket.trim() : "";
|
||||
let authors = doc.querySelectorAll(".opinion-section-title > a[href*='/person/']");
|
||||
for (let author of authors) {
|
||||
item.creators.push(ZU.cleanAuthor(author.textContent.trim(), "author", false));
|
||||
}
|
||||
item.url = url.replace(/\/\?.*/, "");
|
||||
item.attachments.push({ document: doc, title: "Full Text" });
|
||||
item.extra = "";
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.courtlistener.com/opinion/1872757/gibson-v-bossier-city-general-hosp/?type=o&q=testing&type=o&order_by=score%20desc&stat_Precedential=on",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Gibson v. Bossier City General Hosp.",
|
||||
"creators": [],
|
||||
"dateDecided": "Nov. 26, 1991",
|
||||
"court": "Louisiana Court of Appeal",
|
||||
"docketNumber": "22693-CA, 23002-CA",
|
||||
"firstPage": "1332",
|
||||
"history": "1991 La. App. LEXIS 3211, 1991 WL 249791",
|
||||
"reporter": "So.2d",
|
||||
"reporterVolume": "594",
|
||||
"url": "https://www.courtlistener.com/opinion/1872757/gibson-v-bossier-city-general-hosp",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.courtlistener.com/opinion/1611405/blackwell-v-power-test-corp/?type=o&type=o&q=testing&order_by=score+desc&stat_Precedential=on&page=3",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Blackwell v. Power Test Corp.",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Henry Curtis",
|
||||
"lastName": "Meanor",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"dateDecided": "Aug. 19, 1981",
|
||||
"court": "District Court, D. New Jersey",
|
||||
"docketNumber": "Civ. A. 80-2227",
|
||||
"firstPage": "802",
|
||||
"history": "1981 U.S. Dist. LEXIS 10126",
|
||||
"reporter": "F.Supp.",
|
||||
"reporterVolume": "540",
|
||||
"url": "https://www.courtlistener.com/opinion/1611405/blackwell-v-power-test-corp",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.courtlistener.com/opinion/108284/griggs-v-duke-power-co/?q=testing",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "Griggs v. Duke Power Co.",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Warren Earl",
|
||||
"lastName": "Burger",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"dateDecided": "March 8, 1971",
|
||||
"court": "Supreme Court of the United States",
|
||||
"docketNumber": "124",
|
||||
"firstPage": "424",
|
||||
"history": "91 S. Ct. 849, 28 L. Ed. 2d 158, 3 Empl. Prac. Dec. (CCH) 8137, 3 Fair Empl. Prac. Cas. (BNA) 175, 1971 U.S. LEXIS 134",
|
||||
"reporter": "U.S.",
|
||||
"reporterVolume": "401",
|
||||
"url": "https://www.courtlistener.com/opinion/108284/griggs-v-duke-power-co",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.courtlistener.com/?q=testing",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.courtlistener.com/opinion/3959231/state-v-martin/?q=State%20v.%20Martin&type=o&order_by=score%20desc&stat_Precedential=on",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "case",
|
||||
"caseName": "State v. Martin",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Robert L.",
|
||||
"lastName": "Black",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"dateDecided": "Feb. 9, 1983",
|
||||
"court": "Ohio Court of Appeals",
|
||||
"docketNumber": "C-820238",
|
||||
"firstPage": "717",
|
||||
"history": "20 Ohio App. 3d 172, 20 Ohio B. 215, 1983 Ohio App. LEXIS 16057",
|
||||
"reporter": "N.E.2d",
|
||||
"reporterVolume": "485",
|
||||
"url": "https://www.courtlistener.com/opinion/3959231/state-v-martin",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
332
Crossref-REST.js
332
Crossref-REST.js
|
|
@ -1,332 +0,0 @@
|
|||
{
|
||||
"translatorID": "0a61e167-de9a-4f93-a68a-628b48855909",
|
||||
"translatorType": 8,
|
||||
"label": "Crossref REST",
|
||||
"creator": "Martynas Bagdonas",
|
||||
"target": "",
|
||||
"minVersion": "5.0.0",
|
||||
"maxVersion": null,
|
||||
"priority": 90,
|
||||
"inRepository": true,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2018-06-16 12:00:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2018
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
// Based on CrossRef.js (by Simon Kornblith), which uses OpenURL API
|
||||
|
||||
// This translator uses the newer REST API
|
||||
// https://github.com/Crossref/rest-api-doc
|
||||
// https://github.com/Crossref/rest-api-doc/blob/master/api_format.md
|
||||
// REST API documentation not always reflect the actual API
|
||||
// and some fields are undocumented.
|
||||
// All Crossref item types can be retrieved at http://api.crossref.org/types
|
||||
|
||||
function removeUnsupportedMarkup(text) {
|
||||
let markupRE = /<(\/?)(\w+)[^<>]*>/gi;
|
||||
let supportedMarkup = ['i', 'b', 'sub', 'sup', 'sc'];
|
||||
let transformMarkup = {
|
||||
'scp': {
|
||||
open: '<span style="font-variant:small-caps;">',
|
||||
close: '</span>'
|
||||
}
|
||||
};
|
||||
|
||||
return text.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, '$1') // Remove CDATA markup
|
||||
.replace(markupRE, function (m, close, name) {
|
||||
name = name.toLowerCase();
|
||||
|
||||
if (supportedMarkup.includes(name)) {
|
||||
return (close ? '</' : '<') + name + '>';
|
||||
}
|
||||
|
||||
let newMarkup = transformMarkup[name.toLowerCase()];
|
||||
if (newMarkup) {
|
||||
return close ? newMarkup.close : newMarkup.open;
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
function fixAuthorCapitalization(string) {
|
||||
// Try to use capitalization function from Zotero Utilities,
|
||||
// because the current one doesn't support unicode names.
|
||||
// Can't fix this either because ZU.XRegExp.replace is
|
||||
// malfunctioning when calling from translators.
|
||||
if (ZU.capitalizeName) return ZU.capitalizeName(string);
|
||||
if (typeof string === "string" && string.toUpperCase() === string) {
|
||||
string = string.toLowerCase().replace(/\b[a-z]/g, function (m) {
|
||||
return m[0].toUpperCase();
|
||||
});
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
function parseCreators(result, item, typeOverrideMap) {
|
||||
let types = ['author', 'editor', 'chair', 'translator'];
|
||||
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
let type = types[i];
|
||||
|
||||
if (result[type]) {
|
||||
let creatorType = null;
|
||||
|
||||
if (typeOverrideMap && typeOverrideMap[type] !== undefined) {
|
||||
creatorType = typeOverrideMap[type];
|
||||
}
|
||||
else if (type === "author" || type === "editor" || type === "translator") {
|
||||
creatorType = type;
|
||||
}
|
||||
else {
|
||||
creatorType = "contributor";
|
||||
}
|
||||
|
||||
if (!creatorType) continue;
|
||||
|
||||
for (let j = 0; j < result[type].length; j++) {
|
||||
let creator = {};
|
||||
|
||||
creator.creatorType = creatorType;
|
||||
|
||||
if (result[type].name) { // Organization
|
||||
creator.fieldMode = 1;
|
||||
creator.lastName = result[type][j].name;
|
||||
}
|
||||
else {
|
||||
creator.firstName = fixAuthorCapitalization(result[type][j].given);
|
||||
creator.lastName = fixAuthorCapitalization(result[type][j].family);
|
||||
if (!creator.firstName) creator.fieldMode = 1;
|
||||
}
|
||||
|
||||
item.creators.push(creator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processCrossref(json) {
|
||||
json = JSON.parse(json);
|
||||
|
||||
for (let i = 0; i < json.message.items.length; i++) {
|
||||
let result = json.message.items[i];
|
||||
|
||||
let item = null;
|
||||
|
||||
// Journal article
|
||||
if (['journal-article'].includes(result.type)) {
|
||||
item = new Zotero.Item("journalArticle");
|
||||
if (result['container-title']) item.publicationTitle = result['container-title'][0];
|
||||
if (result['short-container-title']
|
||||
&& result['short-container-title'][0] !== result['container-title'][0]) {
|
||||
item.journalAbbreviation = result['short-container-title'][0];
|
||||
}
|
||||
item.volume = result.volume;
|
||||
item.issue = result.issue;
|
||||
if (result.ISBN) item.ISBN = result.ISBN[0];
|
||||
if (result.ISSN) item.ISSN = result.ISSN[0];
|
||||
}
|
||||
// Book
|
||||
else if (['book', 'book-series', 'book-set', 'book-track', 'monograph', 'reference-book']
|
||||
.includes(result.type)) {
|
||||
item = new Zotero.Item("book");
|
||||
item.publisher = result.publisher;
|
||||
item.place = result['publisher-location'];
|
||||
if (result.ISBN) item.ISBN = result.ISBN[0];
|
||||
}
|
||||
// Book section
|
||||
else if (['book-chapter', 'book-part', 'book-section', 'reference-entry']
|
||||
.includes(result.type)) {
|
||||
item = new Zotero.Item("bookSection");
|
||||
item.publisher = result.publisher;
|
||||
item.place = result['publisher-location'];
|
||||
if (result.ISBN) item.ISBN = result.ISBN[0];
|
||||
}
|
||||
// Report
|
||||
else if (['dataset', 'posted-content', 'report', 'report-series', 'standard']
|
||||
.includes(result.type)) {
|
||||
item = new Zotero.Item("report");
|
||||
item.institution = result.publisher;
|
||||
item.place = result['publisher-location'];
|
||||
item.seriesTitle = result['container-title'];
|
||||
}
|
||||
// Conference paper
|
||||
else if (['proceedings-article'].includes(result.type)) {
|
||||
item = new Zotero.Item("conferencePaper");
|
||||
item.proceedingsTitle = result['container-title'];
|
||||
item.publisher = result.publisher;
|
||||
if (result.event) {
|
||||
item.conferenceName = result.event.name;
|
||||
item.place = result.event.location;
|
||||
}
|
||||
if (result.ISBN) item.ISBN = result.ISBN[0];
|
||||
}
|
||||
// Thesis
|
||||
else if (['dissertation'].includes(result.type)) {
|
||||
item = new Zotero.Item("thesis");
|
||||
item.university = result.publisher;
|
||||
item.place = result['publisher-location'];
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
// edited-book, standard-series - ignore, because Crossref has zero results for this type
|
||||
// component, journal, journal-issue, journal-volume, other, proceedings,
|
||||
// proceedings-series, peer-review - ignore, because Zotero doesn't have equivalent item types.
|
||||
|
||||
item.abstractNote = result.abstract;
|
||||
|
||||
parseCreators(result, item);
|
||||
|
||||
|
||||
// Contains the earliest of: published-online, published-print, content-created
|
||||
let pubDate = result['issued'];
|
||||
|
||||
if (pubDate && pubDate['date-parts'][0]) {
|
||||
let year = pubDate['date-parts'][0][0];
|
||||
let month = pubDate['date-parts'][0][1];
|
||||
let day = pubDate['date-parts'][0][2];
|
||||
|
||||
if (year) {
|
||||
if (month) {
|
||||
if (day) {
|
||||
item.date = year + "-" + month + "-" + day;
|
||||
}
|
||||
else {
|
||||
item.date = month + "/" + year;
|
||||
}
|
||||
}
|
||||
else {
|
||||
item.date = year;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.pages = result.page;
|
||||
|
||||
if (result.DOI) {
|
||||
if (ZU.fieldIsValidForType('DOI', item.itemType)) {
|
||||
item.DOI = result.DOI;
|
||||
}
|
||||
// add DOI to extra for unsupprted items
|
||||
else {
|
||||
if (item.extra) {
|
||||
item.extra += '\nDOI: ' + result.DOI;
|
||||
}
|
||||
else {
|
||||
item.extra = 'DOI: ' + result.DOI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// result.URL is always http://dx.doi.org/..
|
||||
|
||||
if (result.link && result.link.URL) item.url = result.link.URL;
|
||||
|
||||
if (result.title && result.title[0]) {
|
||||
item.title = result.title[0];
|
||||
if (result.subtitle && result.subtitle[0]) {
|
||||
// Don't duplicate subtitle if it already exists in title
|
||||
if (item.title.toLowerCase().indexOf(result.subtitle[0].toLowerCase()) < 0) {
|
||||
item.title += ': ' + result.subtitle[0];
|
||||
}
|
||||
}
|
||||
item.title = removeUnsupportedMarkup(item.title);
|
||||
}
|
||||
|
||||
// Check if there are potential issues with character encoding and try to fix it
|
||||
// e.g. 10.1057/9780230391116.0016 (en dash in title is presented as <control><control>â)
|
||||
for (let field in item) {
|
||||
if (typeof item[field] !== 'string') continue;
|
||||
// Check for control characters that should never be in strings from Crossref
|
||||
if (/[\u007F-\u009F]/.test(item[field])) {
|
||||
item[field] = decodeURIComponent(escape(item[field]));
|
||||
}
|
||||
item[field] = ZU.unescapeHTML(item[field]);
|
||||
}
|
||||
item.libraryCatalog = 'Crossref';
|
||||
item.complete();
|
||||
}
|
||||
}
|
||||
|
||||
function detectSearch(item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function doSearch(item) {
|
||||
// Reduce network traffic by selecting only required fields
|
||||
let selectedFields = [
|
||||
'type',
|
||||
'container-title',
|
||||
'short-container-title',
|
||||
'volume',
|
||||
'issue',
|
||||
'ISBN',
|
||||
'ISSN',
|
||||
'publisher',
|
||||
'publisher-location',
|
||||
'event',
|
||||
'abstract',
|
||||
'issued',
|
||||
'page',
|
||||
'DOI',
|
||||
'link',
|
||||
'title',
|
||||
'subtitle',
|
||||
'author',
|
||||
'editor',
|
||||
'chair',
|
||||
'translator'
|
||||
];
|
||||
|
||||
let query = null;
|
||||
|
||||
if (item.DOI) {
|
||||
if (Array.isArray(item.DOI)) {
|
||||
query = '?filter=doi:' + item.DOI.map(x => ZU.cleanDOI(x)).filter(x => x).join(',doi:');
|
||||
} else {
|
||||
query = '?filter=doi:' + ZU.cleanDOI(item.DOI);
|
||||
}
|
||||
}
|
||||
else if (item.query) {
|
||||
query = '?query.bibliographic=' + encodeURIComponent(item.query);
|
||||
}
|
||||
else return;
|
||||
|
||||
query += '&select=' + selectedFields.join(',');
|
||||
|
||||
if (Z.getHiddenPref('CrossrefREST.email')) {
|
||||
query += '&mailto=' + Z.getHiddenPref('CrossrefREST.email');
|
||||
}
|
||||
|
||||
ZU.doGet('https://api.crossref.org/works/' + query, function (responseText) {
|
||||
processCrossref(responseText);
|
||||
});
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [];
|
||||
/** END TEST CASES **/
|
||||
9
DOAJ.js
9
DOAJ.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-07-09 20:47:02"
|
||||
"lastUpdated": "2025-08-08 16:00:53"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -79,6 +79,7 @@ function scrape(doc, url) {
|
|||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.abstractNote = text(doc, '.article-details__abstract');
|
||||
item.attachments = [];
|
||||
|
||||
for (let button of doc.querySelectorAll('.button')) {
|
||||
|
|
@ -140,7 +141,7 @@ var testCases = [
|
|||
"date": "2015/01/01",
|
||||
"DOI": "10.1371/journal.pone.0127427",
|
||||
"ISSN": "1932-6203",
|
||||
"abstractNote": "DOAJ is a community-curated online directory that indexes and provides access to high quality, open access, peer-reviewed journals.",
|
||||
"abstractNote": "BACKGROUND:Heritable factors are evidently involved in prostate cancer (PrCa) carcinogenesis, but currently, genetic markers are not routinely used in screening or diagnostics of the disease. More precise information is needed for making treatment decisions to distinguish aggressive cases from indolent disease, for which heritable factors could be a useful tool. The genetic makeup of PrCa has only recently begun to be unravelled through large-scale genome-wide association studies (GWAS). The thus far identified Single Nucleotide Polymorphisms (SNPs) explain, however, only a fraction of familial clustering. Moreover, the known risk SNPs are not associated with the clinical outcome of the disease, such as aggressive or metastasised disease, and therefore cannot be used to predict the prognosis. Annotating the SNPs with deep clinical data together with miRNA expression profiles can improve the understanding of the underlying mechanisms of different phenotypes of prostate cancer. RESULTS:In this study microRNA (miRNA) profiles were studied as potential biomarkers to predict the disease outcome. The study subjects were from Finnish high risk prostate cancer families. To identify potential biomarkers we combined a novel non-parametrical test with an importance measure provided from a Random Forest classifier. This combination delivered a set of nine miRNAs that was able to separate cases from controls. The detected miRNA expression profiles could predict the development of the disease years before the actual PrCa diagnosis or detect the existence of other cancers in the studied individuals. Furthermore, using an expression Quantitative Trait Loci (eQTL) analysis, regulatory SNPs for miRNA miR-483-3p that were also directly associated with PrCa were found. CONCLUSION:Based on our findings, we suggest that blood-based miRNA expression profiling can be used in the diagnosis and maybe even prognosis of the disease. In the future, miRNA profiling could possibly be used in targeted screening, together with Prostate Specific Antigene (PSA) testing, to identify men with an elevated PrCa risk.",
|
||||
"issue": "5",
|
||||
"language": "en",
|
||||
"libraryCatalog": "doaj.org",
|
||||
|
|
@ -214,10 +215,10 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021/07/01",
|
||||
"date": "2021/09/01",
|
||||
"DOI": "10.1136/bmjoq-2021-001396",
|
||||
"ISSN": "2399-6641",
|
||||
"abstractNote": "DOAJ is a community-curated online directory that indexes and provides access to high quality, open access, peer-reviewed journals.",
|
||||
"abstractNote": "Recent research demonstrates that transfusing whole blood (WB=red blood cells (RBC)+plasma+platelets) rather than just RBC (which is current National Health Service (NHS) practice) may improve outcomes for major trauma patients. As part of a programme to investigate provision of WB, NHS Blood and Transplant undertook a 2-year feasibility study to supply the Royal London Hospital (RLH) with (group O negative, ‘O neg’) leucodepleted red cell and plasma (LD-RCP) for transfusion of trauma patients with major haemorrhage in prehospital settings.Incidents requiring such prehospital transfusion occur randomly, with very high variation. Availability is critical, but O neg LD-RCP is a scarce resource and has a limited shelf life (14 days) after which it must be disposed of. The consequences of wastage are the opportunity cost of loss of overall treatment capacity across the NHS and reputational damage.The context was this feasibility study, set up to assess deliverability to RLH and subsequent wastage levels. Within this, we conducted a quality improvement project, which aimed to reduce the wastage of LD-RCP to no more than 8% (ie, 1 of the 12 units delivered per week).Over this 2-year period, we reduced wastage from a weekly average of 70%–27%. This was achieved over four improvement cycles. The largest improvement came from moving near-expiry LD-RCP to the emergency department (ED) for use with their trauma patients, with subsequent improvements from embedding use in ED as routine practice, introducing a dedicated LD-RCP delivery schedule (which increased the units ≤2 days old at delivery from 42% to 83%) and aligning this delivery schedule to cover two cycles of peak demand (Fridays and Saturdays).",
|
||||
"issue": "3",
|
||||
"language": "en",
|
||||
"libraryCatalog": "doaj.org",
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@
|
|||
"label": "DOI Content Negotiation",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "",
|
||||
"minVersion": "4.0.29.11",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 8,
|
||||
"browserSupport": "gcs",
|
||||
"lastUpdated": "2020-04-20 20:04:00"
|
||||
"lastUpdated": "2025-07-27 04:51:26"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -58,145 +57,296 @@ function filterQuery(items) {
|
|||
return dois;
|
||||
}
|
||||
|
||||
function doSearch(items) {
|
||||
var dois = filterQuery(items);
|
||||
if (!dois.length) return;
|
||||
processDOIs(dois);
|
||||
async function doSearch(items) {
|
||||
for (let doi of filterQuery(items)) {
|
||||
await processDOI(doi);
|
||||
}
|
||||
}
|
||||
|
||||
function processDOIs(dois) {
|
||||
var doi = dois.pop();
|
||||
// by content negotiation we asked for datacite or crossref format, or CSL JSON
|
||||
ZU.doGet('https://doi.org/' + encodeURIComponent(doi), function (text) {
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
Z.debug(text);
|
||||
|
||||
var trans = Zotero.loadTranslator('import');
|
||||
trans.setString(text);
|
||||
if (text.includes("<crossref")) {
|
||||
// Crossref Unixref
|
||||
trans.setTranslator('93514073-b541-4e02-9180-c36d2f3bb401');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (Crossref)";
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
}
|
||||
else if (text.includes("http://datacite.org/schema")
|
||||
// TEMP
|
||||
// https://github.com/zotero/translators/issues/2018#issuecomment-616491407
|
||||
|| text.includes('"agency": "DataCite"')
|
||||
|| text.includes('"providerId": ')) {
|
||||
// Datacite JSON
|
||||
trans.setTranslator('b5b5808b-1c61-473d-9a02-e1f5ba7b8eef');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (Datacite)";
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
}
|
||||
else {
|
||||
// use CSL JSON translator
|
||||
trans.setTranslator('bc03b4fe-436d-4a1f-ba59-de4d2d7a63f7');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (CSL JSON)";
|
||||
// check if there are potential issues with character encoding and try to fix it
|
||||
// e.g. 10.1057/9780230391116.0016 (en dash in title is presented as escaped unicode)
|
||||
for (var field in item) {
|
||||
if (typeof item[field] != 'string') continue;
|
||||
// check for control characters that should never be in strings from CrossRef
|
||||
if (/[\u007F-\u009F]/.test(item[field])) {
|
||||
var escaped = item[field].replace(/[^0-9A-Za-z ]/g, function (c) {
|
||||
return "%" + c.charCodeAt(0).toString(16);
|
||||
});
|
||||
item[field] = decodeURIComponent(escaped);
|
||||
}
|
||||
async function processDOI(doi) {
|
||||
// TEMP: Use Crossref REST for Crossref DOIs during Crossref outage
|
||||
let currentDate = new Date();
|
||||
// Outage: 17 May 2025, 14:00–15:00 UTC
|
||||
// Start 1 hour before (13:00 UTC) and end 2 hours after (17:00 UTC)
|
||||
// TEMP for May 22 outage
|
||||
let startDate = new Date(Date.UTC(2025, 4, 22, 00, 0, 0));
|
||||
let endDate = new Date(Date.UTC(2025, 4, 24, 0, 0, 0));
|
||||
|
||||
// At least for now, always use REST API for Crossref DOIs
|
||||
// due to better reliability
|
||||
// TEMP: Except don't, because some REST API requests are really slow
|
||||
// https://forums.zotero.org/discussion/comment/496121/#Comment_496121
|
||||
//if (currentDate >= startDate && currentDate <= endDate) {
|
||||
if (false) {
|
||||
try {
|
||||
let raJSON = await requestJSON(
|
||||
`https://doi.org/ra/${encodeURIComponent(doi)}`
|
||||
);
|
||||
if (raJSON.length) {
|
||||
let ra = raJSON[0].RA;
|
||||
if (ra == 'Crossref') {
|
||||
let translate = Zotero.loadTranslator('search');
|
||||
// Crossref REST
|
||||
translate.setTranslator("0a61e167-de9a-4f93-a68a-628b48855909");
|
||||
let item = { itemType: "journalArticle", DOI: doi };
|
||||
translate.setSearch(item);
|
||||
translate.translate();
|
||||
return;
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
trans.translate();
|
||||
}
|
||||
}
|
||||
}, function () {
|
||||
if (dois.length) processDOIs(dois);
|
||||
}, undefined, { Accept: "application/vnd.datacite.datacite+json, application/vnd.crossref.unixref+xml, application/vnd.citationstyles.csl+json" });
|
||||
catch (e) {
|
||||
Z.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
let response = await requestText(
|
||||
`https://doi.org/${encodeURIComponent(doi)}`,
|
||||
{ headers: { Accept: "application/vnd.datacite.datacite+json, application/vnd.crossref.unixref+xml, application/vnd.citationstyles.csl+json" } }
|
||||
);
|
||||
// by content negotiation we asked for datacite or crossref format, or CSL JSON
|
||||
if (!response) return;
|
||||
Z.debug(response);
|
||||
|
||||
let trans = Zotero.loadTranslator('import');
|
||||
trans.setString(response);
|
||||
|
||||
if (response.includes("<crossref")) {
|
||||
// Crossref Unixref
|
||||
trans.setTranslator('93514073-b541-4e02-9180-c36d2f3bb401');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (Crossref)";
|
||||
item.complete();
|
||||
});
|
||||
}
|
||||
else if (response.includes("http://datacite.org/schema")
|
||||
// TEMP
|
||||
// https://github.com/zotero/translators/issues/2018#issuecomment-616491407
|
||||
|| response.includes('"agency": "DataCite"')
|
||||
|| response.includes('"providerId": ')) {
|
||||
// Datacite JSON
|
||||
trans.setTranslator('b5b5808b-1c61-473d-9a02-e1f5ba7b8eef');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (Datacite)";
|
||||
item.complete();
|
||||
});
|
||||
}
|
||||
else {
|
||||
// use CSL JSON translator
|
||||
trans.setTranslator('bc03b4fe-436d-4a1f-ba59-de4d2d7a63f7');
|
||||
trans.setHandler('itemDone', function (obj, item) {
|
||||
item.libraryCatalog = "DOI.org (CSL JSON)";
|
||||
// check if there are potential issues with character encoding and try to fix it
|
||||
// e.g. 10.1057/9780230391116.0016 (en dash in title is presented as escaped unicode)
|
||||
for (var field in item) {
|
||||
if (typeof item[field] != 'string') continue;
|
||||
// check for control characters that should never be in strings from CrossRef
|
||||
if (/[\u007F-\u009F]/.test(item[field])) {
|
||||
var escaped = item[field].replace(/[^0-9A-Za-z ]/g, function (c) {
|
||||
return "%" + c.charCodeAt(0).toString(16);
|
||||
});
|
||||
item[field] = decodeURIComponent(escaped);
|
||||
}
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
}
|
||||
|
||||
await trans.translate();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"DOI": "10.12763/ONA1045"
|
||||
},
|
||||
"items": [{
|
||||
"itemType": "journalArticle",
|
||||
"url": "http://docnum.univ-lorraine.fr/pulsar/RCR_543952102_NA1045.pdf",
|
||||
"pages": "39.79 MB, 402 pages",
|
||||
"date": "1734",
|
||||
"DOI": "10.12763/ona1045",
|
||||
"accessDate": "2019-02-02T02:31:57Z",
|
||||
"libraryCatalog": "DOI.org (Datacite)",
|
||||
"language": "fre",
|
||||
"title": "Code criminel de l'empereur Charles V vulgairement appellé la Caroline contenant les loix qui sont suivies dans les jurisdictions criminelles de l'Empire et à l'usage des conseils de guerre des troupes suisses.",
|
||||
"creators": [{
|
||||
"firstName": "",
|
||||
"lastName": "Heiliges Römisches Reich Deutscher Nation",
|
||||
"creatorType": "author"
|
||||
var testCases = [
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"DOI": "10.12763/ONA1045"
|
||||
},
|
||||
{
|
||||
"firstName": "Franz Adam. Éditeur Scientifique",
|
||||
"lastName": "Vogel",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Simon, Claude (167 ?-1752) Éditeur",
|
||||
"lastName": "Commercial",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "",
|
||||
"lastName": "Université De Lorraine-Direction De La Documentation Et De L'Edition",
|
||||
"creatorType": "contributor"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Droit"
|
||||
],
|
||||
"relations": [],
|
||||
"attachments": [],
|
||||
"notes": [
|
||||
"<h2>Other</h2>\nLe code est accompagné de commentaires de F. A. Vogel, qui signe l'épitre dédicatoire<h2>Other</h2>\nReliure 18è siècle<h2>Other</h2>\nEx-libris manuscrit \"Ex libris Dufour\""
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Code criminel de l'empereur Charles V vulgairement appellé la Caroline contenant les loix qui sont suivies dans les jurisdictions criminelles de l'Empire et à l'usage des conseils de guerre des troupes suisses.",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Heiliges Römisches Reich Deutscher Nation",
|
||||
"creatorType": "author",
|
||||
"fieldMode": 1
|
||||
},
|
||||
{
|
||||
"lastName": "Vogel",
|
||||
"firstName": "Franz Adam. Éditeur Scientifique",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"firstName": "Simon, Claude (167 ?-1752) Éditeur",
|
||||
"lastName": "Commercial",
|
||||
"creatorType": "contributor"
|
||||
},
|
||||
{
|
||||
"lastName": "Université De Lorraine-Direction De La Documentation Et De L'Edition",
|
||||
"creatorType": "contributor",
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "1734",
|
||||
"DOI": "10.12763/ONA1045",
|
||||
"language": "fr",
|
||||
"libraryCatalog": "DOI.org (Datacite)",
|
||||
"pages": "39.79 MB, 402 pages",
|
||||
"url": "http://docnum.univ-lorraine.fr/pulsar/RCR_543952102_NA1045.pdf",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Droit"
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"note": "<h2>Other</h2>\nLe code est accompagné de commentaires de F. A. Vogel, qui signe l'épitre dédicatoire<h2>Other</h2>\nReliure 18è siècle<h2>Other</h2>\nEx-libris manuscrit \"Ex libris Dufour\""
|
||||
}
|
||||
],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"DOI": "10.7336/academicus.2014.09.05"
|
||||
},
|
||||
"items": [{
|
||||
"itemType": "journalArticle",
|
||||
"url": "http://academicus.edu.al/?subpage=volumes&nr=9",
|
||||
"volume": "9",
|
||||
"pages": "69-78",
|
||||
"publicationTitle": "Academicus International Scientific Journal",
|
||||
"ISSN": "20793715",
|
||||
"date": "01/2014",
|
||||
"DOI": "10.7336/academicus.2014.09.05",
|
||||
"accessDate": "2019-02-02T03:28:48Z",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"title": "Second world war, communism and post-communism in Albania, an equilateral triangle of a tragic trans-Adriatic story. The Eftimiadi’s Saga",
|
||||
"creators": [{
|
||||
"firstName": "Muner",
|
||||
"lastName": "Paolo",
|
||||
"creatorType": "author"
|
||||
}],
|
||||
"tags": [],
|
||||
"relations": [],
|
||||
"attachments": [],
|
||||
"notes": []
|
||||
}]
|
||||
}
|
||||
{
|
||||
"type": "search",
|
||||
"input": {
|
||||
"DOI": "10.7336/academicus.2014.09.05"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Second world war, communism and post-communism in Albania, an equilateral triangle of a tragic trans-Adriatic story. The Eftimiadi’s Saga",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Paolo",
|
||||
"lastName": "Muner"
|
||||
}
|
||||
],
|
||||
"date": "01/2014",
|
||||
"DOI": "10.7336/academicus.2014.09.05",
|
||||
"ISSN": "20793715, 23091088",
|
||||
"abstractNote": "The complicated, troubled and tragic events of a wealthy family from Vlorë, Albania, which a century ago expanded its business to Italy, in Brindisi and Trieste, and whose grand land tenures and financial properties in Albania were nationalized by Communism after the Second World War. Hence the life-long solitary and hopeless fight of the last heir of the family to reconquer his patrimony that had been nationalized by Communism. Such properties would have been endowed to a planned foundation, which aims at perpetuating the memory of his brother, who was active in the resistance movement during the war and therefore hung by the Germans. His main institutional purpose is to help students from the Vlorë area to attend the University of Trieste. The paper is a travel in time through history, sociology and the consolidation of a state’s fundamentals, by trying to read the past aiming to understand the presence and save the future. The paper highlights the need to consider past models of social solidarity meanwhile renewing the actual one. This as a re-establishment of rule and understanding, a strategy to cope with pressures to renegotiate the social contract, as a universal need, by considering the past’s experiences as a firm base for successful social interaction. All this, inside a story which in the first look seems to be too personal and narrow, meanwhile it highlights the present and the past in a natural organic connection, dedicated to a nation in continuous struggle for its social reconstruction.",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "69-78",
|
||||
"publicationTitle": "Academicus International Scientific Journal",
|
||||
"rights": "https://creativecommons.org/licenses/by-nc-nd/4.0/",
|
||||
"url": "https://www.medra.org/servlet/MREngine?hdl=10.7336/academicus.2014.09.05",
|
||||
"volume": "9",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "search",
|
||||
"input": [
|
||||
{
|
||||
"DOI": "10.5555/12345678"
|
||||
},
|
||||
{
|
||||
"DOI": "10.1109/TPS.1987.4316723"
|
||||
},
|
||||
{
|
||||
"DOI": "10.5555/666655554444"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Toward a Unified Theory of High-Energy Metaphysics: Silly String Theory",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Josiah",
|
||||
"lastName": "Carberry"
|
||||
},
|
||||
{
|
||||
"creatorType": "contributor",
|
||||
"fieldMode": 1,
|
||||
"lastName": "Friends of Josiah Carberry"
|
||||
}
|
||||
],
|
||||
"date": "2008-08-14",
|
||||
"DOI": "10.5555/12345678",
|
||||
"ISSN": "0264-3561",
|
||||
"abstractNote": "The characteristic theme of the works of Stone is the bridge between culture and society. Several narratives concerning the fatal !aw, and subsequent dialectic, of semioticist class may be found. Thus, Debord uses the term ‘the subtextual paradigm of consensus’ to denote a cultural paradox. The subject is interpolated into a neocultural discourse that includes sexuality as a totality. But Marx’s critique of prepatriarchialist nihilism states that consciousness is capable of signi\"cance. The main theme of Dietrich’s[1]model of cultural discourse is not construction, but neoconstruction. Thus, any number of narratives concerning the textual paradigm of narrative exist. Pretextual cultural theory suggests that context must come from the collective unconscious.",
|
||||
"issue": "11",
|
||||
"journalAbbreviation": "Journal of Psychoceramics",
|
||||
"language": "en",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "1-3",
|
||||
"publicationTitle": "Journal of Psychoceramics",
|
||||
"shortTitle": "Toward a Unified Theory of High-Energy Metaphysics",
|
||||
"url": "https://ojs33.crossref.publicknowledgeproject.org/index.php/test/article/view/2",
|
||||
"volume": "5",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
},
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Bulk and Surface Plasmons in Artificially Structured Materials",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "John J.",
|
||||
"lastName": "Quinn"
|
||||
},
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Josiah S.",
|
||||
"lastName": "Carberry"
|
||||
}
|
||||
],
|
||||
"date": "1987",
|
||||
"DOI": "10.1109/TPS.1987.4316723",
|
||||
"ISSN": "0093-3813",
|
||||
"issue": "4",
|
||||
"journalAbbreviation": "IEEE Trans. Plasma Sci.",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "394-410",
|
||||
"publicationTitle": "IEEE Transactions on Plasma Science",
|
||||
"rights": "https://ieeexplore.ieee.org/Xplorehelp/downloads/license-information/IEEE.html",
|
||||
"url": "http://ieeexplore.ieee.org/document/4316723/",
|
||||
"volume": "15",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
},
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "The Memory Bus Considered Harmful",
|
||||
"creators": [
|
||||
{
|
||||
"creatorType": "author",
|
||||
"firstName": "Josiah",
|
||||
"lastName": "Carberry"
|
||||
}
|
||||
],
|
||||
"date": "2012-10-11",
|
||||
"DOI": "10.5555/666655554444",
|
||||
"ISSN": "0264-3561",
|
||||
"issue": "11",
|
||||
"journalAbbreviation": "Journal of Psychoceramics",
|
||||
"language": "en",
|
||||
"libraryCatalog": "DOI.org (Crossref)",
|
||||
"pages": "1-3",
|
||||
"publicationTitle": "Journal of Psychoceramics",
|
||||
"url": "https://ojs33.crossref.publicknowledgeproject.org/index.php/test/article/view/8",
|
||||
"volume": "9",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
24
DOI.js
24
DOI.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-03-12 01:46:07"
|
||||
"lastUpdated": "2024-06-04 14:34:03"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -151,7 +151,7 @@ function detectWeb(doc, url) {
|
|||
return "journalArticle"; // A decent guess
|
||||
}
|
||||
|
||||
function retrieveDOIs(doiOrDOIs) {
|
||||
async function retrieveDOIs(doiOrDOIs) {
|
||||
let showSelect = Array.isArray(doiOrDOIs);
|
||||
let dois = showSelect ? doiOrDOIs : [doiOrDOIs];
|
||||
let items = {};
|
||||
|
|
@ -214,14 +214,19 @@ function retrieveDOIs(doiOrDOIs) {
|
|||
// Don't throw on error
|
||||
translate.setHandler("error", function () {});
|
||||
|
||||
translate.translate();
|
||||
try {
|
||||
await translate.translate();
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(`Failed to resolve DOI '${doi}': ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
async function doWeb(doc, url) {
|
||||
let doiOrDOIs = getDOIs(doc, url);
|
||||
Z.debug(doiOrDOIs);
|
||||
retrieveDOIs(doiOrDOIs);
|
||||
await retrieveDOIs(doiOrDOIs);
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
|
|
@ -278,9 +283,10 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/BEJTMI",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "document",
|
||||
"itemType": "dataset",
|
||||
"title": "Transfer of 50 thousand improved genetically improved farmed tilapia (GIFT) fry to Nigeria",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -296,14 +302,14 @@ var testCases = [
|
|||
{
|
||||
"lastName": "WorldFish",
|
||||
"creatorType": "contributor",
|
||||
"fieldMode": true
|
||||
"fieldMode": 1
|
||||
}
|
||||
],
|
||||
"date": "2023",
|
||||
"DOI": "10.7910/DVN/BEJTMI",
|
||||
"abstractNote": "The data contains the list of female broodstock that produced improved GIFT fry sent to Nigeria in three batches in 2022",
|
||||
"extra": "Type: dataset\nDOI: 10.7910/DVN/BEJTMI",
|
||||
"libraryCatalog": "DOI.org (Datacite)",
|
||||
"publisher": "Harvard Dataverse",
|
||||
"repository": "Harvard Dataverse",
|
||||
"url": "https://dataverse.harvard.edu/citation?persistentId=doi:10.7910/DVN/BEJTMI",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -2,61 +2,64 @@
|
|||
"translatorID": "0526c18d-8dc8-40c9-8314-399e0b743a4d",
|
||||
"label": "Dagstuhl Research Online Publication Server",
|
||||
"creator": "Philipp Zumstein",
|
||||
"target": "^https?://(www\\.)?drops\\.dagstuhl\\.de/opus/",
|
||||
"minVersion": "3.0",
|
||||
"target": "^https?://(www\\.)?drops\\.dagstuhl\\.de/",
|
||||
"minVersion": "6.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2016-08-23 06:54:08"
|
||||
"lastUpdated": "2025-07-19 19:20:18"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2016 Philipp Zumstein
|
||||
|
||||
|
||||
Copyright © 2016-2025 Philipp Zumstein and Zotero 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 detectWeb(doc, url) {
|
||||
if (url.indexOf('source_opus')>-1 || url.indexOf('volltexte')>-1) {
|
||||
var bibtexEntry = ZU.xpathText(doc, '//pre/tt');
|
||||
if (bibtexEntry.indexOf("@InCollection")>-1) {
|
||||
if (url.includes('/entities/document/')) {
|
||||
let bibtexEntry = text(doc, 'pre.bibtex');
|
||||
if (bibtexEntry.includes("@InCollection")) {
|
||||
return "bookSection";
|
||||
}
|
||||
if (bibtexEntry.indexOf("@Article")>-1) {
|
||||
if (bibtexEntry.includes("@Article")) {
|
||||
return "journalArticle";
|
||||
}
|
||||
return "conferencePaper";
|
||||
} 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 = ZU.xpath(doc, '//b/a[contains(@href, "source_opus")]|//td/a[contains(@href, "source_opus")]');//
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].textContent);
|
||||
var rows = doc.querySelectorAll('a[href*="/entities/document/"]');
|
||||
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;
|
||||
|
|
@ -65,74 +68,73 @@ function getSearchResults(doc, checkOnly) {
|
|||
return found ? items : false;
|
||||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
async 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);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
var bibtexEntry = ZU.xpathText(doc, '//pre/tt');
|
||||
//Z.debug(bibtexEntry);
|
||||
var pdfurl = ZU.xpathText(doc, '//td//a[contains(@href, "pdf")]/@href');
|
||||
async function scrape(doc, _url = doc.location.href) {
|
||||
let bibtexEntry = text(doc, 'pre.bibtex');
|
||||
let pdfUrl = attr(doc, 'meta[name="citation_pdf_url"]', 'content');
|
||||
// One more try in case the meta tag didn't work, there are other tags with the PDF link
|
||||
if (!pdfUrl) {
|
||||
Z.debug("PDF URL extraction from the meta tag failed, trying other sources.");
|
||||
pdfUrl = attr(doc, 'section.files a[href$=".pdf"]', 'href');
|
||||
}
|
||||
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("9cb70025-a888-4a29-a210-93ec52da40d4");
|
||||
translator.setString(bibtexEntry);
|
||||
translator.setHandler("itemDone", function(obj, item) {
|
||||
|
||||
//if a note is just a list of keywords, then save them as tags
|
||||
//and delete this note
|
||||
for (var i=0; i<item.notes.length; i++) {
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
// If a note is just a list of keywords, then save them as tags
|
||||
// and delete this note
|
||||
for (var i = 0; i < item.notes.length; i++) {
|
||||
var note = item.notes[i].note;
|
||||
if (note.indexOf('Keywords:')>-1) {
|
||||
if (note.includes('Keywords:')) {
|
||||
note = note.replace('<p>', '').replace('</p>', '').replace('Keywords:', '');
|
||||
var keywords = note.split(',');
|
||||
for (var j=0; j<keywords.length; j++) {
|
||||
for (var j = 0; j < keywords.length; j++) {
|
||||
item.tags.push(keywords[j].trim());
|
||||
}
|
||||
item.notes.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
|
||||
if (pdfurl) {
|
||||
|
||||
if (pdfUrl) {
|
||||
item.attachments.push({
|
||||
url: pdfurl,
|
||||
url: pdfUrl,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
}/** BEGIN TEST CASES **/
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://drops.dagstuhl.de/opus/frontdoor.php?source_opus=4958",
|
||||
"url": "https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.STACS.2015.1",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Overcoming Intractability in Unsupervised Learning (Invited Talk)",
|
||||
"title": "Overcoming Intractability in Unsupervised Learning",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sanjeev",
|
||||
|
|
@ -153,18 +155,19 @@ var testCases = [
|
|||
"date": "2015",
|
||||
"DOI": "10.4230/LIPIcs.STACS.2015.1",
|
||||
"ISBN": "9783939897781",
|
||||
"itemID": "arora:LIPIcs:2015:4958",
|
||||
"itemID": "arora:LIPIcs.STACS.2015.1",
|
||||
"libraryCatalog": "Dagstuhl Research Online Publication Server",
|
||||
"pages": "1–1",
|
||||
"place": "Dagstuhl, Germany",
|
||||
"proceedingsTitle": "32nd International Symposium on Theoretical Aspects of Computer Science (STACS 2015)",
|
||||
"publisher": "Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik",
|
||||
"publisher": "Schloss Dagstuhl – Leibniz-Zentrum für Informatik",
|
||||
"series": "Leibniz International Proceedings in Informatics (LIPIcs)",
|
||||
"url": "http://drops.dagstuhl.de/opus/volltexte/2015/4958",
|
||||
"url": "https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.STACS.2015.1",
|
||||
"volume": "30",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -184,17 +187,17 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://drops.dagstuhl.de/opus/portals/lipics/index.php?semnr=15001",
|
||||
"url": "https://drops.dagstuhl.de/entities/volume/LIPIcs-volume-30",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://drops.dagstuhl.de/opus/ergebnis.php?wer=opus&suchart=teil&Lines_Displayed=10&sort=o.date_year+DESC%2C+o.title&suchfeld1=freitext&suchwert1=&opt1=AND&opt2=AND&suchfeld3=date_year&suchwert3=&startindex=0&page=0&dir=2&suche=&suchfeld2=oa.person&suchwert2=Hauzar%2C%20David",
|
||||
"url": "https://drops.dagstuhl.de/search?term=Hauzar%2C%20David",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://drops.dagstuhl.de/opus/volltexte/2016/5933/",
|
||||
"url": "https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.SoCG.2016.41",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
|
|
@ -239,18 +242,19 @@ var testCases = [
|
|||
"date": "2016",
|
||||
"DOI": "10.4230/LIPIcs.SoCG.2016.41",
|
||||
"ISBN": "9783959770095",
|
||||
"itemID": "geyer_et_al:LIPIcs:2016:5933",
|
||||
"itemID": "geyer_et_al:LIPIcs.SoCG.2016.41",
|
||||
"libraryCatalog": "Dagstuhl Research Online Publication Server",
|
||||
"pages": "41:1–41:15",
|
||||
"place": "Dagstuhl, Germany",
|
||||
"proceedingsTitle": "32nd International Symposium on Computational Geometry (SoCG 2016)",
|
||||
"publisher": "Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik",
|
||||
"publisher": "Schloss Dagstuhl – Leibniz-Zentrum für Informatik",
|
||||
"series": "Leibniz International Proceedings in Informatics (LIPIcs)",
|
||||
"url": "http://drops.dagstuhl.de/opus/volltexte/2016/5933",
|
||||
"url": "https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.SoCG.2016.41",
|
||||
"volume": "51",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -269,4 +273,4 @@ var testCases = [
|
|||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
650
Datacite JSON.js
650
Datacite JSON.js
File diff suppressed because one or more lines are too long
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"translatorID": "2a5dc3ed-ee5e-4bfb-baad-36ae007e40ce",
|
||||
"label": "De Gruyter",
|
||||
"label": "De Gruyter Brill",
|
||||
"creator": "Abe Jellinek",
|
||||
"target": "^https?://www\\.degruyter\\.com/",
|
||||
"target": "^https?://www\\.degruyterbrill\\.com/",
|
||||
"minVersion": "2.1.9",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-09-02 21:52:03"
|
||||
"lastUpdated": "2025-05-13 13:34:42"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -37,23 +37,20 @@
|
|||
|
||||
|
||||
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_inbook_title"]', 'content');
|
||||
if (!bookTitle || title == bookTitle) {
|
||||
return "book";
|
||||
let pageCategory = doc.body.getAttribute('data-pagecategory');
|
||||
switch (pageCategory) {
|
||||
case 'book':
|
||||
return 'book';
|
||||
case 'chapter':
|
||||
return 'bookSection';
|
||||
case 'article':
|
||||
return 'journalArticle';
|
||||
case 'search':
|
||||
case 'journal':
|
||||
default:
|
||||
if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
else {
|
||||
return "bookSection";
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "journalArticle";
|
||||
}
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -62,6 +59,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('.resultTitle > a[href*="/document/"]');
|
||||
if (!rows.length) {
|
||||
rows = doc.querySelectorAll('li a[href*="/document/"][data-doi]');
|
||||
}
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
|
|
@ -127,18 +127,38 @@ function scrape(doc, url) {
|
|||
delete item.bookTitle;
|
||||
}
|
||||
|
||||
if (item.bookTitle && !item.bookTitle.includes(': ')) {
|
||||
if (item.itemType == 'bookSection') {
|
||||
delete item.publicationTitle;
|
||||
delete item.abstractNote;
|
||||
delete item.rights; // AI training disclaimer!
|
||||
|
||||
let risURL = attr(doc, 'a[title="Download in RIS format"]', 'href');
|
||||
if (!risURL) {
|
||||
risURL = url.replace(/\/html([?#].*)$/, '/machineReadableCitation/RIS');
|
||||
}
|
||||
|
||||
ZU.doGet(risURL, function (risText) {
|
||||
let bookTitle = risText.match(/^\s*T1\s*-\s*(.*)$/m);
|
||||
if (bookTitle) {
|
||||
item.bookTitle = bookTitle[1];
|
||||
// De Gruyter uses TI for the container title and T2 for the subtitle
|
||||
// Seems nonstandard! So we'll just handle it here
|
||||
let titleMatch = risText.match(/^\s*TI\s*-\s*(.+)/m);
|
||||
let subtitleMatch = risText.match(/^\s*T2\s*-\s*(.+)/m);
|
||||
if (titleMatch) {
|
||||
item.bookTitle = titleMatch[1];
|
||||
if (subtitleMatch) {
|
||||
item.bookTitle = item.bookTitle.trim() + ': ' + subtitleMatch[1];
|
||||
}
|
||||
}
|
||||
item.complete();
|
||||
|
||||
let translator = Zotero.loadTranslator('import');
|
||||
translator.setTranslator('32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7');
|
||||
translator.setString(risText);
|
||||
translator.setHandler('itemDone', (_obj, risItem) => {
|
||||
if (!item.creators.some(c => c.creatorType == 'editor')) {
|
||||
item.creators.push(...risItem.creators.filter(c => c.creatorType == 'editor'));
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
@ -147,7 +167,17 @@ function scrape(doc, url) {
|
|||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
if (detectWeb(doc, url) == 'bookSection') {
|
||||
let detectedType = detectWeb(doc, url);
|
||||
if (detectedType == 'book') {
|
||||
// Delete citation_inbook_title if this is actually a book, not a book section
|
||||
// Prevents EM from mis-detecting as a bookSection in a way that even setting
|
||||
// trans.itemType can't override
|
||||
let bookTitleMeta = doc.querySelector('meta[name="citation_inbook_title"]');
|
||||
if (bookTitleMeta) {
|
||||
bookTitleMeta.remove();
|
||||
}
|
||||
}
|
||||
else if (detectedType == 'bookSection') {
|
||||
trans.itemType = 'bookSection';
|
||||
}
|
||||
trans.addCustomFields({
|
||||
|
|
@ -164,7 +194,7 @@ function scrape(doc, url) {
|
|||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/vfzg-2021-0028/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/vfzg-2021-0028/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -181,12 +211,13 @@ var testCases = [
|
|||
"ISSN": "2196-7121",
|
||||
"abstractNote": "Die Geschichte homosexueller Menschen im modernen Deutschland besteht nicht nur aus Verfolgung und Diskriminierung, obschon sie oft als solche erinnert wird. Wohl haben homosexuelle Männer unter massiver Verfolgung gelitten, und auch lesbische Frauen waren vielen Diskriminierungen ausgesetzt. Doch die Geschichte der letzten 200 Jahre weist nicht nur jene Transformation im Umgang mit Homosexualität auf, die ab den 1990er Jahren zur Gleichberechtigung führte, sondern mehrere, inhaltlich sehr verschiedene Umbrüche. Wir haben es weder mit einem Kontinuum der Repression noch mit einer linearen Emanzipationsgeschichte zu tun, sondern mit einer höchst widersprüchlichen langfristigen Entwicklung.",
|
||||
"issue": "3",
|
||||
"language": "de",
|
||||
"libraryCatalog": "www.degruyter.com",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "377-414",
|
||||
"publicationTitle": "Vierteljahrshefte für Zeitgeschichte",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"shortTitle": "Homosexuelle im modernen Deutschland",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/vfzg-2021-0028/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/vfzg-2021-0028/html",
|
||||
"volume": "69",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -218,7 +249,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/document/doi/10.3138/9781487518806/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487518806/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
|
|
@ -230,14 +261,15 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-08-25",
|
||||
"date": "2021-07-30",
|
||||
"ISBN": "9781487518806",
|
||||
"abstractNote": "Bringing together themes in the history of art, punishment, religion, and the history of medicine, Picturing Punishment provides new insights into the wider importance of the criminal to civic life.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyter.com",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"publisher": "University of Toronto Press",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"shortTitle": "Picturing Punishment",
|
||||
"url": "https://www.degruyter.com/document/doi/10.3138/9781487518806/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487518806/html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -295,7 +327,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/document/doi/10.3138/9781487518806-008/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487518806-008/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
|
|
@ -307,16 +339,15 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-08-25",
|
||||
"date": "2021-07-30",
|
||||
"ISBN": "9781487518806",
|
||||
"abstractNote": "5 Serving the Public Good: Reform, Prestige, and the Productive Criminal Body in Amsterdam was published in Picturing Punishment on page 135.",
|
||||
"bookTitle": "Picturing Punishment: The Spectacle and Material Afterlife of the Criminal Body in the Dutch Republic",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyter.com",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "135-157",
|
||||
"publisher": "University of Toronto Press",
|
||||
"shortTitle": "5 Serving the Public Good",
|
||||
"url": "https://www.degruyter.com/document/doi/10.3138/9781487518806-008/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487518806-008/html",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
|
|
@ -326,7 +357,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -359,10 +390,11 @@ var testCases = [
|
|||
"abstractNote": "C 17 H 14 FNO 2 , monoclinic, P 2 1 / c (no. 15), a = 7.3840(6) Å, b = 10.9208(8) Å, c = 16.7006(15) Å, β = 101.032(9)°, V = 1321.84(19) Å 3 , Z = 4, R gt ( F ) = 0.0589, wR ref ( F 2 ) = 0.1561, T = 100.00(18) K.",
|
||||
"issue": "5",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyter.com",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "1101-1103",
|
||||
"publicationTitle": "Zeitschrift für Kristallographie - New Crystal Structures",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"volume": "236",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -378,7 +410,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -411,10 +443,11 @@ var testCases = [
|
|||
"abstractNote": "C 17 H 14 FNO 2 , monoclinic, P 2 1 / c (no. 15), a = 7.3840(6) Å, b = 10.9208(8) Å, c = 16.7006(15) Å, β = 101.032(9)°, V = 1321.84(19) Å 3 , Z = 4, R gt ( F ) = 0.0589, wR ref ( F 2 ) = 0.1561, T = 100.00(18) K.",
|
||||
"issue": "5",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyter.com",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "1101-1103",
|
||||
"publicationTitle": "Zeitschrift für Kristallographie - New Crystal Structures",
|
||||
"url": "https://www.degruyter.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/ncrs-2021-0236/html",
|
||||
"volume": "236",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -431,12 +464,211 @@ var testCases = [
|
|||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/search?query=test",
|
||||
"defer": true,
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyter.com/journal/key/mt/html",
|
||||
"url": "https://www.degruyterbrill.com/journal/key/mt/67/5/html",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/9783110773712-010/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "10 Skaldic Poetry – Encrypted Communication",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jon Gunnar",
|
||||
"lastName": "Jørgensen",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Engh",
|
||||
"firstName": "Line Cecilie",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "Gullbekk",
|
||||
"firstName": "Svein Harald",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "Orning",
|
||||
"firstName": "Hans Jacob",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2024-08-19",
|
||||
"ISBN": "9783110773712",
|
||||
"bookTitle": "Standardization in the Middle Ages: Volume 1: The North",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "229-250",
|
||||
"publisher": "De Gruyter",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/9783110773712-010/html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487552978/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Freedoms of Speech: Anthropological Perspectives on Language, Ethics, and Power",
|
||||
"creators": [],
|
||||
"date": "2024-12-16",
|
||||
"ISBN": "9781487552978",
|
||||
"abstractNote": "This collection brings together leading anthropologists and fresh new voices in the discipline to consider freedoms of speech with a wide comparative lens.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"publisher": "University of Toronto Press",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"shortTitle": "Freedoms of Speech",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.3138/9781487552978/html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "censors"
|
||||
},
|
||||
{
|
||||
"tag": "censorship"
|
||||
},
|
||||
{
|
||||
"tag": "defamation"
|
||||
},
|
||||
{
|
||||
"tag": "dissent"
|
||||
},
|
||||
{
|
||||
"tag": "ethics"
|
||||
},
|
||||
{
|
||||
"tag": "fascism"
|
||||
},
|
||||
{
|
||||
"tag": "free speech Islam"
|
||||
},
|
||||
{
|
||||
"tag": "free speech Russia"
|
||||
},
|
||||
{
|
||||
"tag": "freedom of speech"
|
||||
},
|
||||
{
|
||||
"tag": "human rights"
|
||||
},
|
||||
{
|
||||
"tag": "linguistics"
|
||||
},
|
||||
{
|
||||
"tag": "politics of free speech"
|
||||
},
|
||||
{
|
||||
"tag": "press freedom"
|
||||
},
|
||||
{
|
||||
"tag": "speech debates"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/9783111233758/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Internet Lexicography: An Introduction",
|
||||
"creators": [],
|
||||
"date": "2024-11-04",
|
||||
"ISBN": "9783111233758",
|
||||
"abstractNote": "The Internet has become the central publication platform for dictionaries. This profound change in the dictionary landscape gives rise to a whole range of new questions for lexicographic practice and dictionary research. This volume provides for the first time an introduction to the central fields of work in Internet lexicography and presents the current state of scientific research and lexicographic practice. The chapters cover key aspects of dictionary creation, such as the technical framework, data modeling, and lexicographic process, linking dictionary content, access and navigation structures, automatic extraction of lexicographic information, user participation, and research on dictionary use. The aim of this volume is to provide students and teachers (at universities) with an introductory and easy-to-read overview on Internet lexicography, thus anchoring this important and innovative field of research and practice in university teaching. All chapters convey the basic concepts and methods in a comprehensible way and are enriched by references to further and more in-depth reading.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"publisher": "De Gruyter",
|
||||
"rights": "De Gruyter expressly reserves the right to use all content for commercial text and data mining within the meaning of Section 44b of the German Copyright Act.",
|
||||
"shortTitle": "Internet Lexicography",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.1515/9783111233758/html",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Lexicography"
|
||||
},
|
||||
{
|
||||
"tag": "digital language tools"
|
||||
},
|
||||
{
|
||||
"tag": "language documentation"
|
||||
},
|
||||
{
|
||||
"tag": "linguistics"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.31826/9781463235949-008/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "bookSection",
|
||||
"title": "Did Isaiah Really See God? The Ancient Discussion About Isaiah 6:1",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Magnar",
|
||||
"lastName": "Kartveit",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Zehnder",
|
||||
"firstName": "Markus",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2014-05-14",
|
||||
"ISBN": "9781463235949",
|
||||
"bookTitle": "New Studies in the Book of Isaiah: Essays in Honor of Hallvard Hagelia",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.degruyterbrill.com",
|
||||
"pages": "115-136",
|
||||
"publisher": "Gorgias Press",
|
||||
"shortTitle": "Did Isaiah Really See God?",
|
||||
"url": "https://www.degruyterbrill.com/document/doi/10.31826/9781463235949-008/html",
|
||||
"attachments": [],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "d8341c22-8cf4-428f-be3b-ada9fa8933eb",
|
||||
"label": "Deutsche Nationalbibliothek",
|
||||
"creator": "Philipp Zumstein",
|
||||
"target": "^https?://portal\\.dnb\\.de/opac\\.htm\\?",
|
||||
"target": "^https?://portal\\.dnb\\.de/opac(\\.htm|/(enhancedSearch|simpleSearch|showFullRecord)\\?)",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2018-05-14 19:08:02"
|
||||
"lastUpdated": "2024-01-15 19:48:46"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -36,51 +36,55 @@
|
|||
*/
|
||||
|
||||
var typeMapping = {
|
||||
//"Blindendrucke"
|
||||
"Bücher" : "book",
|
||||
//"Elektronische Datenträger"
|
||||
"Filme/Hörbücher" : "videoRecording",
|
||||
"Karten" : "map",
|
||||
//"Blindendrucke"
|
||||
Bücher: "book",
|
||||
//"Elektronische Datenträger"
|
||||
"Filme/Hörbücher": "videoRecording",
|
||||
Karten: "map",
|
||||
//"Medienkombinationen"
|
||||
//"Mikroformen"
|
||||
"Musiktonträger" : "audioRecording",
|
||||
//"Musiknoten"
|
||||
"Artikel" : "journalArticle",
|
||||
Musiktonträger: "audioRecording",
|
||||
//"Musiknoten"
|
||||
Artikel: "journalArticle",
|
||||
//"Online Ressourcen"
|
||||
//"Zeitschriften/Serien"
|
||||
//"Ausgaben/Hefte"
|
||||
"archivierte Webseiten" : "webpage",
|
||||
"archivierte Webseiten": "webpage",
|
||||
//"Gesamttitel Sammlung/Nachlass"
|
||||
"Manuskripte" : "manuscript",
|
||||
"Briefe" : "letter",
|
||||
Manuskripte: "manuscript",
|
||||
Briefe: "letter",
|
||||
//"Lebensdokumente"
|
||||
//"Sammlungen"
|
||||
//"Trägermaterialien (Papiere und Einbände)"
|
||||
"Bilder/Grafiken" : "artwork"
|
||||
"Bilder/Grafiken": "artwork"
|
||||
//"Flugblätter"
|
||||
};
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (
|
||||
url.indexOf('method=showFullRecord')>-1 ||
|
||||
(url.indexOf('method=simpleSearch')>-1 && doc.getElementById('fullRecordTable'))
|
||||
(url.includes('method=showFullRecord') || url.includes('/showFullRecord?'))
|
||||
|| ((url.includes('method=simpleSearch') || url.includes('/simpleSearch?') || url.includes('/enhancedSearch?') || url.includes('method=enhancedSearch'))
|
||||
&& doc.getElementById('fullRecordTable'))
|
||||
) {
|
||||
var type=ZU.xpathText(doc, '//table[@id="fullRecordTable"]/tbody/tr/td/img/@alt');
|
||||
var type = ZU.xpathText(doc, '//table[@id="fullRecordTable"]/tbody/tr/td/img/@alt');
|
||||
if (typeMapping[type]) {
|
||||
return typeMapping[type];
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return "book";
|
||||
}
|
||||
} 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 = ZU.xpath(doc, '//table[@id="searchresult"]//a[contains(@id, "recordLink")]');
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var href = rows[i].href;
|
||||
var title = ZU.trimInternal(rows[i].firstChild.textContent);
|
||||
if (!href || !title) continue;
|
||||
|
|
@ -92,63 +96,57 @@ function getSearchResults(doc, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
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);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
function scrape(doc, url) {
|
||||
async function scrape(doc) {
|
||||
var marc = ZU.xpath(doc, '//div[@class="link"]//a[contains(@href, "/about/marcxml")]');
|
||||
if (marc.length) {
|
||||
var marcUrl = marc[0].href;
|
||||
|
||||
ZU.doGet(marcUrl, function(result) {
|
||||
|
||||
//call MARCXML translator
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("edd87d07-9194-42f8-b2ad-997c4c7deefd");
|
||||
translator.setString(result);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
finalize(doc, item);
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
});
|
||||
|
||||
} else {
|
||||
Z.debug("No MARC link found --> Use COinS translator");
|
||||
|
||||
//call COinS translator
|
||||
var translator = Zotero.loadTranslator("web");
|
||||
translator.setTranslator("05d07af9-105a-4572-99f6-a8e231c0daef");
|
||||
translator.setDocument(doc);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
let result = await requestText(marcUrl);
|
||||
//call MARCXML translator
|
||||
let translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("edd87d07-9194-42f8-b2ad-997c4c7deefd");
|
||||
translator.setString(result);
|
||||
translator.setHandler("itemDone", (_obj, item) => {
|
||||
finalize(doc, item);
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
|
||||
await translator.translate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Z.debug("No MARC link found --> Use COinS translator");
|
||||
|
||||
// call COinS translator
|
||||
// eslint-disable-next-line no-redeclare
|
||||
let translator = Zotero.loadTranslator("web");
|
||||
translator.setTranslator("05d07af9-105a-4572-99f6-a8e231c0daef");
|
||||
translator.setDocument(doc);
|
||||
translator.setHandler("itemDone", (_obj, item) => {
|
||||
finalize(doc, item);
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function finalize(doc, item) {
|
||||
var toc = ZU.xpath(doc, '//a[contains(@title, "Inhaltsverzeichnis")]');
|
||||
if (toc.length) {
|
||||
item.attachments.push( {
|
||||
url : toc[0].href,
|
||||
item.attachments.push({
|
||||
url: toc[0].href,
|
||||
title: "Table of Contents PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
|
|
@ -156,8 +154,8 @@ function finalize(doc, item) {
|
|||
|
||||
var abstract = ZU.xpath(doc, '//a[contains(@title, "Inhaltstext")]');
|
||||
if (abstract.length) {
|
||||
item.attachments.push( {
|
||||
url : abstract[0].href,
|
||||
item.attachments.push({
|
||||
url: abstract[0].href,
|
||||
title: "Abstract",
|
||||
mimeType: "text/html"
|
||||
});
|
||||
|
|
@ -491,6 +489,106 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://portal.dnb.de/opac/simpleSearch?query=test",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://portal.dnb.de/opac/simpleSearch?query=idn%3D1272086992&cqlMode=true",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "Den Netten beißen die Hunde: Wie Sie sich Respekt verschaffen, Grenzen setzen und den verdienten Erfolg erlangen - Mit großem \"Bin ich zu nett?\"-Test",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Martin",
|
||||
"lastName": "Wehrle",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2024",
|
||||
"ISBN": "9783442179046",
|
||||
"language": "ger",
|
||||
"libraryCatalog": "Deutsche Nationalbibliothek",
|
||||
"numPages": "320",
|
||||
"place": "München",
|
||||
"publisher": "Goldmann",
|
||||
"shortTitle": "Den Netten beißen die Hunde",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Abstract",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "(Produktform)Paperback / softback"
|
||||
},
|
||||
{
|
||||
"tag": "(VLB-WN)2933: Taschenbuch / Sachbücher/Angewandte Psychologie"
|
||||
},
|
||||
{
|
||||
"tag": "Business"
|
||||
},
|
||||
{
|
||||
"tag": "Büro"
|
||||
},
|
||||
{
|
||||
"tag": "Den Letzten beißen die Hunde"
|
||||
},
|
||||
{
|
||||
"tag": "Durchsetzungsvermögen"
|
||||
},
|
||||
{
|
||||
"tag": "Mental Load"
|
||||
},
|
||||
{
|
||||
"tag": "Nein sagen ohne Schuldgefühle"
|
||||
},
|
||||
{
|
||||
"tag": "Partnerschaft Kommunikation"
|
||||
},
|
||||
{
|
||||
"tag": "Sei einzig nicht artig"
|
||||
},
|
||||
{
|
||||
"tag": "Selbstbewusstsein"
|
||||
},
|
||||
{
|
||||
"tag": "Selbstbewustsein stärken"
|
||||
},
|
||||
{
|
||||
"tag": "Selbstrespekt"
|
||||
},
|
||||
{
|
||||
"tag": "Wenn jeder dich mag nimmt keiner dich ernst"
|
||||
},
|
||||
{
|
||||
"tag": "Wertschätzung"
|
||||
},
|
||||
{
|
||||
"tag": "ausgenutzt werden"
|
||||
},
|
||||
{
|
||||
"tag": "ernst genommen werden"
|
||||
},
|
||||
{
|
||||
"tag": "fehlende Anerkennung"
|
||||
},
|
||||
{
|
||||
"tag": "sich durchsetzen"
|
||||
},
|
||||
{
|
||||
"tag": "spiegel bestseller"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -9,104 +9,199 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2012-09-20 20:46:53"
|
||||
"lastUpdated": "2024-05-15 15:07:13"
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (doc.evaluate('//div[@class="DHQarticle"]', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2012-2024 Michael Berkowitz
|
||||
|
||||
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('.DHQarticle')) {
|
||||
return "journalArticle";
|
||||
} else if (doc.evaluate('//div[@id="mainContent"]/div/p', doc, null, XPathResult.ANY_TYPE, null).iterateNext()) {
|
||||
}
|
||||
if (doc.querySelector('#toc') && getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function xpathtext(doc, xpath, xdoc) {
|
||||
return Zotero.Utilities.trimInternal(doc.evaluate(xpath, xdoc, null, XPathResult.ANY_TYPE, null).iterateNext().textContent);
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var articles = new Array();
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var items = new Object;
|
||||
var arts = doc.evaluate('//div[@id="mainContent"]/div/p/a', doc, null, XPathResult.ANY_TYPE, null);
|
||||
var art;
|
||||
while (art = arts.iterateNext()) {
|
||||
items[art.href] = art.textContent;
|
||||
}
|
||||
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) {
|
||||
return true;
|
||||
}
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
scrape(articles, function () {
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
articles = [url];
|
||||
scrape(articles);
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('#toc .articleInfo > a:first-of-type');
|
||||
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;
|
||||
}
|
||||
Zotero.debug(articles);}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function scrape(articles){
|
||||
Zotero.Utilities.processDocuments(articles, function(newDoc) {
|
||||
var item = new Zotero.Item("journalArticle");
|
||||
item.url = newDoc.location.href;
|
||||
item.title = xpathtext(newDoc, '//h1[@class="articleTitle"]', newDoc);
|
||||
var voliss = xpathtext(newDoc, '//div[@id="pubInfo"]', newDoc);
|
||||
voliss = voliss.match(/(.*)Volume\s+(\d+)\s+Number\s+(\d+)/);
|
||||
item.date = voliss[1];
|
||||
item.volume = voliss[2];
|
||||
item.issue = voliss[3];
|
||||
var authors = newDoc.evaluate('//div[@class="author"]', newDoc, null, XPathResult.ANY_TYPE, null);
|
||||
var aut;
|
||||
while (aut = authors.iterateNext()) {
|
||||
item.creators.push(Zotero.Utilities.cleanAuthor(xpathtext(newDoc, './a[1]', aut), "author"));
|
||||
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));
|
||||
}
|
||||
item.attachments = [{url:item.url, title:"DHQ Snapshot", mimeType:"text/html"}];
|
||||
item.complete();
|
||||
}, function() {});}/** BEGIN TEST CASES **/
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url = doc.location.href) {
|
||||
// Get the metadata
|
||||
const main = doc.querySelector('#mainContent');
|
||||
// Of the form "YYYY Volume.Issue"
|
||||
const [year, volume, issue] = text(main, '.toolbar > a').split(/[\s\\.]+/);
|
||||
const title = ZU.trimInternal(text(main, 'h1.articleTitle'));
|
||||
const authors = main.querySelectorAll('.DHQheader .author');
|
||||
const abstract = ZU.trimInternal(text(main, '#abstract > p'));
|
||||
const license = ZU.trimInternal(text(main, ".license > a[rel='license']:last-of-type"));
|
||||
// Build item
|
||||
const item = new Z.Item("journalArticle");
|
||||
item.url = doc.location.href;
|
||||
item.title = title;
|
||||
item.creators = [...authors].map((author) => {
|
||||
return ZU.cleanAuthor(text(author, 'a:first-child'), "author");
|
||||
});
|
||||
item.publicationTitle = "Digital Humanities Quarterly";
|
||||
item.ISSN = "1938-4122";
|
||||
item.date = year;
|
||||
item.volume = volume;
|
||||
item.issue = issue;
|
||||
item.abstractNote = abstract;
|
||||
item.rights = license;
|
||||
const pdfLink = main.querySelector('.toolbar > a[href$=".pdf"]');
|
||||
if (pdfLink) {
|
||||
item.attachments.push({
|
||||
url: pdfLink.href,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
document: doc,
|
||||
title: "Snapshot"
|
||||
});
|
||||
}
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.digitalhumanities.org/dhq/vol/5/2/000094/000094.html",
|
||||
"url": "https://www.digitalhumanities.org/dhq/vol/5/2/index.html",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.digitalhumanities.org/dhq/vol/17/1/000671/000671.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Introduction to Special Issue: Project Resiliency in the Digital Humanities",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Wesley",
|
||||
"lastName": "Beal",
|
||||
"firstName": "Martin",
|
||||
"lastName": "Holmes",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Janelle",
|
||||
"lastName": "Jenstad",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "J. Matthew",
|
||||
"lastName": "Huculak",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"tags": [],
|
||||
"seeAlso": [],
|
||||
"date": "2023",
|
||||
"ISSN": "1938-4122",
|
||||
"abstractNote": "This introduction to the Project Resiliency issue argues that we have work to do in getting projects to the point of being done and archivable. The Endings Project, a collaboration between three developers, three humanities scholars, and three librarians, arose from the maintenance burden accrued by the Humanities Computing and Media Centre at the University of Victoria and our desire to design projects that, from their inception, are ready for long-term archiving. After describing the events leading up to the Endings Symposium and briefly summarizing the articles in this issue, we discuss the necessity of a culture of constraint if we wish to preserve digital humanities projects in the same way that libraries preserve books.",
|
||||
"issue": "1",
|
||||
"libraryCatalog": "Digital Humanities Quarterly",
|
||||
"publicationTitle": "Digital Humanities Quarterly",
|
||||
"rights": "Creative Commons Attribution-NoDerivatives 4.0 International License",
|
||||
"shortTitle": "Introduction to Special Issue",
|
||||
"url": "https://www.digitalhumanities.org/dhq/vol/17/1/000671/000671.html",
|
||||
"volume": "17",
|
||||
"attachments": [
|
||||
{
|
||||
"url": "http://www.digitalhumanities.org/dhq/vol/5/2/000094/000094.html",
|
||||
"title": "DHQ Snapshot",
|
||||
"mimeType": "text/html"
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"url": "http://www.digitalhumanities.org/dhq/vol/5/2/000094/000094.html",
|
||||
"title": "Network Narration in John Dos Passos’s U.S.A. Trilogy",
|
||||
"date": "2011",
|
||||
"volume": "5",
|
||||
"issue": "2",
|
||||
"libraryCatalog": "Digital Humanities Quarterly",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "http://www.digitalhumanities.org/dhq/vol/5/1/index.html",
|
||||
"items": "multiple"
|
||||
"url": "https://www.digitalhumanities.org/dhq/vol/17/2/000699/000699.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "ᐊᒐᐦᑭᐯᐦᐃᑲᓇ ᒫᒥᑐᓀᔨᐦᐃᒋᑲᓂᐦᑳᓂᕽ | acahkipehikana mâmitoneyihicikanihkânihk | Programming with Cree# and Ancestral Code: Nehiyawewin Spirit Markings in an Artificial Brain",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Jon",
|
||||
"lastName": "Corbett",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023",
|
||||
"ISSN": "1938-4122",
|
||||
"abstractNote": "In this article, I discuss my project “Ancestral Code”, which consists of an integrated development environment (IDE) and the Nehiyaw (Plains Cree) based programming languages called Cree# (pronounced: Cree-Sharp) and ᐊᒋᒧ (âcimow). These languages developed in response to western perspectives on human-computer relationships, which I challenge and reframe in Nehiyaw/Indigenous contexts.",
|
||||
"issue": "2",
|
||||
"libraryCatalog": "Digital Humanities Quarterly",
|
||||
"publicationTitle": "Digital Humanities Quarterly",
|
||||
"rights": "Creative Commons Attribution-NoDerivatives 4.0 International License",
|
||||
"shortTitle": "ᐊᒐᐦᑭᐯᐦᐃᑲᓇ ᒫᒥᑐᓀᔨᐦᐃᒋᑲᓂᐦᑳᓂᕽ | acahkipehikana mâmitoneyihicikanihkânihk | Programming with Cree# and Ancestral Code",
|
||||
"url": "https://www.digitalhumanities.org/dhq/vol/17/2/000699/000699.html",
|
||||
"volume": "17",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "fc353b26-8911-4c34-9196-f6f567c93901",
|
||||
"label": "Douban",
|
||||
"creator": "Ace Strong<acestrong@gmail.com>",
|
||||
"target": "^https?://(www|book)\\.douban\\.com/(subject|doulist|people/[a-zA-Z._]*/(do|wish|collect)|.*?status=(do|wish|collect)|group/[0-9]*?/collection|tag)",
|
||||
"target": "^https?://(www|book)\\.douban\\.com/(subject|doulist|people/[a-zA-Z0-9._]*/(do|wish|collect)|.*?status=(do|wish|collect)|group/[0-9]*?/collection|tag)",
|
||||
"minVersion": "2.0rc1",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2020-06-04 03:46:18"
|
||||
"lastUpdated": "2024-08-07 08:46:18"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -189,7 +189,7 @@ function scrapeAndParse(doc, url) {
|
|||
// #########################
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
var pattern = /subject_search|doulist|people\/[a-zA-Z._]*?\/(?:do|wish|collect)|.*?status=(?:do|wish|collect)|group\/[0-9]*?\/collection|tag/;
|
||||
var pattern = /subject_search|doulist|people\/[a-zA-Z0-9._]*?\/(?:do|wish|collect)|.*?status=(?:do|wish|collect)|group\/[0-9]*?\/collection|tag/;
|
||||
|
||||
if (pattern.test(url)) {
|
||||
return "multiple";
|
||||
|
|
|
|||
|
|
@ -9,30 +9,30 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-10-05 02:33:49"
|
||||
"lastUpdated": "2023-10-23 09:05:55"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2022 Sebastian Karcher
|
||||
Copyright © 2022 Sebastian Karcher
|
||||
|
||||
This file is part of Zotero.
|
||||
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 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.
|
||||
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/>.
|
||||
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 *****
|
||||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -64,11 +64,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (items) {
|
||||
await Promise.all(
|
||||
Object.keys(items)
|
||||
.map(url => requestDocument(url).then(scrape))
|
||||
);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -213,6 +211,40 @@ var testCases = [
|
|||
"type": "web",
|
||||
"url": "https://www.dukeupress.edu/books/browse?sortid=7",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.dukeupress.edu/beyond-this-narrow-now",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "book",
|
||||
"title": "\"Beyond This Narrow Now\": Or, Delimitations, of W. E. B. Du Bois",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Nahum Dimitri",
|
||||
"lastName": "Chandler",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022",
|
||||
"ISBN": "9781478014805",
|
||||
"abstractNote": "In “Beyond This Narrow Now” Nahum Dimitri Chandler shows that the premises of W. E. B. Du Bois's thinking at the turn of the twentieth century stand as fundamental references for the whole itinerary of his thought. Opening with a distinct approach to the legacy of Du Bois, Chandler proceeds through a series of close readings of Du Bois's early essays, previously unpublished or seldom studied, with discrete annotations of The Souls of Black Folk: Essays and Sketches of 1903, elucidating and elaborating basic epistemological terms of his thought. With theoretical attention to how the African American stands as an example of possibility for Du Bois and renders problematic traditional ontological thought, Chandler also proposes that Du Bois's most well-known phrase—“the problem of the color line”—sustains more conceptual depth than has yet been understood, with pertinence for our accounts of modern systems of enslavement and imperial colonialism and the incipient moments of modern capitalization. Chandler's work exemplifies a more profound engagement with Du Bois, demonstrating that he must be re-read, appreciated, and studied anew as a philosophical writer and thinker contemporary to our time.",
|
||||
"libraryCatalog": "Duke University Press Books",
|
||||
"numPages": "328",
|
||||
"place": "Durham, NC",
|
||||
"publisher": "Duke University Press",
|
||||
"shortTitle": "\"Beyond This Narrow Now\"",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,347 @@
|
|||
{
|
||||
"translatorID": "dbfd99e3-6925-4b71-92b8-12b02aa875fc",
|
||||
"label": "E-periodica Switzerland",
|
||||
"creator": "Alain Borel",
|
||||
"target": "^https?://(www|news?)\\.e-periodica\\.ch",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-08-15 20:15:50"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Alain Borel
|
||||
|
||||
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('/digbib/view')) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
// Zotero.debug(items);
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('h2.ep-result__title > a');
|
||||
for (let row of rows) {
|
||||
//Zotero.debug(row.textContent);
|
||||
let href = row.href;
|
||||
//Zotero.debug(href);
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
// Zotero.debug(items[href]);
|
||||
}
|
||||
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 resultUrl of Object.keys(items)) {
|
||||
await scrape(resultUrl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The journalArticle type will be applicable in general unless we find multiple refs.
|
||||
await scrape(url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(url) {
|
||||
// In general the article ID is given the pid parameter in the URL
|
||||
// If the URL ends with a hash/fragment identifier,
|
||||
// the final digits of the pid parameter (after a double colon) must be replaced with the hash ID
|
||||
// e.g. alp-001:1907:2::332#375 => alp-001:1907:2::375
|
||||
let articleURL = new URL(url);
|
||||
let articleID = articleURL.searchParams.get("pid");
|
||||
let articleViewFragment = articleURL.hash.replace(/^#/, ""); // trim leading #
|
||||
if (/\d+/.test(articleViewFragment)) {
|
||||
// Normalize article ID by replacing the last segment with the real
|
||||
// page id if any
|
||||
articleID = articleID.replace(/::\d+$/, "::" + articleViewFragment);
|
||||
}
|
||||
let pageinfoUrl = "https://www.e-periodica.ch/digbib/ajax/pageinfo?pid=" + encodeURIComponent(articleID);
|
||||
|
||||
//Zotero.debug('JSON URL ' + pageinfoUrl);
|
||||
let epJSON = await requestJSON(pageinfoUrl);
|
||||
//Zotero.debug(epJSON);
|
||||
let risURL;
|
||||
if (epJSON.articles.length == 0) {
|
||||
// Fallback for non-article content, listed as Werbung, Sonstiges and various others:
|
||||
// this information is unfortunately not included in the JSON metadata => let's add a reasonable pseudo-title
|
||||
epJSON.articles = [{ title: "Untitled" }];
|
||||
}
|
||||
if (epJSON.articles["0"].hasRisLink) {
|
||||
risURL = '/view/' + epJSON.articles["0"].risLink;
|
||||
}
|
||||
|
||||
// Zotero.debug(risURL);
|
||||
var pdfURL = null;
|
||||
if (epJSON.articles["0"].hasPdfLink) {
|
||||
pdfURL = epJSON.articles["0"].pdfLink;
|
||||
}
|
||||
// Zotero.debug(pdfURL);
|
||||
if (risURL) {
|
||||
let risText = await requestText(risURL);
|
||||
processRIS(risText, pdfURL);
|
||||
}
|
||||
else {
|
||||
var item = new Zotero.Item("journalArticle");
|
||||
item.title = epJSON.articles["0"].title.replace(' : ', ': ');
|
||||
item.publicationTitle = epJSON.journalTitle.replace(' : ', ': ');
|
||||
var numyear = epJSON.volumeNumYear.split(/[ ()]/).filter(element => element);
|
||||
if (numyear.length > 1) {
|
||||
item.date = numyear.slice(-1);
|
||||
}
|
||||
if (numyear.length > 0) {
|
||||
item.volume = numyear[0];
|
||||
}
|
||||
if (epJSON.issueNumber) {
|
||||
item.issue = epJSON.issueNumber;
|
||||
}
|
||||
if (epJSON.viewerLink.length > 0) {
|
||||
if (epJSON.viewerLink.indexOf("http") == 0) {
|
||||
item.url = epJSON.viewerLink;
|
||||
}
|
||||
else {
|
||||
item.url = "https://www.e-periodica.ch" + epJSON.viewerLink;
|
||||
}
|
||||
}
|
||||
if (epJSON.pdfLink) {
|
||||
if (epJSON.pdfLink.indexOf("http") == 0) {
|
||||
pdfURL = epJSON.pdfLink;
|
||||
}
|
||||
else {
|
||||
pdfURL = "https://www.e-periodica.ch" + epJSON.pdfLink;
|
||||
}
|
||||
}
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
type: "application/pdf"
|
||||
});
|
||||
}
|
||||
item.complete();
|
||||
}
|
||||
}
|
||||
|
||||
function processRIS(risText, pdfURL) {
|
||||
// load translator for RIS
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
// Z.debug(text);
|
||||
|
||||
translator.setString(risText);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
// Don't save HTML snapshot from 'UR' tag
|
||||
item.attachments = [];
|
||||
|
||||
// change colon spacing in title and publicationTitle
|
||||
item.title = item.title.replace(' : ', ': ');
|
||||
|
||||
if (item.publicationTitle) {
|
||||
item.publicationTitle = item.publicationTitle.replace(' : ', ': ');
|
||||
}
|
||||
|
||||
if (item.title == item.title.toUpperCase()) {
|
||||
item.title = ZU.capitalizeTitle(item.title.toLowerCase(), true);
|
||||
}
|
||||
|
||||
// Retrieve fulltext
|
||||
if (pdfURL !== null) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
type: "application/pdf"
|
||||
});
|
||||
}
|
||||
|
||||
// DB in RIS maps to archive; we don't want that
|
||||
delete item.archive;
|
||||
|
||||
item.complete();
|
||||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.doImport();
|
||||
});
|
||||
}/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.e-periodica.ch/digbib/view?pid=enh-006%3A2018%3A11::121#133",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Untersuchungen zur aktuellen Verbreitung der schweizerischen Laufkäfer (Coleoptera: Carabidae): Zwischenbilanz",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Hoess",
|
||||
"firstName": "René",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Chittaro",
|
||||
"firstName": "Yannick",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Walter",
|
||||
"firstName": "Thomas",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018",
|
||||
"DOI": "10.5169/seals-986030",
|
||||
"ISSN": "1662-8500",
|
||||
"libraryCatalog": "E-periodica Switzerland",
|
||||
"pages": "129",
|
||||
"publicationTitle": "Entomo Helvetica: entomologische Zeitschrift der Schweiz",
|
||||
"shortTitle": "Untersuchungen zur aktuellen Verbreitung der schweizerischen Laufkäfer (Coleoptera",
|
||||
"volume": "11",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"type": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.e-periodica.ch/digbib/view?pid=bts-004%3A2011%3A137%3A%3A254&referrer=search#251",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Décentralisation, opportunités et contraintes",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Fignolé",
|
||||
"firstName": "Jean-Claude",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"DOI": "10.5169/seals-144646",
|
||||
"ISSN": "0251-0979",
|
||||
"issue": "05-06",
|
||||
"libraryCatalog": "E-periodica Switzerland",
|
||||
"pages": "14",
|
||||
"publicationTitle": "Tracés: bulletin technique de la Suisse romande",
|
||||
"volume": "137",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"type": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.e-periodica.ch/digbib/view?pid=alp-001%3A1907%3A2%3A%3A332#375",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Stimmen und Meinungen: schweizerisches Nationaldrama?",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Falke",
|
||||
"firstName": "Konrad",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1907-1908",
|
||||
"DOI": "10.5169/seals-747870",
|
||||
"issue": "12",
|
||||
"libraryCatalog": "E-periodica Switzerland",
|
||||
"pages": "364",
|
||||
"publicationTitle": "Berner Rundschau: Halbmonatsschrift für Dichtung, Theater, Musik und bildende Kunst in der Schweiz",
|
||||
"shortTitle": "Stimmen und Meinungen",
|
||||
"volume": "2",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"type": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.e-periodica.ch/digbib/view?pid=bts-004%3A2011%3A137%3A%3A262#262",
|
||||
"detectedItemType": "journalArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Untitled",
|
||||
"creators": [],
|
||||
"date": "2011",
|
||||
"issue": "05-06",
|
||||
"libraryCatalog": "E-periodica Switzerland",
|
||||
"publicationTitle": "Tracés: bulletin technique de la Suisse romande",
|
||||
"url": "https://www.e-periodica.ch/digbib/view?pid=bts-004%3A2011%3A137%3A%3A262",
|
||||
"volume": "137",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"type": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -2,14 +2,14 @@
|
|||
"translatorID": "660fcf3e-3414-41b8-97a5-e672fc2e491d",
|
||||
"label": "EBSCO Discovery Layer",
|
||||
"creator": "Sebastian Karcher",
|
||||
"target": "^https?://discovery\\.ebsco\\.com/",
|
||||
"target": "^https?://(discovery|research)\\.ebsco\\.com/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-02-12 03:36:07"
|
||||
"lastUpdated": "2024-02-04 04:24:48"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -35,14 +35,14 @@
|
|||
***** END LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
const itemRegex = /\/c\/([^/]+)\/(?:details|viewer\/pdf)\/([^?]+)/;
|
||||
const itemRegex = /\/c\/([^/]+)(?:\/search)?\/(?:details|viewer\/pdf)\/([^?]+)/;
|
||||
function detectWeb(doc, url) {
|
||||
if (itemRegex.test(url)) {
|
||||
if (url.includes("/viewer/pdf")) {
|
||||
return "journalArticle";
|
||||
}
|
||||
Z.monitorDOMChanges(doc.querySelector('#page-container'));
|
||||
let type = text(doc, 'div.article-type');
|
||||
let type = text(doc, 'div[class*="article-type"]');
|
||||
if (type) {
|
||||
return getType(type);
|
||||
}
|
||||
|
|
@ -60,7 +60,9 @@ function detectWeb(doc, url) {
|
|||
|
||||
function getType(type) {
|
||||
// This can probably be fine-tuned, but it'll work for 90% of results
|
||||
if (type.toLowerCase().includes("article")) {
|
||||
type = type.toLowerCase();
|
||||
// Z.debug(type)
|
||||
if (type.includes("article") || type.includes("artikel")) {
|
||||
return "journalArticle";
|
||||
}
|
||||
else {
|
||||
|
|
@ -73,6 +75,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
var found = false;
|
||||
|
||||
var rows = doc.querySelectorAll('h2.result-item-title > a');
|
||||
if (!rows.length) {
|
||||
rows = doc.querySelectorAll('div[class*="result-item-title"]>a');
|
||||
}
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.textContent);
|
||||
|
|
@ -138,6 +143,5 @@ async function scrape(doc, url = doc.location.href) {
|
|||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
]
|
||||
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
23
EBSCOhost.js
23
EBSCOhost.js
|
|
@ -8,8 +8,8 @@
|
|||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsib",
|
||||
"lastUpdated": "2021-10-11 01:07:25"
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2024-04-15 01:50:53"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -56,7 +56,7 @@ function detectWeb(doc, url) {
|
|||
* given the text of the delivery page, downloads an item
|
||||
*/
|
||||
function downloadFunction(text, url, prefs) {
|
||||
if (text.search(/^TY\s\s?-/m) == -1) {
|
||||
if (!(/^TY\s\s?-/m.test(text))) {
|
||||
text = "\nTY - JOUR\n" + text; // this is probably not going to work if there is garbage text in the begining
|
||||
}
|
||||
|
||||
|
|
@ -87,12 +87,14 @@ function downloadFunction(text, url, prefs) {
|
|||
let subtitle;
|
||||
|
||||
// EBSCOhost uses nonstandard tags to represent journal titles on some items
|
||||
// Sometimes T2 also just duplicates the journal title across along with JO/JF/J1
|
||||
// no /g flag so we don't create duplicate tags
|
||||
let journalRe = /^(JO|JF|J1)/m;
|
||||
if (journalRe.test(text)) {
|
||||
let journalTitleRe = /^(?:JO|JF|J1)\s\s?-\s?(.*)/m;
|
||||
if (journalTitleRe.test(text)) {
|
||||
let subtitleRe = /^T2\s\s?-\s?(.*)/m;
|
||||
let subtitleMatch = text.match(subtitleRe);
|
||||
if (subtitleMatch) {
|
||||
if (subtitleMatch && subtitleMatch[1] != text.match(journalTitleRe)[1]) {
|
||||
// if there's already something in T2, store it and erase it from the RIS
|
||||
subtitle = subtitleMatch[1];
|
||||
text = text.replace(subtitleRe, '');
|
||||
|
|
@ -100,7 +102,7 @@ function downloadFunction(text, url, prefs) {
|
|||
|
||||
text = text.replace(journalRe, 'T2');
|
||||
}
|
||||
|
||||
|
||||
// Let's try to keep season info
|
||||
// Y1 - 1993///Winter93
|
||||
// Y1 - 2009///Spring2009
|
||||
|
|
@ -115,7 +117,7 @@ function downloadFunction(text, url, prefs) {
|
|||
translator.setString(text);
|
||||
// eslint-disable-next-line padded-blocks
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
|
||||
|
||||
/* Fix capitalization issues */
|
||||
// title
|
||||
if (!item.title && prefs.itemTitle) {
|
||||
|
|
@ -204,7 +206,8 @@ function downloadFunction(text, url, prefs) {
|
|||
item.attachments.push({
|
||||
url: prefs.pdfURL,
|
||||
title: "EBSCO Full Text",
|
||||
mimeType: "application/pdf"
|
||||
mimeType: "application/pdf",
|
||||
proxy: false
|
||||
});
|
||||
item.complete();
|
||||
}
|
||||
|
|
@ -401,6 +404,8 @@ function findPdfUrl(pdfDoc) {
|
|||
/**
|
||||
* borrowed from http://www.webtoolkit.info/javascript-base64.html
|
||||
*/
|
||||
// We should have this available now - leaving in the code just in case
|
||||
/*
|
||||
var base64KeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
|
||||
function utf8Encode(string) {
|
||||
|
|
@ -450,7 +455,7 @@ function btoa(input) {
|
|||
+ base64KeyStr.charAt(enc3) + base64KeyStr.charAt(enc4);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
} */
|
||||
|
||||
/**
|
||||
* end borrowed code
|
||||
|
|
|
|||
37
ERIC.js
37
ERIC.js
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 12,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2022-11-09 21:08:42"
|
||||
"lastUpdated": "2024-07-05 11:56:39"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -89,11 +89,9 @@ function getSearchResults(doc, checkOnly) {
|
|||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, false));
|
||||
if (items) {
|
||||
await Promise.all(
|
||||
Object.keys(items)
|
||||
.map(url => requestDocument(url).then(scrape))
|
||||
);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
await scrape(await requestDocument(url));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -133,8 +131,14 @@ async function scrape(doc, url = doc.location.href) {
|
|||
if (DOI) {
|
||||
item.DOI = ZU.cleanDOI(decodeURIComponent(DOI));
|
||||
}
|
||||
if (item.itemType == "journalArticle" && item.publisher == item.publicationTitle) {
|
||||
delete item.publisher; // Publisher & Publication Title are often identical
|
||||
if (item.publisher == item.publicationTitle) {
|
||||
// Publisher & Publication Title are often identical
|
||||
if (item.itemType == "journalArticle") {
|
||||
delete item.publisher;
|
||||
}
|
||||
else if (item.itemType == "report") {
|
||||
delete item.publicationTitle;
|
||||
}
|
||||
}
|
||||
|
||||
item.extra = "ERIC Number: " + ericID;
|
||||
|
|
@ -224,7 +228,6 @@ async function doSearch(search) {
|
|||
item.complete();
|
||||
}
|
||||
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -445,10 +448,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -525,10 +524,6 @@ var testCases = [
|
|||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -835,7 +830,13 @@ var testCases = [
|
|||
"extra": "ERIC Number: ED616685",
|
||||
"language": "English",
|
||||
"libraryCatalog": "ERIC",
|
||||
"attachments": [],
|
||||
"url": "https://eric.ed.gov/?id=ED616685",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Cognitive Processes"
|
||||
|
|
|
|||
61
EUR-Lex.js
61
EUR-Lex.js
|
|
@ -2,20 +2,20 @@
|
|||
"translatorID": "bf053edc-a8c3-458c-93db-6d04ead2e636",
|
||||
"label": "EUR-Lex",
|
||||
"creator": "Philipp Zumstein, Pieter van der Wees",
|
||||
"target": "^https?://(www\\.)?eur-lex\\.europa\\.eu/(legal-content/[A-Z][A-Z]/(TXT|ALL)/|search\\.html\\?)",
|
||||
"target": "^https://eur-lex\\.europa\\.eu/",
|
||||
"minVersion": "3.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-12-31 02:00:49"
|
||||
"lastUpdated": "2025-10-30 15:50:58"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2017-2021 Philipp Zumstein, Pieter van der Wees
|
||||
Copyright © 2025 Abe Jellinek
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
|
@ -161,19 +161,14 @@ function scrape(doc, url) {
|
|||
var type = detectWeb(doc, url);
|
||||
var item = new Zotero.Item(type);
|
||||
// determine the language in which we are currently viewing the document
|
||||
var languageUrl = url.split("/")[4].toUpperCase();
|
||||
if (languageUrl == "AUTO") {
|
||||
languageUrl = autoLanguage || "EN";
|
||||
}
|
||||
var language = languageMapping[languageUrl].iso || "eng";
|
||||
var viewingLanguage = (doc.documentElement.lang || "en").toUpperCase();
|
||||
// Cases only return language; discard everything else
|
||||
item.language = languageUrl.toLowerCase();
|
||||
|
||||
item.language = viewingLanguage.toLowerCase();
|
||||
|
||||
if (eliTypeUri) {
|
||||
// type: everything with ELI (see var typeMapping: bill, statute, report)
|
||||
item.title = attr(doc, 'meta[property="eli:title"][lang=' + languageUrl.toLowerCase() + "]", "content");
|
||||
var uri = attr(doc, "#format_language_table_digital_sign_act_" + languageUrl.toUpperCase(), "href");
|
||||
item.title = attr(doc, 'meta[property="eli:title"][lang=' + viewingLanguage.toLowerCase() + "]", "content");
|
||||
var uri = attr(doc, "#format_language_table_digital_sign_act_" + viewingLanguage.toUpperCase(), "href");
|
||||
if (uri) {
|
||||
var uriParts = uri.split("/").pop().replace("?uri=", "")
|
||||
.split(":");
|
||||
|
|
@ -207,7 +202,7 @@ function scrape(doc, url) {
|
|||
}
|
||||
item.legislativeBody = passedByArray.join(", ");
|
||||
|
||||
item.url = attr(doc, 'meta[typeOf="eli:LegalResource"]', "about") + "/" + language.toLowerCase();
|
||||
item.url = attr(doc, 'meta[typeOf="eli:LegalResource"]', "about");
|
||||
}
|
||||
|
||||
else if (item.itemType == "case") {
|
||||
|
|
@ -215,13 +210,13 @@ function scrape(doc, url) {
|
|||
// pretty hacky stuff, as there's little metadata available
|
||||
var docCourt = docType.substr(0, 1);
|
||||
if (docCourt == "C") {
|
||||
item.court = languageMapping[languageUrl].ECJ || languageMapping.EN.ECJ;
|
||||
item.court = languageMapping[viewingLanguage].ECJ || languageMapping.EN.ECJ;
|
||||
}
|
||||
else if (docCourt == "T") {
|
||||
item.court = languageMapping[languageUrl].GC || languageMapping.EN.GC;
|
||||
item.court = languageMapping[viewingLanguage].GC || languageMapping.EN.GC;
|
||||
}
|
||||
else if (docCourt == "F") {
|
||||
item.court = languageMapping[languageUrl].CST || languageMapping.EN.CST;
|
||||
item.court = languageMapping[viewingLanguage].CST || languageMapping.EN.CST;
|
||||
}
|
||||
item.url = url;
|
||||
|
||||
|
|
@ -253,10 +248,10 @@ function scrape(doc, url) {
|
|||
}
|
||||
// attachments
|
||||
// type: all
|
||||
var pdfurl = "https://eur-lex.europa.eu/legal-content/" + languageUrl + "/TXT/PDF/?uri=CELEX:" + celex;
|
||||
var htmlurl = "https://eur-lex.europa.eu/legal-content/" + languageUrl + "/TXT/HTML/?uri=CELEX:" + celex;
|
||||
item.attachments = [{ url: pdfurl, title: "EUR-Lex PDF (" + languageUrl + ")", mimeType: "application/pdf" }];
|
||||
item.attachments.push({ url: htmlurl, title: "EUR-Lex HTML (" + languageUrl + ")", mimeType: "text/html", snapshot: true });
|
||||
var pdfurl = "https://eur-lex.europa.eu/legal-content/" + viewingLanguage + "/TXT/PDF/?uri=CELEX:" + celex;
|
||||
var htmlurl = "https://eur-lex.europa.eu/legal-content/" + viewingLanguage + "/TXT/HTML/?uri=CELEX:" + celex;
|
||||
item.attachments = [{ url: pdfurl, title: "EUR-Lex PDF (" + viewingLanguage + ")", mimeType: "application/pdf" }];
|
||||
item.attachments.push({ url: htmlurl, title: "EUR-Lex HTML (" + viewingLanguage + ")", mimeType: "text/html", snapshot: true });
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
|
@ -276,7 +271,7 @@ var testCases = [
|
|||
"codeVolume": "281",
|
||||
"language": "en",
|
||||
"legislativeBody": "EP, CONSIL",
|
||||
"url": "http://data.europa.eu/eli/dir/1995/46/oj/eng",
|
||||
"url": "http://data.europa.eu/eli/dir/1995/46/oj",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "EUR-Lex PDF (EN)",
|
||||
|
|
@ -300,20 +295,20 @@ var testCases = [
|
|||
"items": [
|
||||
{
|
||||
"itemType": "statute",
|
||||
"nameOfAct": "Règlement (CE) n° 2257/94 de la Commission, du 16 septembre 1994, fixant des normes de qualité pour les bananes (Texte présentant de l'intérêt pour l'EEE)",
|
||||
"nameOfAct": "Commission Regulation (EC) No 2257/94 of 16 September 1994 laying down quality standards for bananas (Text with EEA relevance)",
|
||||
"creators": [],
|
||||
"dateEnacted": "1994-09-16",
|
||||
"code": "OJ L",
|
||||
"codeNumber": "245",
|
||||
"language": "fr",
|
||||
"url": "http://data.europa.eu/eli/reg/1994/2257/oj/fra",
|
||||
"language": "en",
|
||||
"url": "http://data.europa.eu/eli/reg/1994/2257/oj",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "EUR-Lex PDF (FR)",
|
||||
"title": "EUR-Lex PDF (EN)",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "EUR-Lex HTML (FR)",
|
||||
"title": "EUR-Lex HTML (EN)",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
|
|
@ -369,15 +364,15 @@ var testCases = [
|
|||
"title": "Bez námitek k navrhovanému spojení (Věc M.10068 — Brookfield/Mansa/Polenergia) (Text s významem pro EHP) 2021/C 14/01",
|
||||
"creators": [],
|
||||
"date": "2021",
|
||||
"language": "cs",
|
||||
"language": "nl",
|
||||
"url": "https://eur-lex.europa.eu/legal-content/CS/TXT/?uri=uriserv%3AOJ.C_.2021.014.01.0001.01.CES&toc=OJ%3AC%3A2021%3A014%3ATOC",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "EUR-Lex PDF (CS)",
|
||||
"title": "EUR-Lex PDF (NL)",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "EUR-Lex HTML (CS)",
|
||||
"title": "EUR-Lex HTML (NL)",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
|
|
@ -398,17 +393,17 @@ var testCases = [
|
|||
"creators": [],
|
||||
"dateDecided": "21 ta' Settembru 2011",
|
||||
"abstractNote": "Trade mark Komunitarja - Proċedimenti għal dikjarazzjoni ta’ invalidità - Trade mark Komunitarja verbali SCOMBER MIX - Raġuni assoluta għal rifjut - Karattru deskrittiv - Artikolu 7(1)(b) u (ċ) tar-Regolament (KE) Nru 40/94 [li sar l-Artikolu 7(1)(b) u (c) tar-Regolament (KE) Nru 207/2009]",
|
||||
"court": "Il-Qorti Ġenerali",
|
||||
"court": "Gerecht EU",
|
||||
"docketNumber": "Kawża T-201/09",
|
||||
"language": "mt",
|
||||
"language": "nl",
|
||||
"url": "https://eur-lex.europa.eu/legal-content/MT/TXT/?uri=CELEX%3A62009TJ0201",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "EUR-Lex PDF (MT)",
|
||||
"title": "EUR-Lex PDF (NL)",
|
||||
"mimeType": "application/pdf"
|
||||
},
|
||||
{
|
||||
"title": "EUR-Lex HTML (MT)",
|
||||
"title": "EUR-Lex HTML (NL)",
|
||||
"mimeType": "text/html",
|
||||
"snapshot": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,116 +1,120 @@
|
|||
{
|
||||
"translatorID": "09a9599e-c20e-a405-d10d-35ad4130a426",
|
||||
"label": "Electronic Colloquium on Computational Complexity",
|
||||
"creator": "Jonas Schrieb",
|
||||
"target": "^https?://eccc\\.weizmann\\.ac\\.il/",
|
||||
"creator": "Jonas Schrieb and Morgan Shirley",
|
||||
"target": "^https?://eccc\\.weizmann\\.ac\\.il/(title|year|keyword|report|search)",
|
||||
"minVersion": "1.0.0b3.r1",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsib",
|
||||
"lastUpdated": "2017-01-05 17:11:41"
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-08-14 06:03:23"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Jonas Schrieb and Morgan Shirley
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
const preprintType = ZU.fieldIsValidForType('title', 'preprint')
|
||||
? 'preprint'
|
||||
: 'report';
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('a[href^="/report/"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = text(row, "h4");
|
||||
if (!href || !title) continue;
|
||||
if (checkOnly) return true;
|
||||
found = true;
|
||||
items[href] = title;
|
||||
}
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
var singleRe = /^https?:\/\/eccc\.weizmann\.ac\.il\/report\/\d{4}\/\d{3}/;
|
||||
var multipleRe = /^https?:\/\/eccc\.weizmann\.ac\.il\/(title|year|keyword)\//;
|
||||
if (singleRe.test(url)) {
|
||||
return "report";
|
||||
} else if (multipleRe.test(url)) {
|
||||
return "multiple";
|
||||
var multipleRe = /^https?:\/\/eccc\.weizmann\.ac\.il\/(title|year|keyword|search)\//;
|
||||
var singleRe = /^https?:\/\/eccc\.weizmann\.ac\.il\/report\//;
|
||||
if (multipleRe.test(url)) {
|
||||
return getSearchResults(doc, true) && "multiple";
|
||||
}
|
||||
else if (singleRe.test(url)) {
|
||||
return preprintType;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
function scrape(doc) {
|
||||
var newItem = new Zotero.Item("report");
|
||||
|
||||
var url = doc.location.href;
|
||||
var tmp = url.match(/\/(\d{4})\/(\d{3})\/$/);
|
||||
newItem.date = tmp[1];
|
||||
newItem.reportNumber = tmp[2];
|
||||
newItem.url = url;
|
||||
async function scrape(doc, url = doc.location.href) {
|
||||
let translator = Zotero.loadTranslator('web');
|
||||
// Embedded Metadata
|
||||
translator.setTranslator('951c027d-74ac-47d4-a107-9c3069ab7b48');
|
||||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', (_obj, item) => {
|
||||
item.publisher = "Electronic Colloquium on Computational Complexity";
|
||||
|
||||
|
||||
var titleXPath = "id('box')//h4";
|
||||
newItem.title = doc.evaluate(titleXPath, doc, null, XPathResult.ANY_TYPE, null).iterateNext().textContent;
|
||||
|
||||
|
||||
|
||||
var authorsXPath = "id('box')//a[contains(@href,'author')]";
|
||||
var authors = doc.evaluate(authorsXPath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var nextAuthor;
|
||||
while (nextAuthor = authors.iterateNext()) {
|
||||
newItem.creators.push(Zotero.Utilities.cleanAuthor(nextAuthor.textContent, "author"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
var keywordsXPath = "id('box')//a[contains(@href,'keyword')]";
|
||||
var keywords = doc.evaluate(keywordsXPath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var nextKeyword;
|
||||
var i = 0;
|
||||
while (nextKeyword = keywords.iterateNext()) {
|
||||
newItem.tags[i++] = nextKeyword.textContent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var abstractXPath = "id('box')/text()";
|
||||
var abstractLines = doc.evaluate(abstractXPath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
newItem.abstractNote = "";
|
||||
var nextLine;
|
||||
while (nextLine = abstractLines.iterateNext()) {
|
||||
newItem.abstractNote += nextLine.textContent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
newItem.attachments = [
|
||||
{url:url, title:"ECCC Snapshot", mimeType:"text/html"},
|
||||
{url:url+"download", title:"ECCC Full Text PDF", mimeType:"application/pdf"}
|
||||
];
|
||||
|
||||
newItem.complete();
|
||||
}
|
||||
|
||||
function doWeb(doc, url) {
|
||||
var articles = new Array();
|
||||
var items = new Object();
|
||||
var nextTitle;
|
||||
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
var titleXPath = "//a[starts-with(@href,'/report/')]/h4";
|
||||
var linkXPath = "//a[starts-with(@href,'/report/')][h4]";
|
||||
|
||||
var titles = doc.evaluate(titleXPath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
var links = doc.evaluate(linkXPath, doc, null, XPathResult.ANY_TYPE, null);
|
||||
while (nextTitle = titles.iterateNext()) {
|
||||
nextLink = links.iterateNext();
|
||||
items[nextLink.href] = nextTitle.textContent;
|
||||
// Keywords and abstract are not in the metadata; scrape from webpage
|
||||
var keywords = doc.querySelectorAll("#box a[href^='/keyword/']");
|
||||
for (let i = 0; i < keywords.length; i++) {
|
||||
item.tags[i] = keywords[i].textContent;
|
||||
}
|
||||
Zotero.selectItems(items, function (items) {
|
||||
if (!items) {
|
||||
Zotero.done();
|
||||
}
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
} else {
|
||||
scrape(doc, url)
|
||||
}
|
||||
|
||||
var abstractParagraphs = doc.querySelectorAll("#box p");
|
||||
item.abstractNote = "";
|
||||
for (let i = 0; i < abstractParagraphs.length; i++) {
|
||||
item.abstractNote += abstractParagraphs[i].innerText + "\n";
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
|
||||
let em = await translator.getTranslatorObject();
|
||||
em.itemType = preprintType;
|
||||
await em.doWeb(doc, url);
|
||||
}
|
||||
/** BEGIN TEST CASES **/
|
||||
|
||||
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://eccc.weizmann.ac.il/report/2006/067/",
|
||||
"detectedItemType": "preprint",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"itemType": "preprint",
|
||||
"title": "On the Impact of Combinatorial Structure on Congestion Games",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Heiner",
|
||||
|
|
@ -128,39 +132,98 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"tags": [
|
||||
"Combinatorial Structure",
|
||||
"Congestion Games",
|
||||
"Convergence Time",
|
||||
"PLS-Completeness"
|
||||
],
|
||||
"seeAlso": [],
|
||||
"date": "2006/5/28",
|
||||
"abstractNote": "We study the impact of combinatorial structure in congestion games on the complexity of computing pure Nash equilibria and the convergence time of best response sequences. In particular, we investigate which properties of the strategy spaces of individual players ensure a polynomial convergence time. We show, if the strategy space of each player consists of the bases of a matroid over the set of resources, then the lengths of all best response sequences are polynomially bounded in the number of players and resources. We can also prove that this result is tight, that is, the matroid property is a necessary and sufficient condition on the players' strategy spaces for guaranteeing polynomial time convergence to a Nash equilibrium. In addition, we present an approach that enables us to devise hardness proofs for various kinds of combinatorial games, including first results about the hardness of market sharing games and congestion games for overlay network design. Our approach also yields a short proof for the PLS-completeness of network congestion games.",
|
||||
"archiveID": "TR06-067",
|
||||
"language": "en",
|
||||
"libraryCatalog": "eccc.weizmann.ac.il",
|
||||
"repository": "Electronic Colloquium on Computational Complexity",
|
||||
"url": "https://eccc.weizmann.ac.il/report/2006/067/",
|
||||
"attachments": [
|
||||
{
|
||||
"url": "https://eccc.weizmann.ac.il/report/2006/067/",
|
||||
"title": "ECCC Snapshot",
|
||||
"mimeType": "text/html"
|
||||
},
|
||||
{
|
||||
"url": "https://eccc.weizmann.ac.il/report/2006/067/download",
|
||||
"title": "ECCC Full Text PDF",
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"date": "2006",
|
||||
"reportNumber": "067",
|
||||
"url": "https://eccc.weizmann.ac.il/report/2006/067/",
|
||||
"title": "On the Impact of Combinatorial Structure on Congestion Games",
|
||||
"abstractNote": "",
|
||||
"libraryCatalog": "Electronic Colloquium on Computational Complexity",
|
||||
"accessDate": "CURRENT_TIMESTAMP"
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Combinatorial Structure"
|
||||
},
|
||||
{
|
||||
"tag": "Congestion Games"
|
||||
},
|
||||
{
|
||||
"tag": "Convergence Time"
|
||||
},
|
||||
{
|
||||
"tag": "PLS-Completeness"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://eccc.weizmann.ac.il/keyword/13486/",
|
||||
"url": "https://eccc.weizmann.ac.il/report/2007/112/",
|
||||
"detectedItemType": "preprint",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "preprint",
|
||||
"title": "Unbounded-Error Communication Complexity of Symmetric Functions",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Alexander A.",
|
||||
"lastName": "Sherstov",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2007/11/12",
|
||||
"abstractNote": "The sign-rank of a real matrix M is the least rank\nof a matrix R in which every entry has the same sign as the\ncorresponding entry of M. We determine the sign-rank of every\nmatrix of the form M=[ D(|x AND y|) ]_{x,y}, where\nD:{0,1,...,n}->{-1,+1} is given and x and y range over {0,1}^n.\nSpecifically, we prove that the sign-rank of M equals\n2^{\\tilde Theta(k)}, where k is the number of times D changes\nsign in {0,1,...,n}.\nPut differently, we prove an optimal lower bound\non the unbounded-error communication complexity of every\nsymmetric function, i.e., a function of the form\nf(x,y)=D(|x AND y|) for some D. The unbounded-error model is\nessentially the most powerful of all models of communication\n(both classical and quantum), and proving lower bounds in it\nis a substantial challenge. The only previous nontrivial lower\nbounds for this model appear in the groundbreaking work of\nForster (2001) and its extensions. As corollaries to our\nresult, we give new lower bounds for PAC learning and for\nthreshold-of-majority circuits.\nThe technical content of our proof is diverse and\nfeatures random walks on (Z_2)^n, discrete approximation theory,\nthe Fourier transform on (Z_2)^n, linear-programming duality,\nand matrix analysis.",
|
||||
"archiveID": "TR07-112",
|
||||
"language": "en",
|
||||
"libraryCatalog": "eccc.weizmann.ac.il",
|
||||
"repository": "Electronic Colloquium on Computational Complexity",
|
||||
"url": "https://eccc.weizmann.ac.il/report/2007/112/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Communication complexity"
|
||||
},
|
||||
{
|
||||
"tag": "Sign-rank"
|
||||
},
|
||||
{
|
||||
"tag": "Unbounded-error communication complexity"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://eccc.weizmann.ac.il/search/?search=combinatorial",
|
||||
"detectedItemType": "multiple",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://eccc.weizmann.ac.il/search/?search=asdf",
|
||||
"detectedItemType": false,
|
||||
"items": []
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://eccc.weizmann.ac.il/keyword/14114/",
|
||||
"detectedItemType": "multiple",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-04-24 14:42:56"
|
||||
"lastUpdated": "2025-10-14 17:29:56"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -179,7 +179,9 @@ function getContentText(doc, name, strict, all) {
|
|||
}
|
||||
|
||||
function getContent(doc, name, strict) {
|
||||
var xpath = '/x:html/x:head/x:meta['
|
||||
var xpath = '/x:html'
|
||||
+ '/*[local-name() = "head" or local-name() = "body"]'
|
||||
+ '/x:meta['
|
||||
+ (strict ? '@name' : 'substring(@name, string-length(@name)-' + (name.length - 1) + ')')
|
||||
+ '="' + name + '"]/';
|
||||
return ZU.xpath(doc, xpath + '@content | ' + xpath + '@contents', namespaces);
|
||||
|
|
@ -234,25 +236,15 @@ function detectWeb(doc, url) {
|
|||
function init(doc, url, callback, forceLoadRDF) {
|
||||
getPrefixes(doc);
|
||||
|
||||
var metaTags = doc.head.getElementsByTagName("meta");
|
||||
Z.debug("Embedded Metadata: found " + metaTags.length + " meta tags.");
|
||||
var metaTags = doc.querySelectorAll("meta");
|
||||
Z.debug("Embedded Metadata: found " + metaTags.length + " meta tags");
|
||||
if (forceLoadRDF /* check if this is called from doWeb */ && !metaTags.length) {
|
||||
if (doc.head) {
|
||||
Z.debug(doc.head.innerHTML
|
||||
.replace(/<style[^<]+(?:<\/style>|\/>)/ig, '')
|
||||
.replace(/<link[^>]+>/ig, '')
|
||||
.replace(/(?:\s*[\r\n]\s*)+/g, '\n')
|
||||
);
|
||||
}
|
||||
else {
|
||||
Z.debug("Embedded Metadata: No head tag");
|
||||
}
|
||||
Z.debug("Embedded Metadata: No meta tags found");
|
||||
}
|
||||
|
||||
var hwType, hwTypeGuess, generatorType, statements = [];
|
||||
var hwType, hwTypeGuess, generatorType, heuristicType, statements = [];
|
||||
|
||||
for (let i = 0; i < metaTags.length; i++) {
|
||||
let metaTag = metaTags[i];
|
||||
for (let metaTag of metaTags) {
|
||||
// Two formats allowed:
|
||||
// <meta name="..." content="..." />
|
||||
// <meta property="..." content="..." />
|
||||
|
|
@ -334,6 +326,11 @@ function init(doc, url, callback, forceLoadRDF) {
|
|||
}
|
||||
}
|
||||
|
||||
// WordPress indicators:
|
||||
if (doc.getElementById("wp-block-library-css") || doc.getElementsByClassName("yoast-schema-graph").length) {
|
||||
heuristicType = "blogPost";
|
||||
}
|
||||
|
||||
if (statements.length || forceLoadRDF) {
|
||||
// load RDF translator, so that we don't need to replicate import code
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
|
|
@ -350,7 +347,7 @@ function init(doc, url, callback, forceLoadRDF) {
|
|||
rdf.Zotero.RDF.addStatement(statement[0], statement[1], statement[2], true);
|
||||
}
|
||||
var nodes = rdf.getNodes(true);
|
||||
rdf.defaultUnknownType = hwTypeGuess || generatorType
|
||||
rdf.defaultUnknownType = hwTypeGuess || generatorType || heuristicType
|
||||
// if we have RDF data, then default to webpage
|
||||
|| (nodes.length ? "webpage" : false);
|
||||
|
||||
|
|
@ -581,16 +578,24 @@ function processHighwireCreators(creatorNodes, role, doc) {
|
|||
/* If there is only one author node and
|
||||
we get nothing when splitting by semicolon, there are at least two
|
||||
words on either side of a comma, and it doesn't appear to be a
|
||||
two-word Spanish surname, we split by comma. */
|
||||
Spanish surname, we split by comma. */
|
||||
|
||||
let lang = getContentText(doc, 'citation_language');
|
||||
let twoWordName = authorsByComma.length == 2
|
||||
let spanishName = authorsByComma.length == 2
|
||||
&& ['es', 'spa', 'Spanish', 'español'].includes(lang)
|
||||
&& authorsByComma[0].split(' ').length == 2;
|
||||
&& (
|
||||
// If it's a Spanish-language item and the text before the comma
|
||||
// has exactly two words, this is very probably a single Spanish name
|
||||
authorsByComma[0].split(' ').length == 2
|
||||
// If the text before the comma has more than two words, we can't be
|
||||
// sure, but we'll take it if there's an accented character or a
|
||||
// "de" particle (this is not great)
|
||||
|| authorsByComma[0].split(' ').length > 2 && /[À-ú]|\b[Dd]e\b/u.test(authorsByComma[0])
|
||||
);
|
||||
if (authorsByComma.length > 1
|
||||
&& authorsByComma[0].includes(" ")
|
||||
&& authorsByComma[1].includes(" ")
|
||||
&& !twoWordName) creators = authorsByComma;
|
||||
&& !spanishName) creators = authorsByComma;
|
||||
}
|
||||
|
||||
for (let creator of creators) {
|
||||
|
|
@ -683,7 +688,8 @@ function addLowQualityMetadata(doc, newItem) {
|
|||
Array.from(doc.querySelectorAll('meta[name="author" i], meta[property="author" i]'))
|
||||
.map(authorNode => authorNode.content)
|
||||
.filter(content => content && /[^\s,-.;]/.test(content)));
|
||||
if (w3authors.size) {
|
||||
// Condé Nast is a company, not an author
|
||||
if (w3authors.size && !(w3authors.size == 1 && w3authors.has("Condé Nast"))) {
|
||||
for (let author of w3authors) {
|
||||
newItem.creators.push(ZU.cleanAuthor(author, "author"));
|
||||
}
|
||||
|
|
@ -707,7 +713,7 @@ function addLowQualityMetadata(doc, newItem) {
|
|||
}
|
||||
|
||||
if (!newItem.url) {
|
||||
newItem.url = ZU.xpathText(doc, '//head/link[@rel="canonical"]/@href') || doc.location.href;
|
||||
newItem.url = attr(doc, 'head > link[rel="canonical"]', 'href') || doc.location.href;
|
||||
}
|
||||
|
||||
if (!newItem.language) {
|
||||
|
|
@ -736,7 +742,7 @@ function tryOgAuthors(doc) {
|
|||
var authors = [];
|
||||
var ogAuthors = ZU.xpath(doc, '//meta[@property="article:author" or @property="video:director" or @property="music:musician"]');
|
||||
for (var i = 0; i < ogAuthors.length; i++) {
|
||||
if (ogAuthors[i].content && /(https?:\/\/)?[\da-z.-]+\.[a-z.]{2,6}/.test(ogAuthors[i].content) && ogAuthors[i].content !== "false") {
|
||||
if (ogAuthors[i].content && !/(https?:\/\/)?[\da-z.-]+\.[a-z.]{2,6}/.test(ogAuthors[i].content) && ogAuthors[i].content !== "false") {
|
||||
authors.push(ZU.cleanAuthor(ogAuthors[i].content, "author"));
|
||||
}
|
||||
}
|
||||
|
|
@ -747,13 +753,33 @@ function getAuthorFromByline(doc, newItem) {
|
|||
var bylineClasses = ['byline', 'bylines', 'vcard', 'article-byline'];
|
||||
Z.debug("Looking for authors in " + bylineClasses.join(', '));
|
||||
var bylines = [], byline;
|
||||
for (var i = 0; i < bylineClasses.length; i++) {
|
||||
byline = doc.getElementsByClassName(bylineClasses[i]);
|
||||
Z.debug("Found " + byline.length + " elements with '" + bylineClasses[i] + "' class");
|
||||
for (var j = 0; j < byline.length; j++) {
|
||||
if (!byline[j].innerText.trim()) continue;
|
||||
for (let isStrict of [true, false]) {
|
||||
for (let bylineClass of bylineClasses) {
|
||||
byline = isStrict
|
||||
? doc.getElementsByClassName(bylineClass)
|
||||
: doc.querySelectorAll(`[class*="${bylineClass}" i]`);
|
||||
Z.debug(`Found ${byline.length} elements with '${bylineClass}' class (strict: ${isStrict})`);
|
||||
for (let bylineElement of byline) {
|
||||
if (!bylineElement.innerText?.trim()) continue;
|
||||
if (bylines.includes(bylineElement)) continue;
|
||||
bylines.push(bylineElement);
|
||||
}
|
||||
|
||||
bylines.push(byline[j]);
|
||||
if (isStrict && bylines.length) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bylines.length) {
|
||||
let otherSelectors = ['a[rel="author"]'];
|
||||
|
||||
for (let selector of otherSelectors) {
|
||||
selector += ':not(:empty)';
|
||||
if (doc.querySelectorAll(selector).length == 1) {
|
||||
bylines.push(doc.querySelector(selector));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +852,9 @@ function getAuthorFromByline(doc, newItem) {
|
|||
}
|
||||
|
||||
if (ZU.xpath(bylineParent, titleXPath).length) {
|
||||
if (actualByline) {
|
||||
if (actualByline
|
||||
&& actualByline.textContent.trim().toLowerCase()
|
||||
!== bylines[i].textContent.trim().toLowerCase()) {
|
||||
// found more than one, bail
|
||||
Z.debug('More than one possible byline found. Will not proceed');
|
||||
return;
|
||||
|
|
@ -843,11 +871,11 @@ function getAuthorFromByline(doc, newItem) {
|
|||
// are any of these actual likely to appear in the real world?
|
||||
// well, no, but things happen:
|
||||
// https://github.com/zotero/translators/issues/2001
|
||||
let irrelevantTags = 'time, button, textarea, script';
|
||||
if (actualByline.querySelector(irrelevantTags)) {
|
||||
let irrelevantSelector = 'time, button, textarea, script, [class*="email"], [class*="date"]';
|
||||
if (actualByline.querySelector(irrelevantSelector)) {
|
||||
actualByline = actualByline.cloneNode(true);
|
||||
for (let child of actualByline.querySelectorAll(irrelevantTags)) {
|
||||
child.parentNode.removeChild(child);
|
||||
for (let child of [...actualByline.querySelectorAll(irrelevantSelector)]) {
|
||||
child.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1057,7 +1085,7 @@ var testCases = [
|
|||
"ISSN": "1821-9241",
|
||||
"abstractNote": "The synergistic interaction between Human Immunodeficiency virus (HIV) disease and Malaria makes it mandatory for patients with HIV to respond appropriately in preventing and treating malaria. Such response will help to control the two diseases. This study assessed the knowledge of 495 patients attending the HIV clinic, in Lagos University Teaching Hospital, Nigeria. Their treatment seeking, preventive practices with regards to malaria, as well as the impact of socio – demographic / socio - economic status were assessed. Out of these patients, 245 (49.5 %) used insecticide treated bed nets; this practice was not influenced by socio – demographic or socio – economic factors. However, knowledge of the cause, knowledge of prevention of malaria, appropriate use of antimalarial drugs and seeking treatment from the right source increased with increasing level of education (p < 0.05). A greater proportion of the patients, 321 (64.9 %) utilized hospitals, pharmacy outlets or health centres when they perceived an attack of malaria. Educational intervention may result in these patients seeking treatment from the right place when an attack of malaria fever is perceived.",
|
||||
"issue": "4",
|
||||
"journalAbbreviation": "1",
|
||||
"journalAbbreviation": "Tanzania J Hlth Res",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.ajol.info",
|
||||
"publicationTitle": "Tanzania Journal of Health Research",
|
||||
|
|
@ -1078,168 +1106,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://scholarworks.umass.edu/climate_nuclearpower/2011/nov19/34/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "conferencePaper",
|
||||
"title": "Session F: Contributed Oral Papers – F2: Energy, Climate, Nuclear Medicine: Reducing Energy Consumption and CO2 One Street Lamp at a Time",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Peter",
|
||||
"lastName": "Somssich",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2011",
|
||||
"abstractNote": "Why wait for federal action on incentives to reduce energy use and address Greenhouse Gas (GHG) reductions (e.g. CO2), when we can take personal actions right now in our private lives and in our communities? One such initiative by private citizens working with Portsmouth NH officials resulted in the installation of energy reducing lighting products on Court St. and the benefits to taxpayers are still coming after over 4 years of operation. This citizen initiative to save money and reduce CO2 emissions, while only one small effort, could easily be duplicated in many towns and cities. Replacing old lamps in just one street fixture with a more energy efficient (Non-LED) lamp has resulted after 4 years of operation ($\\sim $15,000 hr. life of product) in real electrical energy savings of $>$ {\\$}43. and CO2 emission reduction of $>$ 465 lbs. The return on investment (ROI) was less than 2 years. This is much better than any financial investment available today and far safer. Our street only had 30 such lamps installed; however, the rest of Portsmouth (population 22,000) has at least another 150 street lamp fixtures that are candidates for such an upgrade. The talk will also address other energy reduction measures that green the planet and also put more green in the pockets of citizens and municipalities.",
|
||||
"conferenceName": "Climate Change and the Future of Nuclear Power",
|
||||
"language": "en",
|
||||
"libraryCatalog": "scholarworks.umass.edu",
|
||||
"shortTitle": "Session F",
|
||||
"url": "https://scholarworks.umass.edu/climate_nuclearpower/2011/nov19/34",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://scholarworks.umass.edu/lov/vol2/iss1/2/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Wabanaki Resistance and Healing: An Exploration of the Contemporary Role of an Eighteenth Century Bounty Proclamation in an Indigenous Decolonization Process",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Bonnie D.",
|
||||
"lastName": "Newsom",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Jamie",
|
||||
"lastName": "Bissonette-Lewey",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2012",
|
||||
"DOI": "10.7275/R5KW5CXB",
|
||||
"ISSN": "1947-508X",
|
||||
"abstractNote": "The purpose of this paper is to examine the contemporary role of an eighteenth century bounty proclamation issued on the Penobscot Indians of Maine. We focus specifically on how the changing cultural context of the 1755 Spencer Phips Bounty Proclamation has transformed the document from serving as a tool for sanctioned violence to a tool of decolonization for the Indigenous peoples of Maine. We explore examples of the ways indigenous and non-indigenous people use the Phips Proclamation to illustrate past violence directed against Indigenous peoples. This exploration is enhanced with an analysis of the re-introduction of the Phips Proclamation using concepts of decolonization theory.",
|
||||
"issue": "1",
|
||||
"language": "en",
|
||||
"libraryCatalog": "scholarworks.umass.edu",
|
||||
"pages": "2",
|
||||
"publicationTitle": "Landscapes of Violence",
|
||||
"shortTitle": "Wabanaki Resistance and Healing",
|
||||
"url": "https://scholarworks.umass.edu/lov/vol2/iss1/2",
|
||||
"volume": "2",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://scholarworks.umass.edu/open_access_dissertations/508/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "thesis",
|
||||
"title": "Decision-Theoretic Meta-reasoning in Partially Observable and Decentralized Settings",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Alan Scott",
|
||||
"lastName": "Carlin",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2012",
|
||||
"abstractNote": "This thesis examines decentralized meta-reasoning. For a single agent or multiple agents, it may not be enough for agents to compute correct decisions if they do not do so in a timely or resource efficient fashion. The utility of agent decisions typically increases with decision quality, but decreases with computation time. The reasoning about one's computation process is referred to as meta-reasoning. Aspects of meta-reasoning considered in this thesis include the reasoning about how to allocate computational resources, including when to stop one type of computation and begin another, and when to stop all computation and report an answer. Given a computational model, this translates into computing how to schedule the basic computations that solve a problem. This thesis constructs meta-reasoning strategies for the purposes of monitoring and control in multi-agent settings, specifically settings that can be modeled by the Decentralized Partially Observable Markov Decision Process (Dec-POMDP). It uses decision theory to optimize computation for efficiency in time and space in communicative and non-communicative decentralized settings. Whereas base-level reasoning describes the optimization of actual agent behaviors, the meta-reasoning strategies produced by this thesis dynamically optimize the computational resources which lead to the selection of base-level behaviors.",
|
||||
"extra": "DOI: 10.7275/n8e9-xy93",
|
||||
"language": "en",
|
||||
"libraryCatalog": "scholarworks.umass.edu",
|
||||
"university": "University of Massachusetts Amherst",
|
||||
"url": "https://scholarworks.umass.edu/open_access_dissertations/508",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://scielosp.org/article/rsp/2007.v41suppl2/94-100/en/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Perceptions of HIV rapid testing among injecting drug users in Brazil",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "P. R.",
|
||||
"lastName": "Telles-Dias",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "S.",
|
||||
"lastName": "Westman",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "A. E.",
|
||||
"lastName": "Fernandez",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "M.",
|
||||
"lastName": "Sanchez",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2007-12",
|
||||
"DOI": "10.1590/S0034-89102007000900015",
|
||||
"ISSN": "0034-8910, 0034-8910, 1518-8787",
|
||||
"abstractNote": "OBJETIVO: Descrever as impressões, experiências, conhecimentos, crenças e a receptividade de usuários de drogas injetáveis para participar das estratégias de testagem rápida para HIV. MÉTODOS: Estudo qualitativo exploratório foi conduzido entre usuários de drogas injetáveis, de dezembro de 2003 a fevereiro de 2004, em cinco cidades brasileiras, localizadas em quatro regiões do País. Um roteiro de entrevista semi-estruturado contendo questões fechadas e abertas foi usado para avaliar percepções desses usuários sobre procedimentos e formas alternativas de acesso e testagem. Foram realizadas 106 entrevistas, aproximadamente 26 por região. RESULTADOS: Características da população estudada, opiniões sobre o teste rápido e preferências por usar amostras de sangue ou saliva foram apresentadas junto com as vantagens e desvantagens associadas a cada opção. Os resultados mostraram a viabilidade do uso de testes rápidos entre usuários de drogas injetáveis e o interesse deles quanto à utilização destes métodos, especialmente se puderem ser equacionadas questões relacionadas à confidencialidade e confiabilidade dos testes. CONCLUSÕES: Os resultados indicam que os testes rápidos para HIV seriam bem recebidos por essa população. Esses testes podem ser considerados uma ferramenta valiosa, ao permitir que mais usuários de drogas injetáveis conheçam sua sorologia para o HIV e possam ser referidos para tratamento, como subsidiar a melhoria das estratégias de testagem entre usuários de drogas injetáveis.",
|
||||
"journalAbbreviation": "Rev. Saúde Pública",
|
||||
"language": "en",
|
||||
"libraryCatalog": "scielosp.org",
|
||||
"pages": "94-100",
|
||||
"publicationTitle": "Revista de Saúde Pública",
|
||||
"url": "https://scielosp.org/article/rsp/2007.v41suppl2/94-100/en/",
|
||||
"volume": "41",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.hindawi.com/journals/mpe/2013/868174/",
|
||||
"url": "https://onlinelibrary.wiley.com/doi/10.1155/2013/868174",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
|
|
@ -1261,14 +1128,16 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2013/2/20",
|
||||
"date": "2013/01/01",
|
||||
"DOI": "10.1155/2013/868174",
|
||||
"ISSN": "1024-123X",
|
||||
"abstractNote": "The problem of network-based robust filtering for stochastic systems with sensor nonlinearity is investigated in this paper. In the network environment, the effects of the sensor saturation, output quantization, and network-induced delay are taken into simultaneous consideration, and the output measurements received in the filter side are incomplete. The random delays are modeled as a linear function of the stochastic variable described by a Bernoulli random binary distribution. The derived criteria for performance analysis of the filtering-error system and filter design are proposed which can be solved by using convex optimization method. Numerical examples show the effectiveness of the design method.",
|
||||
"ISSN": "1563-5147",
|
||||
"abstractNote": "The problem of network-based robust filtering for stochastic systems with sensor nonlinearity is investigated in this paper. In the network environment, the effects of the sensor saturation, output q...",
|
||||
"issue": "1",
|
||||
"language": "en",
|
||||
"libraryCatalog": "www.hindawi.com",
|
||||
"libraryCatalog": "onlinelibrary.wiley.com",
|
||||
"pages": "868174",
|
||||
"publicationTitle": "Mathematical Problems in Engineering",
|
||||
"url": "https://www.hindawi.com/journals/mpe/2013/868174/",
|
||||
"url": "https://onlinelibrary.wiley.com/doi/10.1155/2013/868174",
|
||||
"volume": "2013",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -1337,10 +1206,8 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-08-05T12:05:17Z",
|
||||
"abstractNote": "New research finds creativity benefits.",
|
||||
"language": "en",
|
||||
"url": "https://hbr.org/2015/08/how-to-do-walking-meetings-right",
|
||||
"websiteTitle": "Harvard Business Review",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -1379,6 +1246,7 @@ var testCases = [
|
|||
"language": "en",
|
||||
"libraryCatalog": "olh.openlibhums.org",
|
||||
"publicationTitle": "Open Library of Humanities",
|
||||
"rights": "Copyright: © 2015 The Author(s). This is an open-access article distributed under the terms of the Creative Commons Attribution 3.0 Unported License (CC-BY 3.0), which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited. See http://creativecommons.org/licenses/by/3.0/.",
|
||||
"url": "https://olh.openlibhums.org/article/id/4400/",
|
||||
"volume": "1",
|
||||
"attachments": [
|
||||
|
|
@ -1407,9 +1275,9 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2016-01-07T08:20:02-05:00",
|
||||
"date": "2016-01-07T13:20:02+00:00",
|
||||
"abstractNote": "Excluding female characters in merchandise is an ongoing pattern.",
|
||||
"language": "en",
|
||||
"language": "en-US",
|
||||
"url": "https://www.vox.com/2016/1/7/10726296/wheres-rey-star-wars-monopoly",
|
||||
"websiteTitle": "Vox",
|
||||
"attachments": [
|
||||
|
|
@ -1499,7 +1367,7 @@ var testCases = [
|
|||
"language": "eng",
|
||||
"libraryCatalog": "www.diva-portal.org",
|
||||
"shortTitle": "Mobility modeling for transport efficiency",
|
||||
"url": "http://urn.kb.se/resolve?urn=urn:nbn:se:liu:diva-112443",
|
||||
"url": "https://urn.kb.se/resolve?urn=urn:nbn:se:liu:diva-112443",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -1569,12 +1437,13 @@ var testCases = [
|
|||
"DOI": "10.1353/kri.2008.0061",
|
||||
"ISSN": "1538-5000",
|
||||
"issue": "4",
|
||||
"journalAbbreviation": "kri",
|
||||
"language": "en",
|
||||
"libraryCatalog": "muse.jhu.edu",
|
||||
"pages": "627-656",
|
||||
"publicationTitle": "Kritika: Explorations in Russian and Eurasian History",
|
||||
"shortTitle": "Serfs on the Move",
|
||||
"url": "https://muse.jhu.edu/article/234097",
|
||||
"url": "https://muse.jhu.edu/pub/28/article/234097",
|
||||
"volume": "1",
|
||||
"attachments": [
|
||||
{
|
||||
|
|
@ -1635,14 +1504,12 @@ var testCases = [
|
|||
],
|
||||
"date": "2015-06",
|
||||
"ISBN": "9788460842118",
|
||||
"abstractNote": "Abstracts aceptados sin presentacion / Accepted abstracts without presentation",
|
||||
"conferenceName": "International Conference Arquitectonics Network: Architecture, Education and Society, Barcelona, 3-5 June 2015: Abstracts",
|
||||
"language": "spa",
|
||||
"libraryCatalog": "upcommons.upc.edu",
|
||||
"publisher": "GIRAS. Universitat Politècnica de Catalunya",
|
||||
"rights": "Open Access",
|
||||
"shortTitle": "Necesidad y morfología",
|
||||
"url": "https://upcommons.upc.edu/handle/2117/114657",
|
||||
"url": "https://hdl.handle.net/2117/114657",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
|
|
@ -1657,7 +1524,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.pewresearch.org/fact-tank/2019/12/12/u-s-children-more-likely-than-children-in-other-countries-to-live-with-just-one-parent/",
|
||||
"url": "https://www.pewresearch.org/short-reads/2019/12/12/u-s-children-more-likely-than-children-in-other-countries-to-live-with-just-one-parent/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
|
|
@ -1669,10 +1536,11 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2019-12-12",
|
||||
"abstractNote": "Almost a quarter of U.S. children under 18 live with one parent and no other adults, more than three times the share of children around the world who do so.",
|
||||
"blogTitle": "Pew Research Center",
|
||||
"language": "en-US",
|
||||
"url": "https://www.pewresearch.org/fact-tank/2019/12/12/u-s-children-more-likely-than-children-in-other-countries-to-live-with-just-one-parent/",
|
||||
"url": "https://www.pewresearch.org/short-reads/2019/12/12/u-s-children-more-likely-than-children-in-other-countries-to-live-with-just-one-parent/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -1785,10 +1653,10 @@ var testCases = [
|
|||
"DOI": "10.3765/plsa.v4i1.4468",
|
||||
"ISSN": "2473-8689",
|
||||
"abstractNote": "Forced alignment automatically aligns audio recordings of spoken language with transcripts at the segment level, greatly reducing the time required to prepare data for phonetic analysis. However, existing algorithms are mostly trained on a few well-documented languages. We test the performance of three algorithms against manually aligned data. For at least some tasks, unsupervised alignment (either based on English or trained from a small corpus) is sufficiently reliable for it to be used on legacy data for low-resource languages. Descriptive phonetic work on vowel inventories and prosody can be accurately captured by automatic alignment with minimal training data. Consonants provided significantly more challenges for forced alignment.",
|
||||
"issue": "1",
|
||||
"journalAbbreviation": "Proc Ling Soc Amer",
|
||||
"language": "en",
|
||||
"libraryCatalog": "journals.linguisticsociety.org",
|
||||
"pages": "3-12",
|
||||
"pages": "3:1-12",
|
||||
"publicationTitle": "Proceedings of the Linguistic Society of America",
|
||||
"rights": "Copyright (c) 2019 Sarah Babinski, Rikker Dockum, J. Hunter Craft, Anelisa Fergus, Dolly Goldenberg, Claire Bowern",
|
||||
"shortTitle": "A Robin Hood approach to forced alignment",
|
||||
|
|
@ -1808,23 +1676,17 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.swr.de/wissen/1000-antworten/kultur/woher-kommt-redensart-ueber-die-wupper-gehen-100.html",
|
||||
"url": "https://www.swr.de/wissen/1000-antworten/woher-kommt-redensart-ueber-die-wupper-gehen-102.html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "Woher kommt \"über die Wupper gehen\"?",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "",
|
||||
"lastName": "SWRWissen",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2019-04-11",
|
||||
"abstractNote": "Es gibt eine Vergleichsredensart: \"Der ist über den Jordan gegangen.“ Das heißt, er ist gestorben. Das bezieht sich auf die alten Grenzen Israels. In Wuppertal jedoch liegt jenseits des Flusses das Gefängnis.",
|
||||
"creators": [],
|
||||
"date": "2024-03-05",
|
||||
"abstractNote": "Es gibt eine Vergleichsredensart: \"Der ist über den Jordan gegangen.\" Das heißt, er ist gestorben. Das bezieht sich auf die alten Grenzen Israels. In Wuppertal jedoch liegt jenseits des Flusses das Gefängnis. Von Rolf-Bernhard Essig",
|
||||
"language": "de",
|
||||
"url": "https://www.swr.de/wissen/1000-antworten/woher-kommt-redensart-ueber-die-wupper-gehen-100.html",
|
||||
"websiteTitle": "swr.online",
|
||||
"url": "https://www.swr.de/kultur/sprache/woher-kommt-redensart-ueber-die-wupper-gehen-102.html",
|
||||
"websiteTitle": "SWR",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
|
|
@ -1877,13 +1739,13 @@ var testCases = [
|
|||
"title": "Windows Privilege Escalation: Kernel Exploit",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Raj",
|
||||
"lastName": "Chandel",
|
||||
"firstName": "",
|
||||
"lastName": "Raj",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-12-30T17:41:33+00:00",
|
||||
"abstractNote": "As this series was dedicated to Windows Privilege escalation thus I’m writing this Post to explain command practice for kernel-mode exploitation. Table of Content What",
|
||||
"abstractNote": "Learn about kernel-mode exploitation techniques for Windows Privilege Escalation with Metasploit, ExploitDB, and more.",
|
||||
"blogTitle": "Hacking Articles",
|
||||
"language": "en",
|
||||
"shortTitle": "Windows Privilege Escalation",
|
||||
|
|
@ -1900,85 +1762,6 @@ var testCases = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://opg.optica.org/oe/fulltext.cfm?uri=oe-30-21-39188&id=509758",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Self-calibration interferometric stitching test method for cylindrical surfaces",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Hao",
|
||||
"lastName": "Hu",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Zizhou",
|
||||
"lastName": "Sun",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Shuai",
|
||||
"lastName": "Xue",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Chaoliang",
|
||||
"lastName": "Guan",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Yifan",
|
||||
"lastName": "Dai",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Junfeng",
|
||||
"lastName": "Liu",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Xiaoqiang",
|
||||
"lastName": "Peng",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Shanyong",
|
||||
"lastName": "Chen",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Yong",
|
||||
"lastName": "Liu",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2022/10/10",
|
||||
"DOI": "10.1364/OE.473836",
|
||||
"ISSN": "1094-4087",
|
||||
"abstractNote": "The surface figure accuracy requirement of cylindrical surfaces widely used in rotors of gyroscope, spindles of ultra-precision machine tools and high-energy laser systems is nearly 0.1 µm. Cylindricity measuring instrument that obtains 1-D profile result cannot be utilized for deterministic figuring methods. Interferometric stitching test for cylindrical surfaces utilizes a CGH of which the system error will accumulated to unacceptable extent for large aperture/angular aperture that require many subapertures. To this end, a self-calibration interferometric stitching method for cylindrical surfaces is proposed. The mathematical model of cylindrical surface figure and the completeness condition of self-calibration stitching test of cylindrical surfaces were analyzed theoretically. The effects of shear/stitching motion error and the subapertures lattice on the self-calibration test results were analyzed. Further, a self-calibration interferometric stitching algorithm that can theoretically recover all the necessary components of the system error for testing cylindrical surfaces was proposed. Simulations and experiments on a shaft were conducted to validate the feasibility.",
|
||||
"issue": "21",
|
||||
"journalAbbreviation": "Opt. Express, OE",
|
||||
"language": "EN",
|
||||
"libraryCatalog": "opg.optica.org",
|
||||
"pages": "39188-39206",
|
||||
"publicationTitle": "Optics Express",
|
||||
"rights": "© 2022 Optica Publishing Group",
|
||||
"url": "https://opg.optica.org/oe/abstract.cfm?uri=oe-30-21-39188",
|
||||
"volume": "30",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://themarkup.org/inside-the-markup/2023/01/18/five-ways-toward-a-fairer-more-transparent-hiring-process",
|
||||
|
|
@ -2008,6 +1791,188 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.nhs.uk/baby/babys-development/behaviour/separation-anxiety/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "Separation anxiety",
|
||||
"creators": [],
|
||||
"date": "7 Dec 2020, 4:40 p.m.",
|
||||
"abstractNote": "Separation anxiety is a normal part of your child's development. Find out how to handle the times when your baby or toddler cries or is clingy when you leave them.",
|
||||
"language": "en",
|
||||
"url": "https://www.nhs.uk/baby/babys-development/behaviour/separation-anxiety/",
|
||||
"websiteTitle": "nhs.uk",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.tatler.com/article/clodagh-mckenna-hon-harry-herbert-wedding-george-osborne-highclere-castle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "The Queen’s godson married glamorous Irish chef Clodagh McKenna at Highclere this weekend",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Annabel",
|
||||
"lastName": "Sampson",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-08-16T09:54:36.000Z",
|
||||
"abstractNote": "The Hon Harry Herbert, son of the 7th Earl of Carnarvon, married Clodagh McKenna in a fairytale wedding attended by everyone from George Osborne and his fiancée, Thea Rogers, to Laura Whitmore",
|
||||
"language": "en-GB",
|
||||
"url": "https://www.tatler.com/article/clodagh-mckenna-hon-harry-herbert-wedding-george-osborne-highclere-castle",
|
||||
"websiteTitle": "Tatler",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.timesofisrael.com/in-biggest-exit-in-israeli-history-google-buying-cyber-unicorn-wiz-for-32-billion/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "In biggest exit in Israeli history, Google buys cyber unicorn Wiz for $32 billion",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Sharon",
|
||||
"lastName": "Wrobel",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"abstractNote": "With the acquisition of Wiz, Google's parent company wants to strengthen its cyber offerings to better compete in the cloud computing race against tech giants Amazon and Microsoft",
|
||||
"language": "en-US",
|
||||
"url": "https://www.timesofisrael.com/in-biggest-exit-in-israeli-history-google-buying-cyber-unicorn-wiz-for-32-billion/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://minerva.usc.gal/entities/publication/9a4fd001-4717-428f-96a5-44812f8f3805",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "Contribución del análisis del líquido pleural al diagnóstico de los derrames pleurales",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "María Esther",
|
||||
"lastName": "San José Capilla",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2016-05-13",
|
||||
"abstractNote": "El derrame pleural es una complicación común en numerosas enfermedades, y el diagnóstico diferencial es frecuentemente difícil de obtener sin la utilización de técnicas invasivas, lo que se intenta evitar. Aunque hay una amplia variedad de pruebas de laboratorio, un porcentaje significativo de pacientes con derrame pleural permanecen sin diagnosticar, o el diagnóstico se basa exclusivamente en evidencias clínicas, como son la experiencia del clínico o la respuesta al tratamiento empírico; por lo que son necesarios estudiar nuevos parámetros que permitan un diagnóstico diferencial más preciso. El trabajo actual consiste en estudiar cómo podemos mejorar el diagnóstico de líquido pleural a partir de la toracocentesis diagnóstica y de una muestra de sangre periférica extraída en el mismo momento de la punción pleural. El punto inicial de la diferenciación de la patología pleural es la diferenciación trasudado/exudado, que se realiza tradicionalmente mediante los clásicos criterios de Light. No obstante, esta diferenciación sigue siendo objeto de controversia, por lo que estudiamos para dicho fin nuevos parámetros, como son las fracciones de Colesterol, la determinación de Triglicéridos o de N-terminal del propéptido natriurético cerebral. Una vez clasificado el derrame como exudado, los pasos siguientes incluyen la diferenciación de las distintas patologías que pueden estar implicadas en su desarrollo. Para ello, se utilizan los parámetros clásicos en líquido pleural y suero de Adenosina Desaminasa, Lactato Deshidrogenasa, pH, Glucosa, recuento total y diferencial de células nucleadas,…. . Después del despistaje habitual de las diferentes entidades, aún permanece un 5-10% de los derrames pleurales sin diagnosticar, por lo que intentamos estudiar nuevos enfoques, como son la determinación de citoquinas proinflamatorias para el estudio de derrames de causa infecciosa, así como el intento de diagnóstico de tuberculosis pleural mediante un estudio de regresión aplicando datos clínicos y de laboratorio para el diagnóstico de esta entidad en pacientes menores de 40 años, grupo de pacientes donde la incidencia de esta enfermedad es muy elevada. Asimismo, intentamos comprobar la utilidad de un método sencillo como es el recuento diferencial de las células nucleadas para clarificar las distintas patologías que acompañan al derrame pleural, y un estudio estadístico de rendimiento del análisis del líquido pleural, junto con los datos clínicos y radiográficos, como ayuda para el diagnóstico de esta patología, fundamentalmente orientado hacia el origen neoplásico del derrame pleural. Nuestra finalidad es facilitar el diagnóstico de las distintas patologías implicadas en la patogenia del derrame pleural, sin necesidad de tener que recurrir a procedimientos invasivos, como son la biopsia pleural, la videotoracoscopia,.., y evitar lo máximo posible las posibles complicaciones que conlleva un diagnóstico tardío de estos procesos.",
|
||||
"language": "spa",
|
||||
"libraryCatalog": "minerva.usc.gal",
|
||||
"url": "http://hdl.handle.net/10347/14743",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.statista.com/chart/13139/estimated-worldwide-mobile-e-commerce-sales/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "webpage",
|
||||
"title": "Infographic: Global Mobile E-Commerce Worth $2.2 Trillion in 2023",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Katharina",
|
||||
"lastName": "Buchholz",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-08-10",
|
||||
"abstractNote": "This chart shows estimated worldwide mobile e-commerce sales and their share in all e-commerce sales.",
|
||||
"language": "en",
|
||||
"shortTitle": "Infographic",
|
||||
"url": "https://www.statista.com/chart/13139/estimated-worldwide-mobile-e-commerce-sales",
|
||||
"websiteTitle": "Statista Daily Data",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://optimization-online.org/2023/05/maximum-likelihood-probability-measures-over-sets-and-applications-to-data-driven-optimization/",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "blogPost",
|
||||
"title": "Maximum Likelihood Probability Measures over Sets and Applications to Data-Driven Optimization – Optimization Online",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Juan",
|
||||
"lastName": "Borrero",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Denis",
|
||||
"lastName": "Saure",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-05-15",
|
||||
"language": "en-US",
|
||||
"url": "https://optimization-online.org/2023/05/maximum-likelihood-probability-measures-over-sets-and-applications-to-data-driven-optimization/",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2019-12-25 15:35:07"
|
||||
"lastUpdated": "2024-08-29 15:32:04"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -35,13 +35,11 @@
|
|||
***** 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;}
|
||||
let doiRe = /\/(10\.[^#?/]+\/[^#?/]+)\//;
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
// ensure that we only detect where scrape will (most likely) work
|
||||
if (url.includes('/content/doi/') && (url.search(/\/(10\.[^#?/]+\/[^#?/]+)\//) != -1 || url.includes("/full"))) {
|
||||
if (url.includes('/content/doi/') && doiRe.test(url)) {
|
||||
if (attr(doc, 'meta[name="dc.Type"]', 'content') == "book-part") {
|
||||
return "bookSection";
|
||||
}
|
||||
|
|
@ -78,36 +76,47 @@ function getSearchResults(doc, url, checkOnly) {
|
|||
}
|
||||
|
||||
|
||||
function doWeb(doc, url) {
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == "multiple") {
|
||||
Zotero.selectItems(getSearchResults(doc, url, false), function (items) {
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
var articles = [];
|
||||
for (var i in items) {
|
||||
articles.push(i);
|
||||
}
|
||||
ZU.processDocuments(articles, scrape);
|
||||
});
|
||||
let items = await Zotero.selectItems(getSearchResults(doc, url, false));
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
// requestDocument() doesn't yet set doc.cookie, so pass the parent doc's cookie
|
||||
await scrape(await requestDocument(url), url, doc.cookie);
|
||||
}
|
||||
}
|
||||
else {
|
||||
scrape(doc, url);
|
||||
await scrape(doc, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function scrape(doc, url) {
|
||||
var DOI = url.match(/\/(10\.[^#?/]+\/[^#?/]+)\//);
|
||||
var risURL;
|
||||
if (DOI) {
|
||||
risURL = "/insight/content/doi/" + DOI[1] + "/full/ris";
|
||||
async function scrape(doc, url, cookieFallback) {
|
||||
let response;
|
||||
let DOI = url.match(doiRe)[1];
|
||||
let cookie = doc.cookie || cookieFallback;
|
||||
let xsrfTokenMatch = cookie && cookie.match(/XSRF-TOKEN=([^;]+)/);
|
||||
if (xsrfTokenMatch) {
|
||||
let xsrfToken = xsrfTokenMatch[1];
|
||||
Z.debug('Using new API. XSRF token:');
|
||||
Z.debug(xsrfToken);
|
||||
|
||||
let risURL = "/insight/api/citations/format/ris?_xsrf=" + xsrfToken; // Already URL-encoded
|
||||
let body = JSON.stringify({ dois: [DOI] });
|
||||
response = await requestText(risURL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-XSRF-TOKEN': decodeURIComponent(xsrfToken)
|
||||
},
|
||||
body
|
||||
});
|
||||
}
|
||||
else {
|
||||
Z.debug("can't find DOI, trying alternative approach for risURL");
|
||||
risURL = url.replace(/\/full.*/, "/full/ris");
|
||||
Z.debug('Using old API');
|
||||
|
||||
let risURL = "/insight/content/doi/" + DOI + "/full/ris";
|
||||
response = await requestText(risURL);
|
||||
}
|
||||
// Z.debug(risURL);
|
||||
|
||||
var pdfURL;
|
||||
// make this works on PDF pages
|
||||
|
|
@ -118,66 +127,63 @@ function scrape(doc, url) {
|
|||
pdfURL = attr(doc, 'a.intent_pdf_link', 'href');
|
||||
}
|
||||
|
||||
// Z.debug("pdfURL: " + pdfURL);
|
||||
ZU.doGet(risURL, function (response) {
|
||||
// they number authors in their RIS...
|
||||
response = response.replace(/A\d+\s+-/g, "AU -");
|
||||
// they number authors in their RIS...
|
||||
response = response.replace(/^A\d+\s+-/gm, "AU -");
|
||||
|
||||
var abstract = doc.getElementById('abstract');
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
var tags = doc.querySelectorAll('li .intent_text');
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(response);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
var abstract = doc.getElementById('abstract');
|
||||
var translator = Zotero.loadTranslator("import");
|
||||
var tags = doc.querySelectorAll('li .intent_text');
|
||||
translator.setTranslator("32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7");
|
||||
translator.setString(response);
|
||||
translator.setHandler("itemDone", function (obj, item) {
|
||||
if (pdfURL) {
|
||||
item.attachments.push({
|
||||
url: pdfURL,
|
||||
title: "Full Text PDF",
|
||||
mimeType: "application/pdf"
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
|
||||
for (let tag of tags) {
|
||||
item.tags.push(tag.textContent);
|
||||
}
|
||||
|
||||
var authorsNodes = doc.querySelectorAll("div > a.contrib-search");
|
||||
if (authorsNodes.length > 0) {
|
||||
// prefer the authors information from the website as it contains the last and first name separately
|
||||
// where the RIS data does not separate them correctly (it uses a space instead of comma)
|
||||
// but the editors are only part of the RIS data
|
||||
var authors = [];
|
||||
for (let author of authorsNodes) {
|
||||
authors.push({
|
||||
firstName: text(author, "span.given-names"),
|
||||
lastName: text(author, "span.surname"),
|
||||
creatorType: "author"
|
||||
});
|
||||
}
|
||||
else {
|
||||
item.attachments.push({
|
||||
title: "Snapshot",
|
||||
document: doc
|
||||
});
|
||||
}
|
||||
|
||||
for (let tag of tags) {
|
||||
item.tags.push(tag.textContent);
|
||||
}
|
||||
|
||||
var authorsNodes = doc.querySelectorAll("div > a.contrib-search");
|
||||
if (authorsNodes.length > 0) {
|
||||
// prefer the authors information from the website as it contains the last and first name separately
|
||||
// where the RIS data does not separate them correctly (it uses a space instead of comma)
|
||||
// but the editors are only part of the RIS data
|
||||
var authors = [];
|
||||
for (let author of authorsNodes) {
|
||||
authors.push({
|
||||
firstName: text(author, "span.given-names"),
|
||||
lastName: text(author, "span.surname"),
|
||||
creatorType: "author"
|
||||
});
|
||||
}
|
||||
var otherContributors = item.creators.filter(creator => creator.creatorType !== "author");
|
||||
item.creators = otherContributors.length !== 0 ? authors.concat(separateNames(otherContributors)) : authors;
|
||||
}
|
||||
else {
|
||||
Z.debug("No tags available for authors");
|
||||
item.creators = separateNames(item.creators);
|
||||
}
|
||||
var otherContributors = item.creators.filter(creator => creator.creatorType !== "author");
|
||||
item.creators = otherContributors.length !== 0 ? authors.concat(separateNames(otherContributors)) : authors;
|
||||
}
|
||||
else {
|
||||
Z.debug("No tags available for authors");
|
||||
item.creators = separateNames(item.creators);
|
||||
}
|
||||
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
if (abstract) {
|
||||
item.abstractNote = ZU.trimInternal(abstract.textContent).replace(/^Abstract\s*/, "");
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
translator.translate();
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
}
|
||||
if (abstract) {
|
||||
item.abstractNote = ZU.trimInternal(abstract.textContent).replace(/^Abstract\s*/, "");
|
||||
}
|
||||
item.complete();
|
||||
});
|
||||
await translator.translate();
|
||||
}
|
||||
|
||||
function separateNames(creators) {
|
||||
|
|
@ -283,18 +289,18 @@ var testCases = [
|
|||
"creators": [
|
||||
{
|
||||
"lastName": "Menk",
|
||||
"creatorType": "author",
|
||||
"firstName": "K. Bryan"
|
||||
"firstName": "K. Bryan",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Malone",
|
||||
"creatorType": "author",
|
||||
"firstName": "Stephanie"
|
||||
"firstName": "Stephanie",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2015-01-01",
|
||||
"ISBN": "9781784415877 9781784415884",
|
||||
"abstractNote": "Originality/value This technique creates opportunities for students to have unique assignments encouraging student to student teaching and can be applied to assignments in any accounting course (undergraduate and graduate). This testing method has been used in Intermediate I and II, Individual Taxation, and Corporate Taxation.",
|
||||
"abstractNote": "Purpose The subject area of the assignment is accounting education and testing techniques. Methodology/approach This paper details an effective method to create individualized assignments and testing materials. Using a spreadsheet (Microsoft Excel), the creation of the unique assignments and answer keys can be semi-automated to reduce the grading difficulties of unique assignments. Findings Because students are using a unique data set for each assignment, the students are able to more effectively engage in student to student teaching. This process of unique assignments allows students to collaborate without fear that a single student would provide the answers. As tax laws (e.g., credit and deduction phase-outs, tax rates, and dependents) change depending on the level of income and other factors, an individualized test is ideal in a taxation course. Practical implications The unique assignments allow instructors to create markedly different scenarios for each student. Using this testing method requires that the student thoroughly understands the conceptual processes as the questions cannot be predicted. A list of supplementary materials is included, covering sample questions, conversion to codes, and sample assignment questions. Originality/value This technique creates opportunities for students to have unique assignments encouraging student to student teaching and can be applied to assignments in any accounting course (undergraduate and graduate). This testing method has been used in Intermediate I and II, Individual Taxation, and Corporate Taxation.",
|
||||
"bookTitle": "Advances in Accounting Education: Teaching and Curriculum Innovations",
|
||||
"extra": "DOI: 10.1108/S1085-462220150000016007",
|
||||
"libraryCatalog": "Emerald Insight",
|
||||
|
|
@ -306,7 +312,8 @@ var testCases = [
|
|||
"volume": "16",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -339,24 +346,24 @@ var testCases = [
|
|||
"title": "The influence of context upon consumer sensory evaluation of chicken‐meat quality",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Orla",
|
||||
"lastName": "Kennedy",
|
||||
"creatorType": "author",
|
||||
"firstName": "Orla"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Barbara",
|
||||
"lastName": "Stewart‐Knox",
|
||||
"creatorType": "author",
|
||||
"firstName": "Barbara"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Peter",
|
||||
"lastName": "Mitchell",
|
||||
"creatorType": "author",
|
||||
"firstName": "Peter"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "David",
|
||||
"lastName": "Thurnham",
|
||||
"creatorType": "author",
|
||||
"firstName": "David"
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2004-01-01",
|
||||
|
|
@ -371,8 +378,8 @@ var testCases = [
|
|||
"volume": "106",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -401,33 +408,33 @@ var testCases = [
|
|||
"creators": [
|
||||
{
|
||||
"lastName": "Kutz-Flamenbaum",
|
||||
"creatorType": "author",
|
||||
"firstName": "Rachel V."
|
||||
"firstName": "Rachel V.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Staggenborg",
|
||||
"creatorType": "author",
|
||||
"firstName": "Suzanne"
|
||||
"firstName": "Suzanne",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Duncan",
|
||||
"creatorType": "author",
|
||||
"firstName": "Brittany J."
|
||||
"firstName": "Brittany J.",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Earl",
|
||||
"creatorType": "editor",
|
||||
"firstName": "Jennifer"
|
||||
"firstName": "Jennifer",
|
||||
"creatorType": "editor"
|
||||
},
|
||||
{
|
||||
"lastName": "A. Rohlinger",
|
||||
"creatorType": "editor",
|
||||
"firstName": "Deana"
|
||||
"lastName": "Rohlinger",
|
||||
"firstName": "Deana A.",
|
||||
"creatorType": "editor"
|
||||
}
|
||||
],
|
||||
"date": "2012-01-01",
|
||||
"ISBN": "9781780528816 9781780528809",
|
||||
"abstractNote": "Research implications – We argue that events such as the G-20 meetings provide protesters with opportunities to gain temporary “standing” with the media. During such times, activists can use tactics and frames to alter the balance of power in relations with the media and the state and to attract positive media coverage, particularly when activists develop strategies that are not exclusively focused on the media. We argue that a combination of political opportunities and activist media strategies enabled protest organizers to position themselves as central figures in the G-20 news story and leverage that position to build media interest, develop relationships with reporters, and influence newspaper coverage.",
|
||||
"abstractNote": "Purpose – Movements typically have great difficulty using the mass media to spread their messages to the public, given the media's greater power to impose their frames on movement activities and goals. In this paper, we look at the impact of the political context and media strategies of protesters against the 2009 G-20 meetings in Pittsburgh on media coverage of the protests.Methodology – We employ field observations, interviews with activists and reporters, and a content analysis of print coverage of the demonstrations by the two local daily newspapers, the Pittsburgh Post-Gazette and the Pittsburgh Tribune-Review.Findings – We find that protesters were relatively successful in influencing how they were portrayed in local newspaper stories and in developing a sympathetic image of their groups’ members. Specifically, we find that activist frames were present in newspaper coverage and activists were quoted as frequently as city officials.Research implications – We argue that events such as the G-20 meetings provide protesters with opportunities to gain temporary “standing” with the media. During such times, activists can use tactics and frames to alter the balance of power in relations with the media and the state and to attract positive media coverage, particularly when activists develop strategies that are not exclusively focused on the media. We argue that a combination of political opportunities and activist media strategies enabled protest organizers to position themselves as central figures in the G-20 news story and leverage that position to build media interest, develop relationships with reporters, and influence newspaper coverage.",
|
||||
"bookTitle": "Media, Movements, and Political Change",
|
||||
"extra": "DOI: 10.1108/S0163-786X(2012)0000033008",
|
||||
"libraryCatalog": "Emerald Insight",
|
||||
|
|
@ -438,7 +445,8 @@ var testCases = [
|
|||
"volume": "33",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -475,29 +483,29 @@ var testCases = [
|
|||
"title": "Tourism research in Spain: The contribution of geography (1960–1995)",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Salvador",
|
||||
"lastName": "Antón i Clavé",
|
||||
"creatorType": "author",
|
||||
"firstName": "Salvador"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Francisco",
|
||||
"lastName": "López Palomeque",
|
||||
"creatorType": "author",
|
||||
"firstName": "Francisco"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Manuel J.",
|
||||
"lastName": "Marchena Gómez",
|
||||
"creatorType": "author",
|
||||
"firstName": "Manuel J."
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Sevilla",
|
||||
"lastName": "Vera Rebollo",
|
||||
"creatorType": "author",
|
||||
"firstName": "Sevilla"
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "J.",
|
||||
"lastName": "Fernando Vera Rebollo",
|
||||
"creatorType": "author",
|
||||
"firstName": "J."
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "1996-01-01",
|
||||
|
|
@ -513,8 +521,8 @@ var testCases = [
|
|||
"volume": "51",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
|
|
@ -547,6 +555,72 @@ var testCases = [
|
|||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.emerald.com/insight/content/doi/10.1108/JACPR-02-2022-0685/full/html",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "journalArticle",
|
||||
"title": "A multi-level, time-series network analysis of the impact of youth peacebuilding on quality peace",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Laura K.",
|
||||
"lastName": "Taylor",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"firstName": "Celia",
|
||||
"lastName": "Bähr",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2023-01-01",
|
||||
"DOI": "10.1108/JACPR-02-2022-0685",
|
||||
"ISSN": "1759-6599",
|
||||
"abstractNote": "Purpose Over 60% of armed conflicts re-occur; the seed of future conflict is sown even as a peace agreement is signed. The cyclical nature of war calls for a focus on youth who can disrupt this pattern over time. Addressing this concern, the developmental peace-building model calls for a dynamic, multi-level and longitudinal approach. Using an innovative statistical approach, this study aims to investigate the associations among four youth peace-building dimensions and quality peace. Design/methodology/approach Multi-level time-series network analysis of a data set containing 193 countries and spanning the years between 2011 and 2020 was performed. This statistical approach allows for complex modelling that can reveal new patterns of how different youth peace-building dimensions (i.e. education, engagement, information, inclusion), identified through rapid evidence assessment, promote quality peace over time. Such a methodology not only assesses between-country differences but also within-country change. Findings While the within-country contemporaneous network shows positive links for education, the temporal network shows significant lagged effects for all four dimensions on quality peace. The between-country network indicates significant direct effects of education and information, on average, and indirect effects of inclusion and engagement, on quality peace. Originality/value This approach demonstrates a novel application of multi-level time-series network analysis to explore the dynamic development of quality peace, capturing both stability and change. The analysis illustrates how youth peace-building dimensions impact quality peace in the macro-system globally. This investigation of quality peace thus illustrates that the science of peace does not necessitate violent conflict.",
|
||||
"issue": "2",
|
||||
"libraryCatalog": "Emerald Insight",
|
||||
"pages": "109-123",
|
||||
"publicationTitle": "Journal of Aggression, Conflict and Peace Research",
|
||||
"url": "https://doi.org/10.1108/JACPR-02-2022-0685",
|
||||
"volume": "15",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Developmental peace-building model"
|
||||
},
|
||||
{
|
||||
"tag": "Education"
|
||||
},
|
||||
{
|
||||
"tag": "Engagement"
|
||||
},
|
||||
{
|
||||
"tag": "Inclusion"
|
||||
},
|
||||
{
|
||||
"tag": "Information"
|
||||
},
|
||||
{
|
||||
"tag": "Quality peace"
|
||||
},
|
||||
{
|
||||
"tag": "Time-series network analysis"
|
||||
},
|
||||
{
|
||||
"tag": "Youth peacebuilding"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,221 @@
|
|||
{
|
||||
"translatorID": "dc879929-ae39-45b3-b49b-dab2c80815ab",
|
||||
"label": "Encyclopedia of Korean Culture",
|
||||
"creator": "jacoblee36251",
|
||||
"target": "^https?://(www\\.)?encykorea\\.aks\\.ac\\.kr/Article/",
|
||||
"minVersion": "5.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2023-09-15 20:07:33"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 jacoblee36251
|
||||
|
||||
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 (/^https?:\/\/[^/]+\/Article\/E\d+/.test(url)) {
|
||||
return 'encyclopediaArticle';
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return 'multiple';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
var rows = doc.querySelectorAll('li.item > a[href^="/Article/E"]');
|
||||
for (let row of rows) {
|
||||
let href = row.href;
|
||||
let title = ZU.trimInternal(row.querySelector('div.title').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) {
|
||||
var item = new Zotero.Item('encyclopediaArticle');
|
||||
|
||||
item.title = ZU.trimInternal(text(doc, ".content-head-title"));
|
||||
item.encyclopediaTitle = "한국민족문화대백과사전 [Encyclopedia of Korean Culture]";
|
||||
item.publisher = "Academy of Korean Studies";
|
||||
item.language = "ko";
|
||||
// Clean url by removing # terms
|
||||
item.url = url.replace(/#.*/, "");
|
||||
|
||||
// Author processing; may be 0 or more names, would be in Korean
|
||||
var authors = doc.querySelector('div.author-wrap > span');
|
||||
|
||||
if (authors) {
|
||||
authors = authors.textContent;
|
||||
// For simplicity, assume one character surnames for everybody (there are rare exceptions)
|
||||
for (let author of authors.split('·')) {
|
||||
item.creators.push({
|
||||
lastName: author[0],
|
||||
firstName: author.slice(1),
|
||||
creatorType: "author"
|
||||
});
|
||||
}
|
||||
}
|
||||
item.attachments.push({ title: "Snapshot", document: doc, mimeType: "text/html" });
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0013414#cm_multimedia",
|
||||
"detectedItemType": "encyclopediaArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "다대포 (多大浦)",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "오",
|
||||
"firstName": "건환",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "김",
|
||||
"firstName": "건유",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"encyclopediaTitle": "한국민족문화대백과사전 [Encyclopedia of Korean Culture]",
|
||||
"language": "ko",
|
||||
"libraryCatalog": "Encyclopedia of Korean Culture",
|
||||
"publisher": "Academy of Korean Studies",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0013414",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0002855",
|
||||
"detectedItemType": "encyclopediaArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "경주 남산 탑곡 마애불상군 (慶州 南山 塔谷 磨崖佛像群)",
|
||||
"creators": [],
|
||||
"encyclopediaTitle": "한국민족문화대백과사전 [Encyclopedia of Korean Culture]",
|
||||
"language": "ko",
|
||||
"libraryCatalog": "Encyclopedia of Korean Culture",
|
||||
"publisher": "Academy of Korean Studies",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0002855",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0025488",
|
||||
"detectedItemType": "encyclopediaArticle",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "encyclopediaArticle",
|
||||
"title": "사랑 (舍廊)",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "김",
|
||||
"firstName": "동욱",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"encyclopediaTitle": "한국민족문화대백과사전 [Encyclopedia of Korean Culture]",
|
||||
"language": "ko",
|
||||
"libraryCatalog": "Encyclopedia of Korean Culture",
|
||||
"publisher": "Academy of Korean Studies",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/E0025488",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Snapshot",
|
||||
"mimeType": "text/html"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/Search/%ED%95%99%EC%9B%90?field=&type=&alias=false&body=false&containdesc=false&keyword=%ED%95%99%EC%9B%90",
|
||||
"detectedItemType": "multiple",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/List/Field/%EC%98%88%EC%88%A0%C2%B7%EC%B2%B4%EC%9C%A1%3E%EC%A1%B0%EA%B0%81",
|
||||
"detectedItemType": "multiple",
|
||||
"items": "multiple"
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://encykorea.aks.ac.kr/Article/List/Type/%EC%9C%A0%EC%A0%81",
|
||||
"detectedItemType": "multiple",
|
||||
"items": "multiple"
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
{
|
||||
"translatorID": "0f6f5164-b44b-4ef6-9c5e-e3f39637569b",
|
||||
"label": "Envidat",
|
||||
"creator": "Alain Borel",
|
||||
"target": "^https://(www\\.)?envidat.ch/",
|
||||
"minVersion": "6.0",
|
||||
"maxVersion": "",
|
||||
"priority": 100,
|
||||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2025-04-29 03:02:00"
|
||||
}
|
||||
|
||||
/*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright © 2023 Alain Borel
|
||||
|
||||
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 *****
|
||||
*/
|
||||
|
||||
// A search query in the frontend will be converted to a query for:
|
||||
// all the words in the title or the notes
|
||||
// OR all possible single-word queries in the title or notes
|
||||
let possibleCombinations = (str) => {
|
||||
let combinations = ['%22*' + str.split(' ').join('%20') + '*%22~2'];
|
||||
let terms = str.match(/\S+/g);
|
||||
for (let i = 0; i < terms.length; i++) {
|
||||
combinations.push('%22*' + terms[i] + '*%22');
|
||||
}
|
||||
return combinations;
|
||||
};
|
||||
|
||||
// create the search URL for the API using an array of possible combinations
|
||||
let apiQuery = (arr) => {
|
||||
const finalParams = '&wt=json&rows=1000&fq=capacity:public&fq=state:active';
|
||||
let subterms = [];
|
||||
for (let k = 0; k < arr.length; k++) {
|
||||
subterms.push('title:' + arr[k]);
|
||||
subterms.push('notes:' + arr[k]);
|
||||
}
|
||||
return 'q=' + subterms.join('%20OR%20') + finalParams;
|
||||
};
|
||||
|
||||
function detectWeb(doc, url) {
|
||||
if (url.includes('/#/metadata/') || url.includes('/dataset/')) {
|
||||
return 'dataset';
|
||||
}
|
||||
else if (url.includes('/#/browse?')) {
|
||||
Zotero.debug('This should be multiple objects');
|
||||
return 'multiple';
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
async function getSearchResults(doc, checkOnly) {
|
||||
var items = {};
|
||||
var found = false;
|
||||
|
||||
// https://www.envidat.ch/#/browse?search=rock%20snow
|
||||
// => https://www.envidat.ch/query?q=title:%22*rock%20snow*%22~2%20OR%20notes:%22*rock%20snow*%22~2%20OR%20title:%20%22*rock*%22%20OR%20notes:%20%22*rock*%22%20OR%20title:%20%22*snow*%22%20OR%20notes:%20%22*snow*%22&wt=json&rows=1000&fq=capacity:public&fq=state:active
|
||||
// tags are used at frontend level: https://www.envidat.ch/#/browse?search=rock%20snow&tags=FOREST&isAuthorSearch=false
|
||||
// => same call
|
||||
let queryString = doc.location.href.replace('https://www.envidat.ch/#/browse', '');
|
||||
let urlParams = new URLSearchParams(queryString);
|
||||
let query = urlParams.get('search');
|
||||
let tags = urlParams.get('tags');
|
||||
if (tags) {
|
||||
tags = tags.split(',');
|
||||
}
|
||||
else {
|
||||
tags = [];
|
||||
}
|
||||
|
||||
let termCombinations = possibleCombinations(query);
|
||||
let myQuery = apiQuery(termCombinations);
|
||||
|
||||
let searchApiUrl = 'https://www.envidat.ch/query?' + myQuery;
|
||||
let { response: rsp } = await requestJSON(searchApiUrl);
|
||||
|
||||
let href;
|
||||
let title;
|
||||
if (rsp.docs) {
|
||||
found = true;
|
||||
if (checkOnly) return found;
|
||||
for (let row of rsp.docs) {
|
||||
// Zotero.debug(row.tags);
|
||||
let foundTags = {};
|
||||
let allTagsFound = true;
|
||||
for (let tag of tags) {
|
||||
foundTags[tag] = [];
|
||||
for (let rowTag of row.tags) {
|
||||
let matcher = new RegExp(tag, "g");
|
||||
//if (rowTag.search(tag) >= 0) {
|
||||
if (matcher.match(rowTag)) {
|
||||
foundTags[tag].push(rowTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let tag of tags) {
|
||||
if (foundTags[tag] == 0) {
|
||||
allTagsFound = false;
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.debug(allTagsFound);
|
||||
if (allTagsFound) {
|
||||
// Zotero.debug(foundTags);
|
||||
href = '/#/metadata/' + row.name;
|
||||
title = ZU.trimInternal(row.title);
|
||||
// Zotero.debug(href + '/' + title);
|
||||
items[href] = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found ? items : false;
|
||||
}
|
||||
|
||||
async function doWeb(doc, url) {
|
||||
if (detectWeb(doc, url) == 'multiple') {
|
||||
// Zotero.debug('multiple');
|
||||
let searchResults = await getSearchResults(doc, false);
|
||||
let items = await Zotero.selectItems(searchResults);
|
||||
// Zotero.debug(items.length);
|
||||
if (!items) return;
|
||||
for (let url of Object.keys(items)) {
|
||||
// Zotero.debug('about to scrape() ' + url);
|
||||
await scrape(url);
|
||||
}
|
||||
}
|
||||
else {
|
||||
await scrape(url);
|
||||
}
|
||||
}
|
||||
|
||||
async function scrape(url) {
|
||||
// Zotero.debug(url);
|
||||
let dataciteUrl = url.replace('#/metadata/', 'dataset/') + '/export/datacite.xml';
|
||||
// Zotero.debug(dataciteUrl);
|
||||
if (dataciteUrl) {
|
||||
let xmlDoc = await requestDocument(dataciteUrl);
|
||||
processMetadata(xmlDoc);
|
||||
}
|
||||
}
|
||||
|
||||
function processMetadata(xmlDoc) {
|
||||
// TODO: Replace with call to Datacite XML if we ever add a translator for that
|
||||
let item = new Zotero.Item('dataset');
|
||||
item.repository = 'Envidat';
|
||||
|
||||
item.title = text(xmlDoc, "title");
|
||||
item.date = text(xmlDoc, "publicationYear");
|
||||
item.language = text(xmlDoc, "language");
|
||||
item.publisher = text(xmlDoc, "publisher");
|
||||
for (let creatorNode of xmlDoc.getElementsByTagName("creator")) {
|
||||
let givenName = text(creatorNode, "givenName");
|
||||
let familyName = text(creatorNode, "familyName");
|
||||
// TODO should we use or map the roles from Datacite?
|
||||
let author = { lastName: familyName, firstName: givenName, creatorType: 'author' };
|
||||
item.creators.push(author);
|
||||
}
|
||||
|
||||
for (let subjectNode of xmlDoc.getElementsByTagName("subject")) {
|
||||
let tag = { tag: subjectNode.textContent };
|
||||
if (tag.tag === tag.tag.toUpperCase()) {
|
||||
tag.tag = ZU.capitalizeTitle(tag.tag, true);
|
||||
}
|
||||
item.tags.push(tag);
|
||||
}
|
||||
|
||||
// TODO find an example with a DOI
|
||||
item.DOI = text(xmlDoc, "Identifier");
|
||||
item.url = text(xmlDoc, "alternateIdentifier[alternateIdentifierType='URL']:last-child");
|
||||
item.abstractNote = text(xmlDoc, "description[descriptionType='Abstract' i]");
|
||||
item.rights = text(xmlDoc, "rights");
|
||||
|
||||
item.complete();
|
||||
}
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.envidat.ch/#/metadata/experimental-rockfall-dataset-tschamut-grisons-switzerland",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dataset",
|
||||
"title": "Induced Rockfall Dataset (Small Rock Experimental Campaign), Tschamut, Grisons, Switzerland",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Caviezel",
|
||||
"firstName": "Andrin",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Bühler",
|
||||
"firstName": "Yves",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Christen",
|
||||
"firstName": "Marc",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Bartelt",
|
||||
"firstName": "Perry",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018",
|
||||
"abstractNote": "Dataset of an experimental campaign of induced rockfall in Tschamut, Grisons, Switzerland. \nThe data archive contains site specific geographical data such as DEM and orthophoto as well as the deposition points of manually induced rockfall by releasing differently shaped boulders with 30–80 kg of mass. Additionally available are all the StoneNode data streams for rocks equipped with a sensor. The data set consists of \n* Deposition points from two series (wet (27/10/2016) and frozen (08/12/2016) ground) \n* Digital Elevation Model (grid resolution 2 m) obtained via UAV\n* Orthophoto (5 cm resolution) obtained via UAV\n* Digitized rock point clouds (.pts input files for RAMMS::ROCKFALL)\n* StoneNode v1.0 raw data stream for equipped rocks.\nFurther information is found in\n* A. Caviezel et al., _Design and Evaluation of a Low-Power Sensor Device for Induced Rockfall Experiments_, IEEE Transactions on Instrumentation and Measurement, 2018, 67, 767-779, http://ieeexplore.ieee.org/document/8122020/\n* P. Niklaus et al., _StoneNode: A low-power sensor device for induced rockfall experiments_, 2017 IEEE Sensors Applications Symposium (SAS), 2017, 1-6, http://ieeexplore.ieee.org/document/7894081/",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Envidat",
|
||||
"repository": "EnviDat",
|
||||
"rights": "ODbL with Database Contents License (DbCL)",
|
||||
"url": "https://www.envidat.ch/dataset/5b7a47bf-cbea-42a0-879f-ea2ccd17e82f",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Dem"
|
||||
},
|
||||
{
|
||||
"tag": "Deposition Points"
|
||||
},
|
||||
{
|
||||
"tag": "Induced Rockfall"
|
||||
},
|
||||
{
|
||||
"tag": "Natural Hazards"
|
||||
},
|
||||
{
|
||||
"tag": "Rockfall"
|
||||
},
|
||||
{
|
||||
"tag": "Rockfall Experiments"
|
||||
},
|
||||
{
|
||||
"tag": "Rockfall Runout"
|
||||
},
|
||||
{
|
||||
"tag": "Sensor Stream"
|
||||
},
|
||||
{
|
||||
"tag": "Stonenode"
|
||||
},
|
||||
{
|
||||
"tag": "Stonenodedata"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "web",
|
||||
"url": "https://www.envidat.ch/dataset/10-16904-envidat-28",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "dataset",
|
||||
"title": "Snowfarming data set Davos and Martell 2015",
|
||||
"creators": [
|
||||
{
|
||||
"lastName": "Grünewald",
|
||||
"firstName": "Thomas",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Wolfsperger",
|
||||
"firstName": "Fabian",
|
||||
"creatorType": "author"
|
||||
},
|
||||
{
|
||||
"lastName": "Lehning",
|
||||
"firstName": "Michael",
|
||||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2018",
|
||||
"abstractNote": "Two data sets obtained for snow farming projects (Fluela, Davos, CH and Martell, IT) in 2015. \nThe data set contains for each site:\n* 10 cm GIS raster of snow depth calculated from terrestrial laserscanning surveys (TLS) in the end of winter season (April/May)\n* 10 cm GIS raster of snow depth calculated from TLS in the end of summer season (October)\nInput files for SNOWPACK model:\n* .sno: snow profile at the end of winter\n* .smet: meteorological data measured by weather stations in the area\nFor more details see Grünewald, T., Lehning, M., and Wolfsperger, F.: Snow farming: Conserving snow over the summer season, The Cryosphere Discuss., https://doi.org/10.5194/tc-2017-93, in review, 2017.",
|
||||
"language": "en",
|
||||
"libraryCatalog": "Envidat",
|
||||
"repository": "EnviDat",
|
||||
"rights": "ODbL with Database Contents License (DbCL)",
|
||||
"url": "https://www.envidat.ch/dataset/640b09be-3b86-492e-aba2-449329969989",
|
||||
"attachments": [],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Snow"
|
||||
},
|
||||
{
|
||||
"tag": "Snow Conservation"
|
||||
},
|
||||
{
|
||||
"tag": "Snow Farming"
|
||||
},
|
||||
{
|
||||
"tag": "Snowpack"
|
||||
},
|
||||
{
|
||||
"tag": "Terrestrial Laser Scanning"
|
||||
},
|
||||
{
|
||||
"tag": "Winter Tourism"
|
||||
}
|
||||
],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
/** END TEST CASES **/
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-06-19 08:52:49"
|
||||
"lastUpdated": "2024-03-23 01:38:15"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
function detectWeb(doc, url) {
|
||||
if (url.includes('/article/')) {
|
||||
if (url.includes('/PPR/')) {
|
||||
return 'report';
|
||||
return 'preprint';
|
||||
}
|
||||
else {
|
||||
return "journalArticle";
|
||||
|
|
@ -66,17 +66,18 @@ 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) return;
|
||||
Object.keys(items).forEach(scrape);
|
||||
});
|
||||
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 {
|
||||
let jsonURL = getJSONURL(url);
|
||||
if (jsonURL) {
|
||||
scrape(jsonURL);
|
||||
await scrape(jsonURL);
|
||||
}
|
||||
else {
|
||||
Z.debug('Couldn\'t extract ID from URL: ' + url);
|
||||
|
|
@ -84,10 +85,11 @@ function doWeb(doc, url) {
|
|||
}
|
||||
}
|
||||
|
||||
function scrape(jsonURL) {
|
||||
ZU.doGet(jsonURL, function (respText) {
|
||||
processJSON(JSON.parse(respText));
|
||||
});
|
||||
|
||||
async function scrape(jsonURL) {
|
||||
// Z.debug(jsonURL);
|
||||
let respText = await requestJSON(jsonURL);
|
||||
processJSON(respText);
|
||||
}
|
||||
|
||||
function getJSONURL(pageURL) {
|
||||
|
|
@ -98,6 +100,7 @@ function getJSONURL(pageURL) {
|
|||
}
|
||||
|
||||
function processJSON(json) {
|
||||
// Z.debug(json);
|
||||
if (!json.resultList || !json.resultList.result || !json.resultList.result.length) {
|
||||
Z.debug('Query returned no results');
|
||||
return;
|
||||
|
|
@ -145,8 +148,7 @@ function processPubTypeList(pubTypeList, item) {
|
|||
if (!pubTypeList || !pubTypeList.pubType) return;
|
||||
|
||||
if (pubTypeList.pubType.length == 1 && pubTypeList.pubType[0] == 'Preprint') {
|
||||
item.itemType = 'report';
|
||||
item.extra = (item.extra || '') + `Type: article\n`;
|
||||
item.itemType = 'preprint';
|
||||
}
|
||||
else {
|
||||
item.itemType = 'journalArticle';
|
||||
|
|
@ -214,6 +216,7 @@ function processKeywordList(keywordList, item) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** BEGIN TEST CASES **/
|
||||
var testCases = [
|
||||
{
|
||||
|
|
@ -363,7 +366,7 @@ var testCases = [
|
|||
"url": "https://europepmc.org/article/PPR/PPR358366",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"itemType": "preprint",
|
||||
"title": "Fly ash application in moorum embankment and its stability analysis using FLAC/SLOPE and Response Surface Metho",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -378,11 +381,17 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2021",
|
||||
"DOI": "10.21203/rs.3.rs-631949/v1",
|
||||
"abstractNote": "This paper presents the application of fly ash in moorum embankment by partial replacement of moorum with fly ash and its stability analysis has been carried out. An experimental investigation was carried out on moorum blended with fly ash at different proportions of fly ash by dry weight of soil for the moorum embankment stability analysis. The Index properties and strength properties were assessed by performing Atterberg's limit, specific gravity, grain size distribution, compaction test, direct shear test (DST), and California Bearing Ratio (CBR) test respectively. The embankment slope stability analysis was performed using FLAC/SLOPE version 8.10 (Fast Lagrangian Analysis of Continua) software at a various slope angle of 30°, 32°, and 34° and different heights of the embankment of 6 m, 8 m, and 10 m to calculate Factor of Safety (FOS). FOS decreases with the increment of fly ash content, the height of embankment, and slope angle respectively. In addition to the numerical analysis, Response Surface Methodology (RSM) based (Face-Centered Central Composite Design) was used to predict FOS. The developed mathematical equation illustrates that the RSM model was statistically significant and the results give a reliable prediction of FOS.",
|
||||
"extra": "Type: article",
|
||||
"libraryCatalog": "Europe PMC",
|
||||
"rights": "cc by",
|
||||
"url": "https://doi.org/10.21203/rs.3.rs-631949/v1",
|
||||
"attachments": [],
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Full Text PDF (Open access)",
|
||||
"mimeType": "application/pdf"
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"notes": [],
|
||||
"seeAlso": []
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"inRepository": true,
|
||||
"translatorType": 4,
|
||||
"browserSupport": "gcsibv",
|
||||
"lastUpdated": "2021-08-16 20:40:08"
|
||||
"lastUpdated": "2024-03-21 19:05:49"
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
function detectWeb(doc, url) {
|
||||
if (url.includes('/articles/')
|
||||
&& doc.querySelector('meta[name="citation_title"]')) {
|
||||
return "report";
|
||||
return "preprint";
|
||||
}
|
||||
else if (getSearchResults(doc, true)) {
|
||||
return "multiple";
|
||||
|
|
@ -85,20 +85,21 @@ function scrape(doc, url) {
|
|||
translator.setDocument(doc);
|
||||
|
||||
translator.setHandler('itemDone', function (obj, item) {
|
||||
item.itemType = 'report';
|
||||
item.extra = (item.extra || '') + '\nType: article'; // preprint
|
||||
|
||||
item.itemType = 'preprint';
|
||||
delete item.pages;
|
||||
delete item.reportType;
|
||||
|
||||
item.reportNumber = `${item.volume}:${item.issue}`;
|
||||
delete item.genre;
|
||||
if (item.volume && item.issue) {
|
||||
item.archiveID = `${item.volume}:${item.issue}`;
|
||||
}
|
||||
delete item.volume;
|
||||
delete item.issue;
|
||||
delete item.number;
|
||||
|
||||
item.institution = item.publicationTitle;
|
||||
delete item.publisher;
|
||||
item.publisher = item.publicationTitle;
|
||||
delete item.publicationTitle;
|
||||
delete item.distributor;
|
||||
delete item.company;
|
||||
delete item.institution;
|
||||
delete item.label;
|
||||
|
||||
if (item.date) {
|
||||
item.date = ZU.strToISO(item.date);
|
||||
|
|
@ -110,7 +111,7 @@ function scrape(doc, url) {
|
|||
});
|
||||
|
||||
translator.getTranslatorObject(function (trans) {
|
||||
trans.itemType = "report";
|
||||
trans.itemType = "preprint";
|
||||
trans.doWeb(doc, url);
|
||||
});
|
||||
}
|
||||
|
|
@ -122,8 +123,8 @@ var testCases = [
|
|||
"url": "https://f1000research.com/articles/10-614",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"title": "Cerebrospinal fluid neurofilament light levels in CLN2 disease patients treated with enzyme replacement therapy normalise after two years on treatment",
|
||||
"itemType": "preprint",
|
||||
"title": "Cerebrospinal fluid neurofilament light chain levels in CLN2 disease patients treated with enzyme replacement therapy normalise after two years on treatment",
|
||||
"creators": [
|
||||
{
|
||||
"firstName": "Katharina",
|
||||
|
|
@ -186,13 +187,13 @@ var testCases = [
|
|||
"creatorType": "author"
|
||||
}
|
||||
],
|
||||
"date": "2021-07-20",
|
||||
"date": "2022-01-05",
|
||||
"DOI": "10.12688/f1000research.54556.2",
|
||||
"abstractNote": "Classic late infantile neuronal ceroid lipofuscinosis (CLN2 disease) is caused by a deficiency of tripeptidyl-peptidase-1. In 2017, the first CLN2 enzyme replacement therapy (ERT) cerliponase alfa (Brineura) was approved by the FDA and EMA. The CLN2 disease clinical rating scale (CLN2 CRS) was developed to monitor loss of motor function, language and vision as well as frequency of generalised tonic clonic seizures. Using CLN2 CRS in an open label clinical trial it was shown that Brineura slowed down the progression of CLN2 symptoms. Neurofilament light chain (NfL) is a protein highly expressed in myelinated axons. An increase of cerebrospinal fluid (CSF) and blood NfL is found in a variety of neuroinflammatory, neurodegenerative, traumatic, and cerebrovascular diseases. We analysed CSF NfL in CLN2 patients treated with Brineura to establish whether it can be used as a possible biomarker of response to therapy. Newly diagnosed patients had CSF samples collected and analysed at first treatment dose and up to 12 weeks post-treatment to look at acute changes. Patients on a compassionate use programme who were already receiving ERT for approximately 1yr had CSF samples collected and NfL analysed over the following 1.3 years (2.3 years post-initiation of ERT) to look at long-term changes. All newly diagnosed patients we investigated with classical late infantile phenotype had high NfL levels >2000 pg/ml at start of treatment. No significant change was observed in NfL up to 12 weeks post-treatment. After one year of ERT, two out of six patients still had high NfL levels, but all patients showed a continued decrease, and all had low NfL levels after two years on ERT. NfL levels appear to correspond and predict improved clinical status of patients on ERT and could be useful as a biomarker to monitor neurodegeneration and verify disease modification in CLN2 patients on ERT.",
|
||||
"extra": "Type: article",
|
||||
"institution": "F1000Research",
|
||||
"archiveID": "10:614",
|
||||
"language": "en",
|
||||
"libraryCatalog": "f1000research.com",
|
||||
"reportNumber": "10:614",
|
||||
"repository": "F1000Research",
|
||||
"rights": "http://creativecommons.org/licenses/by/4.0/",
|
||||
"url": "https://f1000research.com/articles/10-614",
|
||||
"attachments": [
|
||||
|
|
@ -203,7 +204,7 @@ var testCases = [
|
|||
],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "Enzyme replacment therapy"
|
||||
"tag": "Enzyme replacement therapy"
|
||||
},
|
||||
{
|
||||
"tag": "Neurofilament light"
|
||||
|
|
@ -222,7 +223,7 @@ var testCases = [
|
|||
"url": "https://f1000research.com/articles/10-153",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"itemType": "preprint",
|
||||
"title": "Regional disparities in postnatal care among mothers aged 15-49 years old: An analysis of the Indonesian Demographic and Health Survey 2017",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -252,12 +253,12 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2021-08-16",
|
||||
"DOI": "10.12688/f1000research.50938.2",
|
||||
"abstractNote": "Background: In Indonesia, maternal mortality remains high, significantly 61.59% occur in the postnatal period. Postnatal care (PNC) provision is a critical intervention between six hours and 42 days after childbirth and is the primary strategy to reduce maternal mortality rates. However, underutilisation of PNC in Indonesia still remains high, and limited studies have shown the regional disparities of PNC in Indonesia. Methods: This study aims to explore the gaps between regions in PNC service for mothers who have had live births during the last five years in Indonesia. This study was a secondary data analysis study using the Indonesian Demographic and Health Survey (IDHS) in 2017. A total of 13,901 mothers aged 15-49 years having had live births within five years were included. Chi-squared test and binary logistic regression were performed to determine regional disparities in PNC. Results: Results indicated that the prevalence of PNC service utilisation among mothers aged 15-49 years was 70.94%. However, regional gaps in the utilisation of PNC service were indicated. Mothers in the Central of Indonesia have used PNC services 2.54 times compared to mothers in the Eastern of Indonesia (OR = 2.54; 95% CI = 1.77-3.65, p<0.001). Apart from the region, other variables have a positive relationship with PNC service, including wealth quintile, accessibility health facilities, age of children, childbirth order, mother's education, maternal occupation, spouse's age, and spouse's education. Conclusion: The results suggest the need for national policy focuses on service equality, accessible, and reliable implementation to improve postnatal care utilisation among mothers to achieve the maximum results for the Indonesian Universal Health Coverage plan.",
|
||||
"extra": "Type: article",
|
||||
"institution": "F1000Research",
|
||||
"archiveID": "10:153",
|
||||
"language": "en",
|
||||
"libraryCatalog": "f1000research.com",
|
||||
"reportNumber": "10:153",
|
||||
"repository": "F1000Research",
|
||||
"rights": "http://creativecommons.org/licenses/by/4.0/",
|
||||
"shortTitle": "Regional disparities in postnatal care among mothers aged 15-49 years old",
|
||||
"url": "https://f1000research.com/articles/10-153",
|
||||
|
|
@ -475,7 +476,7 @@ var testCases = [
|
|||
"url": "https://hrbopenresearch.org/articles/4-87",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"itemType": "preprint",
|
||||
"title": "Effectiveness of quality improvement strategies for type 1 diabetes in children and adolescents: a systematic review protocol",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -525,12 +526,12 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2021-08-10",
|
||||
"DOI": "10.12688/hrbopenres.13223.1",
|
||||
"abstractNote": "Introduction: Optimal glycaemic control is often a challenge in children and adolescents with type 1 diabetes (T1D). Implementation of patient, clinician or organisation-targeted quality improvement (QI) strategies has been proven to be beneficial in terms of improving glycaemic outcomes in adults living with diabetes. This review aims to assess the effectiveness of such QI interventions in improving glycaemic control, care delivery, and screening rates in children and adolescents with T1D. Methods and analysis: MEDLINE, EMBASE, CINAHL and Cochrane CENTRAL databases will be searched for relevant studies up to January 2021. Trial registries, ClinicalTrials.gov and ICTRP, will also be explored for any ongoing trials of relevance. We will include trials which examine QI strategies as defined by a modified version of the Cochrane Effective Practice and Organisation of Care 2015 Taxonomy in children (<18 years) with a diagnosis of T1D. The primary outcome to be assessed is glycated haemoglobin (HbA1c), although a range of secondary outcomes relating to clinical management, adverse events, healthcare engagement, screening rates and psychosocial parameters will also be assessed. Our primary intention is to generate a best-evidence narrative to summarise and synthesise the resulting studies. If a group of studies are deemed to be highly similar, then a meta-analysis using a random effects model will be considered. Cochrane Risk of Bias 1.0 tool will be applied for quality assessment. All screening, data extraction and quality assessment will be performed by two independent researchers. Dissemination: The results of this review will be disseminated through peer-reviewed publication in order to inform invested partners (e.g., Paediatric Endocrinologists) on the potential of QI strategies to improve glycaemic management and other related health outcomes in children with T1D, thereby guiding best practices in the outpatient management of the disorder. PROSPERO registration number: CRD42021233974 (28/02/2021).",
|
||||
"extra": "Type: article",
|
||||
"institution": "HRB Open Research",
|
||||
"archiveID": "4:87",
|
||||
"language": "en",
|
||||
"libraryCatalog": "hrbopenresearch.org",
|
||||
"reportNumber": "4:87",
|
||||
"repository": "HRB Open Research",
|
||||
"rights": "http://creativecommons.org/licenses/by/4.0/",
|
||||
"shortTitle": "Effectiveness of quality improvement strategies for type 1 diabetes in children and adolescents",
|
||||
"url": "https://hrbopenresearch.org/articles/4-87",
|
||||
|
|
@ -569,6 +570,7 @@ var testCases = [
|
|||
},
|
||||
{
|
||||
"type": "web",
|
||||
"defer": true,
|
||||
"url": "https://f1000research.com/search?q=test",
|
||||
"items": "multiple"
|
||||
},
|
||||
|
|
@ -577,7 +579,7 @@ var testCases = [
|
|||
"url": "https://gatesopenresearch.org/articles/5-122",
|
||||
"items": [
|
||||
{
|
||||
"itemType": "report",
|
||||
"itemType": "preprint",
|
||||
"title": "Young infant clinical signs study­­, Pakistan: a data note",
|
||||
"creators": [
|
||||
{
|
||||
|
|
@ -612,12 +614,12 @@ var testCases = [
|
|||
}
|
||||
],
|
||||
"date": "2021-08-12",
|
||||
"DOI": "10.12688/gatesopenres.13317.1",
|
||||
"abstractNote": "Neonatal sepsis is the leading cause of child death globally with most of these deaths occurring in the first week of life. It is of utmost public health importance that clinical signs predictive of severe illness and need for referral are identified early in the course of illness. From 2002-2005, a multi country trial called the Young Infant Clinical Signs Study (YICSS) was conducted in seven sites across three South-Asian (Bangladesh, India, and Pakistan), two African (Ghana, and South Africa), and one South American (Bolivia) country. The study aimed to develop a simplified algorithm to be used by primary healthcare workers for the identification of sick young infants needing prompt referral and treatment. The main study enrolled 8,889 young infants between the ages of 0-59 days old. This dataset contains observations on 2950 young infants aged 0-59 days from the Pakistan site. The data was collected between 2003-2004 with information on the most prevalent signs and symptoms. The data from this study was used to update the Integrated Management of Childhood Illness guidelines. The World Health Organisation (WHO) seven-sign algorithm has been used in other major community-based trials to study possible serious bacterial infection and its treatment regimens.",
|
||||
"extra": "Type: article",
|
||||
"institution": "Gates Open Research",
|
||||
"archiveID": "5:122",
|
||||
"language": "en",
|
||||
"libraryCatalog": "gatesopenresearch.org",
|
||||
"reportNumber": "5:122",
|
||||
"repository": "Gates Open Research",
|
||||
"rights": "http://creativecommons.org/licenses/by/4.0/",
|
||||
"shortTitle": "Young infant clinical signs study­­, Pakistan",
|
||||
"url": "https://gatesopenresearch.org/articles/5-122",
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue