Skip to content

Commit

Permalink
support updatable dictionaries (#1174)
Browse files Browse the repository at this point in the history
* dict format mvp

* store data

* wip

* rename dictionary-version to dictionary-revision

* wip

* validate urls in importer

* wip

* check mvp

* update-single-modal

* works

* count updates

* dry regex

* dry regex

* escape regex dot

* regex comment

* fix css mistake

* add compareRevisions test

* use downloadUrl from new index

* updates singular
  • Loading branch information
StefanVukovic99 authored Jul 19, 2024
1 parent 7426876 commit e268de9
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 15 deletions.
1 change: 1 addition & 0 deletions ext/css/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -2324,6 +2324,7 @@ input[type=number].dictionary-priority {
margin-right: 0.5em;
}
.dictionary-outdated-button,
.dictionary-update-available,
.dictionary-integrity-button {
--button-content-color: transparent;
--button-border-color: transparent;
Expand Down
22 changes: 19 additions & 3 deletions ext/data/schemas/dictionary-index-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"revision": {
"type": "string",
"description": "Revision of the dictionary. This value is only used for displaying information."
"description": "Revision of the dictionary. This value is displayed, and used to check for dictionary updates."
},
"sequenced": {
"type": "boolean",
Expand All @@ -42,9 +42,22 @@
"type": "string",
"description": "Creator of the dictionary."
},
"isUpdatable": {
"type": "boolean",
"const": true,
"description": "Whether this dictionary contains links to its latest version."
},
"indexUrl": {
"type": "string",
"description": "URL for the index file of the latest revision of the dictionary, used to check for updates."
},
"downloadUrl": {
"type": "string",
"description": "URL for the download of the latest revision of the dictionary."
},
"url": {
"type": "string",
"description": "URL for the source of the dictionary."
"description": "URL for the source of the dictionary, displayed in the dictionary details."
},
"description": {
"type": "string",
Expand Down Expand Up @@ -101,5 +114,8 @@
{
"required": ["version"]
}
]
],
"dependencies": {
"isUpdatable": ["indexUrl", "downloadUrl"]
}
}
27 changes: 27 additions & 0 deletions ext/js/dictionary/dictionary-data-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,33 @@ export function isNonNounVerbOrAdjective(wordClasses) {
return isVerbOrAdjective && !(isSuruVerb && isNoun);
}

/**
* @param {string} current
* @param {string} latest
* @returns {boolean}
*/
export function compareRevisions(current, latest) {
const simpleVersionTest = /^(\d+\.)*\d+$/; // dot-separated integers, so 4.7 or 24.1.1.1 are ok, 1.0.0-alpha is not
if (!simpleVersionTest.test(current) || !simpleVersionTest.test(latest)) {
return current < latest;
}

const currentParts = current.split('.').map((part) => Number.parseInt(part, 10));
const latestParts = latest.split('.').map((part) => Number.parseInt(part, 10));

if (currentParts.length !== latestParts.length) {
return current < latest;
}

for (let i = 0; i < currentParts.length; i++) {
if (currentParts[i] !== latestParts[i]) {
return currentParts[i] < latestParts[i];
}
}

return false;
}

// Private

/**
Expand Down
32 changes: 30 additions & 2 deletions ext/js/dictionary/dictionary-importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export class DictionaryImporter {
* @param {import('dictionary-data').Index} index
* @param {import('dictionary-importer').SummaryDetails} details
* @returns {import('dictionary-importer').Summary}
* @throws {Error}
*/
_createSummary(dictionaryTitle, version, index, details) {
const indexSequenced = index.sequenced;
Expand All @@ -327,18 +328,45 @@ export class DictionaryImporter {
styles,
};

const {author, url, description, attribution, frequencyMode, sourceLanguage, targetLanguage} = index;
const {author, url, description, attribution, frequencyMode, isUpdatable, sourceLanguage, targetLanguage} = index;
if (typeof author === 'string') { summary.author = author; }
if (typeof url === 'string') { summary.url = url; }
if (typeof description === 'string') { summary.description = description; }
if (typeof attribution === 'string') { summary.attribution = attribution; }
if (typeof frequencyMode === 'string') { summary.frequencyMode = frequencyMode; }
if (typeof sourceLanguage === 'string') { summary.sourceLanguage = sourceLanguage; }
if (typeof targetLanguage === 'string') { summary.targetLanguage = targetLanguage; }

if (typeof isUpdatable === 'boolean') {
const {indexUrl, downloadUrl} = index;
if (!isUpdatable || !this._validateUrl(indexUrl) || !this._validateUrl(downloadUrl)) {
throw new Error('Invalid index data for updatable dictionary');
}
summary.isUpdatable = isUpdatable;
summary.indexUrl = indexUrl;
summary.downloadUrl = downloadUrl;
}
return summary;
}

/**
* @param {string|undefined} string
* @returns {boolean}
*/
_validateUrl(string) {
if (typeof string !== 'string') {
return false;
}

let url;
try {
url = new URL(string);
} catch (_) {
return false;
}

return url.protocol === 'http:' || url.protocol === 'https:';
}

/**
* @param {import('ajv').ValidateFunction} schema
* @param {string} fileName
Expand Down
2 changes: 1 addition & 1 deletion ext/js/pages/settings/collapsible-dictionary-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class CollapsibleDictionaryController {
nameNode.textContent = dictionary;

/** @type {HTMLElement} */
const versionNode = querySelectorNotNull(node, '.dictionary-version');
const versionNode = querySelectorNotNull(node, '.dictionary-revision');
versionNode.textContent = version;

return querySelectorNotNull(node, '.definitions-collapsible');
Expand Down
Loading

0 comments on commit e268de9

Please sign in to comment.