From 0ce4bed349e4fac9182917693697c4f54d84c7f4 Mon Sep 17 00:00:00 2001 From: azu Date: Sun, 18 Mar 2018 13:00:51 +0900 Subject: [PATCH] fix(rule): fix cache mechanism --- package.json | 2 +- src/create-tester.js | 36 +++++++++++++++- src/dictionary-storage.js | 24 +++++++++++ src/mode.js | 9 ++++ src/proofdict-repo-util.js | 2 +- src/textlint-rule-proofdict.js | 62 ++++++++++------------------ test/fixtures/proofdict.json | 2 +- test/textlint-rule-proofdict-test.js | 53 ++++++++++++++++++------ yarn.lock | 6 +-- 9 files changed, 135 insertions(+), 61 deletions(-) create mode 100644 src/dictionary-storage.js create mode 100644 src/mode.js diff --git a/package.json b/package.json index cc407a4..6b4163c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "@types/url-join": "^0.8.2", "debug": "^3.1.0", - "fetch-ponyfill": "^5.0.1", + "fetch-ponyfill": "^6.0.0", "localstorage-ponyfill": "^1.0.1", "proofdict": "^1.2.1", "proofdict-tester": "^1.0.0", diff --git a/src/create-tester.js b/src/create-tester.js index 0f0898b..cb5756f 100644 --- a/src/create-tester.js +++ b/src/create-tester.js @@ -1,5 +1,8 @@ // MIT © 2017 azu "use strict"; +import { MODE } from "./mode"; +import { storage } from "./dictionary-storage"; + const { ProofdictTester } = require("proofdict-tester"); let currentTester = null; let checkedLastTime = -1; @@ -8,10 +11,11 @@ let checkedLastTime = -1; * @param {*} dictionary * @param {string[]} whitelistTags * @param {string[]} blacklistTags + * @param {boolean} disableTesterCache * @returns {ProofdictTester} */ -export const createTester = ({ lastUpdated, dictionary, whitelistTags, blacklistTags }) => { - if (currentTester === null && checkedLastTime < lastUpdated) { +export const createTester = ({ lastUpdated, dictionary, whitelistTags, blacklistTags, disableTesterCache }) => { + if (disableTesterCache || (currentTester === null && checkedLastTime < lastUpdated)) { checkedLastTime = lastUpdated; currentTester = new ProofdictTester({ dictionary, @@ -22,3 +26,31 @@ export const createTester = ({ lastUpdated, dictionary, whitelistTags, blacklist } return currentTester; }; + + +/** + * @param options + * @param {string} mode + * @returns {*} + */ +export const getDictionary = (options, mode) => { + // prefer `dictionary` option + if (options.proofdict !== undefined) { + return options.proofdict; + } + let proofDictData; + // NETWORK + if (mode === MODE.NETWORK) { + try { + const cachedProofdict = storage.getItem("proofdict"); + proofDictData = JSON.parse(cachedProofdict); + } catch (error) { + storage.removeItem("proofdict"); + } + } + // LOCAL + if (mode === MODE.LOCAL) { + // TODO: not implemented + } + return proofDictData; +}; diff --git a/src/dictionary-storage.js b/src/dictionary-storage.js new file mode 100644 index 0000000..80e7f20 --- /dev/null +++ b/src/dictionary-storage.js @@ -0,0 +1,24 @@ +// MIT © 2018 azu +"use strict"; +const { createLocalStorage } = require("localstorage-ponyfill"); + + +class Storage { + constructor() { + this.localStorage = createLocalStorage(); + } + + getItem(name, defaultValue) { + return this.localStorage.getItem(name, defaultValue); + } + + setItem(name, value) { + return this.localStorage.setItem(name, value); + }; + + removeItem(name) { + return this.localStorage.removeItem(name); + } +} + +export const storage = new Storage(); diff --git a/src/mode.js b/src/mode.js new file mode 100644 index 0000000..451494d --- /dev/null +++ b/src/mode.js @@ -0,0 +1,9 @@ +// MIT © 2018 azu +"use strict"; +/** + * @type {{LOCAL: string, NETWORK: string}} + */ +export const MODE = { + LOCAL: "LOCAL", + NETWORK: "NETWORK" +}; diff --git a/src/proofdict-repo-util.js b/src/proofdict-repo-util.js index b2150ca..baefcaa 100644 --- a/src/proofdict-repo-util.js +++ b/src/proofdict-repo-util.js @@ -10,7 +10,7 @@ export function getDictJSONURL(options) { if (typeof options.dictURL === "object" && typeof options.dictURL.jsonAPI === "string") { return options.dictURL.jsonAPI; } - return urlJoin(options.dictURL, "dict.json"); + return urlJoin(options.dictURL, "dictionary.json"); } /** diff --git a/src/textlint-rule-proofdict.js b/src/textlint-rule-proofdict.js index 6aef7e0..9e853a4 100644 --- a/src/textlint-rule-proofdict.js +++ b/src/textlint-rule-proofdict.js @@ -1,11 +1,12 @@ // MIT © 2017 azu "use strict"; const debug = require("debug")("textlint-rule-proofdict"); -const { createLocalStorage } = require("localstorage-ponyfill"); const { RuleHelper } = require("textlint-rule-helper"); -import { createTester } from "./create-tester"; +import { createTester, getDictionary } from "./create-tester"; import { fetchProofdict } from "./fetch-proofdict"; import { getDictJSONURL, getRuleURL } from "./proofdict-repo-util"; +import { MODE } from "./mode"; +import { storage } from "./dictionary-storage"; const DefaultOptions = { // If you want to use live-proofdict @@ -28,16 +29,11 @@ const DefaultOptions = { "blacklistTags": [], // For testing // set you proofdict json object - "proofdict": undefined + "proofdict": undefined, + // Disable cache for tester + "disableProofdictTesterCache": false }; -/** - * @type {{LOCAL: string, NETWORK: string}} - */ -const MODE = { - LOCAL: "LOCAL", - NETWORK: "NETWORK" -}; const reporter = (context, options = DefaultOptions) => { const helper = new RuleHelper(context); const { Syntax, RuleError, report, getSource, fixer } = context; @@ -52,24 +48,28 @@ Please set dictURL or dictPath to .textlintrc.`)) const mode = options.dictURL ? MODE.NETWORK : MODE.LOCAL; const whitelistTags = Array.isArray(options.whitelistTags) ? options.whitelistTags : DefaultOptions.whitelistTags; const blacklistTags = Array.isArray(options.blacklistTags) ? options.blacklistTags : DefaultOptions.blacklistTags; + const disableTesterCache = options.disableProofdictTesterCache !== undefined + ? options.disableProofdictTesterCache + : DefaultOptions.disableProofdictTesterCache; const autoUpdateInterval = options.autoUpdateInterval !== undefined - ? options.autoUpdateInterval - : DefaultOptions.autoUpdateInterval; - const localStorage = createLocalStorage(); + ? options.autoUpdateInterval + : DefaultOptions.autoUpdateInterval; const targetNodes = []; const addQueue = node => targetNodes.push(node); let promiseQueue = null; return { [Syntax.Document]() { // default: 0 - const lastUpdated = Number(localStorage.getItem("proofdict-lastUpdated", "0")); - const isExpired = lastUpdated + autoUpdateInterval < Date.now(); + const lastUpdated = Number(storage.getItem("proofdict-lastUpdated", "-1")); + const isExpired = lastUpdated <= 0 + ? true + : Date.now() - lastUpdated > autoUpdateInterval; if (mode === MODE.NETWORK && isExpired) { const jsonAPIURL = getDictJSONURL(options); promiseQueue = fetchProofdict({ URL: jsonAPIURL }) .then(dictionary => { - localStorage.setItem("proofdict", JSON.stringify(dictionary)); - localStorage.setItem("proofdict-lastUpdated", Date.now()); + storage.setItem("proofdict", JSON.stringify(dictionary)); + storage.setItem("proofdict-lastUpdated", Date.now()); }) .catch(error => { debug("Fetch is failed", error); @@ -84,34 +84,14 @@ Please set dictURL or dictPath to .textlintrc.`)) }, [`${Syntax.Document}:exit`]() { return promiseQueue.then(() => { - const getDict = (options) => { - // prefer `dictionary` option - if (options.proofdict !== undefined) { - return options.proofdict; - } - let proofDictData; - // NETWORK - if (options.dictURL) { - try { - const cachedProofdict = localStorage.getItem("proofdict"); - proofDictData = JSON.parse(cachedProofdict); - } catch (error) { - localStorage.removeItem("proofdict"); - } - } - // LOCAL - if (options.dictPath) { - // TODO: not implemented - } - return proofDictData; - }; - const dictionary = getDict(options); - const lastUpdated = Number(localStorage.getItem("proofdict-lastUpdated", "0")); + const dictionary = getDictionary(options, mode); + const lastUpdated = Number(storage.getItem("proofdict-lastUpdated", "0")); const tester = createTester({ dictionary, lastUpdated, whitelistTags, - blacklistTags + blacklistTags, + disableTesterCache }); // check const promises = targetNodes.map(node => { diff --git a/test/fixtures/proofdict.json b/test/fixtures/proofdict.json index b41cd29..3348987 100644 --- a/test/fixtures/proofdict.json +++ b/test/fixtures/proofdict.json @@ -24,4 +24,4 @@ "noun" ] } -] \ No newline at end of file +] diff --git a/test/textlint-rule-proofdict-test.js b/test/textlint-rule-proofdict-test.js index 0c78432..4b85691 100644 --- a/test/textlint-rule-proofdict-test.js +++ b/test/textlint-rule-proofdict-test.js @@ -2,26 +2,26 @@ const TextLintTester = require("textlint-tester"); const tester = new TextLintTester(); // rule import rule from "../src/textlint-rule-proofdict"; +// IN testing , disable tester cache +const disableProofdictTesterCache = true; +const defaultOptions = { + disableProofdictTesterCache, + proofdict: require("./fixtures/proofdict.json") +}; // ruleName, rule, { valid, invalid } tester.run("proofdict", rule, { valid: [ { text: "jQuery", - options: { - proofdict: require("./fixtures/proofdict.json") - } + options: defaultOptions }, { text: "WebKit", - options: { - proofdict: require("./fixtures/proofdict.json") - } + options: defaultOptions }, { text: "WebKit", - options: { - proofdict: require("./fixtures/proofdict.json") - } + options: defaultOptions }, ], invalid: [ @@ -29,7 +29,8 @@ tester.run("proofdict", rule, { text: "texlint check your texts.\n" + "jquery is libray.\n", output: "texlint check your texts.\n" + "jQuery is libray.\n", options: { - dictURL: "https://proofdict.github.io/proof-dictionary/" + dictURL: "https://proofdict.github.io/proof-dictionary/", + disableProofdictTesterCache }, errors: [ { @@ -44,7 +45,8 @@ tester.run("proofdict", rule, { text: "jquery", output: "jQuery", options: { - dictURL: "https://proofdict.github.io/proof-dictionary/" + dictURL: "https://proofdict.github.io/proof-dictionary/", + disableProofdictTesterCache }, errors: [ { @@ -59,7 +61,34 @@ tester.run("proofdict", rule, { text: "This is webkit.", output: "This is WebKit.", options: { - proofdict: require("./fixtures/proofdict.json") + proofdict: [ + { + "id": "01BQ92YZ6QR8RJKA5Y8W2F9NMY", + "description": "Reference https://webkit.org/", + "expected": "WebKit", + "patterns": [ + "/webkit/i" + ], + "specs": [ + { + "from": "これはwebkitです", + "to": "これはWebKitです" + }, + { + "from": "XXXwebkit", + "to": "XXXwebkit" + }, + { + "from": "node-webkit", + "to": "node-webkit" + } + ], + "tags": [ + "noun" + ] + } + ], + disableProofdictTesterCache }, errors: [ { diff --git a/yarn.lock b/yarn.lock index b72eae4..1a78691 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1139,9 +1139,9 @@ fetch-ponyfill@^4.1.0: dependencies: node-fetch "~1.7.1" -fetch-ponyfill@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-5.0.1.tgz#2789ec179c1de357f60f9fd49e154a8b3fd8cd1b" +fetch-ponyfill@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-6.0.0.tgz#1809503d4e3f966920708bb296114e1b69c0c477" dependencies: node-fetch "~2.0.0"