-
Notifications
You must be signed in to change notification settings - Fork 769
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
130 changed files
with
16,596 additions
and
6,045 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 0 additions & 15 deletions
15
.ci/eslint-plugin-zotero-translator/lib/processor/index.js
This file was deleted.
Oops, something went wrong.
55 changes: 55 additions & 0 deletions
55
.ci/eslint-plugin-zotero-translator/lib/rules/header-last-updated.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}); | ||
} | ||
} | ||
}; | ||
}, | ||
}; |
65 changes: 65 additions & 0 deletions
65
.ci/eslint-plugin-zotero-translator/lib/rules/header-translator-id.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()}"`), | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
}; |
82 changes: 82 additions & 0 deletions
82
.ci/eslint-plugin-zotero-translator/lib/rules/header-translator-type.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} | ||
}; | ||
}, | ||
}; |
Oops, something went wrong.