From 0f95f635b54fd0d4201f50ec8803c03cf4483cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sta=C5=9B=20Ma=C5=82olepszy?= Date: Mon, 27 Jan 2020 15:45:01 +0100 Subject: [PATCH 1/4] (@fluent/sequence) Migrate to TypeScript --- fluent-bundle/.gitignore | 4 +- fluent-bundle/makefile | 14 +++---- fluent-sequence/.esdoc.json | 16 -------- fluent-sequence/.gitignore | 1 + fluent-sequence/.npmignore | 4 +- fluent-sequence/eslint_src.json | 26 +++++++++++++ fluent-sequence/makefile | 38 ++++++++++++++++--- fluent-sequence/package.json | 8 ++-- fluent-sequence/src/index.js | 7 ---- fluent-sequence/src/index.ts | 7 ++++ .../src/{map_async.js => map_async.ts} | 22 +++++++---- fluent-sequence/src/map_sync.js | 30 --------------- fluent-sequence/src/map_sync.ts | 37 ++++++++++++++++++ fluent-sequence/test/fallback_async_test.js | 2 +- fluent-sequence/test/fallback_sync_test.js | 2 +- fluent-sequence/tsconfig.json | 16 ++++++++ 16 files changed, 151 insertions(+), 83 deletions(-) delete mode 100644 fluent-sequence/.esdoc.json create mode 100644 fluent-sequence/eslint_src.json delete mode 100644 fluent-sequence/src/index.js create mode 100644 fluent-sequence/src/index.ts rename fluent-sequence/src/{map_async.js => map_async.ts} (50%) delete mode 100644 fluent-sequence/src/map_sync.js create mode 100644 fluent-sequence/src/map_sync.ts create mode 100644 fluent-sequence/tsconfig.json diff --git a/fluent-bundle/.gitignore b/fluent-bundle/.gitignore index 1e865dd80..99472bc4d 100644 --- a/fluent-bundle/.gitignore +++ b/fluent-bundle/.gitignore @@ -1,3 +1,3 @@ esm/ -index.js -compat.js +/index.js +/compat.js diff --git a/fluent-bundle/makefile b/fluent-bundle/makefile index 41bedf5d8..2b612e19d 100644 --- a/fluent-bundle/makefile +++ b/fluent-bundle/makefile @@ -16,6 +16,13 @@ esm/.compiled: $(SOURCES) @touch $@ @echo -e " $(OK) esm/ compiled" +.PHONY: test +test: esm/.compiled + @nyc --reporter=text --reporter=html mocha \ + --recursive --ui tdd \ + --require esm \ + test/**/*_test.js + build: index.js compat.js index.js: esm/.compiled @@ -36,13 +43,6 @@ compat.js: esm/.compiled --output.file $@ @echo -e " $(OK) $@ built" -.PHONY: test -test: esm/.compiled - @nyc --reporter=text --reporter=html mocha \ - --recursive --ui tdd \ - --require esm \ - test/**/*_test.js - html: @typedoc src \ --out ../html/bundle \ diff --git a/fluent-sequence/.esdoc.json b/fluent-sequence/.esdoc.json deleted file mode 100644 index 459f25d05..000000000 --- a/fluent-sequence/.esdoc.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "source": "./src", - "destination": "../html/sequence", - "plugins": [ - { - "name": "esdoc-standard-plugin" - }, - { - "name": "esdoc-ecmascript-proposal-plugin", - "option": { - "objectRestSpread": true, - "asyncGenerators": true - } - } - ] -} diff --git a/fluent-sequence/.gitignore b/fluent-sequence/.gitignore index 7d147bec1..99472bc4d 100644 --- a/fluent-sequence/.gitignore +++ b/fluent-sequence/.gitignore @@ -1,2 +1,3 @@ +esm/ /index.js /compat.js diff --git a/fluent-sequence/.npmignore b/fluent-sequence/.npmignore index f520b36f5..abad613ff 100644 --- a/fluent-sequence/.npmignore +++ b/fluent-sequence/.npmignore @@ -1,5 +1,7 @@ .nyc_output coverage -docs +esm/.compiled +src test makefile +tsconfig.json diff --git a/fluent-sequence/eslint_src.json b/fluent-sequence/eslint_src.json new file mode 100644 index 000000000..2aa340b27 --- /dev/null +++ b/fluent-sequence/eslint_src.json @@ -0,0 +1,26 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 9, + "sourceType": "module", + "project": "./tsconfig.json" + }, + "env": { + "es6": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "../eslint_src.json" + ], + "rules": { + "prefer-const": "off", + "no-unused-vars": ["error", {"args": "none"}], + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-unused-vars": ["error", {"args": "none"}], + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/explicit-function-return-type": "error" + } +} diff --git a/fluent-sequence/makefile b/fluent-sequence/makefile index 8d79d8a6c..4fdd9268e 100644 --- a/fluent-sequence/makefile +++ b/fluent-sequence/makefile @@ -3,7 +3,21 @@ GLOBAL := FluentSequence include ../common.mk -test: +lint: + @eslint --config ./eslint_src.json --max-warnings 0 src/*.ts + @eslint --config $(ROOT)/eslint_test.json --max-warnings 0 test/ + @echo -e " $(OK) lint" + +.PHONY: compile +compile: esm/.compiled + +esm/.compiled: $(SOURCES) + @tsc + @touch $@ + @echo -e " $(OK) esm/ compiled" + +.PHONY: test +test: esm/.compiled @nyc --reporter=text --reporter=html mocha \ --recursive --ui tdd \ --require esm \ @@ -12,7 +26,7 @@ test: build: index.js compat.js index.js: $(SOURCES) - @rollup $(CURDIR)/src/index.js \ + @rollup $(CURDIR)/esm/index.js \ --config $(ROOT)/bundle_config.js \ --banner "/* $(PACKAGE)@$(VERSION) */" \ --amd.id $(PACKAGE) \ @@ -21,7 +35,7 @@ index.js: $(SOURCES) @echo -e " $(OK) $@ built" compat.js: $(SOURCES) - @rollup $(CURDIR)/src/index.js \ + @rollup $(CURDIR)/esm/index.js \ --config $(ROOT)/compat_config.js \ --banner "/* $(PACKAGE)@$(VERSION) */" \ --amd.id $(PACKAGE) \ @@ -29,6 +43,18 @@ compat.js: $(SOURCES) --output.file $@ @echo -e " $(OK) $@ built" -lint: _lint -html: _html -clean: _clean +html: + @typedoc src \ + --out ../html/bundle \ + --mode file \ + --excludeNotExported \ + --excludePrivate \ + --logger none \ + --hideGenerator + @echo -e " $(OK) html build" + +clean: + @rm -f esm/*.js esm/*.d.ts esm/.compiled + @rm -f index.js compat.js + @rm -rf .nyc_output coverage + @echo -e " $(OK) clean" diff --git a/fluent-sequence/package.json b/fluent-sequence/package.json index c26ec3af5..d7be18c84 100644 --- a/fluent-sequence/package.json +++ b/fluent-sequence/package.json @@ -15,11 +15,10 @@ "email": "stas@mozilla.com" } ], - "directories": { - "lib": "./src" - }, + "type": "commonjs", "main": "./index.js", - "module": "./src/index.js", + "module": "./esm/index.js", + "types": "./esm/index.d.ts", "repository": { "type": "git", "url": "https://github.com/projectfluent/fluent.js.git" @@ -32,6 +31,7 @@ "node": ">=10.0.0" }, "devDependencies": { + "@fluent/bundle": ">= 0.15.0", "cached-iterable": "^0.2.1" }, "peerDependencies": { diff --git a/fluent-sequence/src/index.js b/fluent-sequence/src/index.js deleted file mode 100644 index 84f354fb8..000000000 --- a/fluent-sequence/src/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * @module fluent-sequence - * @overview Manage ordered sequences of FluentBundles. - */ - -export {default as mapBundleSync} from "./map_sync"; -export {default as mapBundleAsync} from "./map_async"; diff --git a/fluent-sequence/src/index.ts b/fluent-sequence/src/index.ts new file mode 100644 index 000000000..1dfeac71d --- /dev/null +++ b/fluent-sequence/src/index.ts @@ -0,0 +1,7 @@ +/* + * @module fluent-sequence + * @overview Manage ordered sequences of FluentBundles. + */ + +export { mapBundleSync } from "./map_sync.js"; +export { mapBundleAsync } from "./map_async.js"; diff --git a/fluent-sequence/src/map_async.js b/fluent-sequence/src/map_async.ts similarity index 50% rename from fluent-sequence/src/map_async.js rename to fluent-sequence/src/map_async.ts index ebd2abe77..bb439a6a3 100644 --- a/fluent-sequence/src/map_async.js +++ b/fluent-sequence/src/map_async.ts @@ -1,31 +1,37 @@ +import { FluentBundle } from "@fluent/bundle"; + /* * Asynchronously map an identifier or an array of identifiers to the best * `FluentBundle` instance(s). * - * @param {AsyncIterable} iterable - * @param {string|Array} ids - * @returns {Promise>} + * @param bundles - An iterable of bundles to sift through. + * @param ids - An id or ids to map. */ -export default async function mapBundleAsync(iterable, ids) { +export async function mapBundleAsync( + bundles: AsyncIterable, + ids: string | Array +): Promise> { if (!Array.isArray(ids)) { - for await (const bundle of iterable) { + for await (const bundle of bundles) { if (bundle.hasMessage(ids)) { return bundle; } } + + return null; } + const foundBundles = new Array(ids.length).fill(null); let remainingCount = ids.length; - const foundBundles = new Array(remainingCount).fill(null); - for await (const bundle of iterable) { + for await (const bundle of bundles) { for (const [index, id] of ids.entries()) { if (!foundBundles[index] && bundle.hasMessage(id)) { foundBundles[index] = bundle; remainingCount--; } - // Return early when all ids have been mapped to contexts. + // Return early when all ids have been mapped to bundles. if (remainingCount === 0) { return foundBundles; } diff --git a/fluent-sequence/src/map_sync.js b/fluent-sequence/src/map_sync.js deleted file mode 100644 index b40cedbe3..000000000 --- a/fluent-sequence/src/map_sync.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Synchronously map an identifier or an array of identifiers to the best - * `FluentBundle` instance(s). - * - * @param {Iterable} iterable - * @param {string|Array} ids - * @returns {FluentBundle|Array} - */ -export default function mapBundleSync(iterable, ids) { - if (!Array.isArray(ids)) { - return getBundleForId(iterable, ids); - } - - return ids.map( - id => getBundleForId(iterable, id) - ); -} - -/* - * Find the best `FluentBundle` with the translation for `id`. - */ -function getBundleForId(iterable, id) { - for (const bundle of iterable) { - if (bundle.hasMessage(id)) { - return bundle; - } - } - - return null; -} diff --git a/fluent-sequence/src/map_sync.ts b/fluent-sequence/src/map_sync.ts new file mode 100644 index 000000000..58de71500 --- /dev/null +++ b/fluent-sequence/src/map_sync.ts @@ -0,0 +1,37 @@ +import { FluentBundle } from "@fluent/bundle"; + +/* + * Synchronously map an identifier or an array of identifiers to the best + * `FluentBundle` instance(s). + * + * @param bundles - An iterable of bundles to sift through. + * @param ids - An id or ids to map. + */ +export function mapBundleSync( + bundles: Iterable, + ids: string | Array +): FluentBundle | null | Array { + if (!Array.isArray(ids)) { + return getBundleForId(bundles, ids); + } + + return ids.map( + id => getBundleForId(bundles, id) + ); +} + +/* + * Find the best `FluentBundle` with the translation for `id`. + */ +function getBundleForId( + bundles: Iterable, + id: string +): NonNullable | null { + for (const bundle of bundles) { + if (bundle.hasMessage(id)) { + return bundle; + } + } + + return null; +} diff --git a/fluent-sequence/test/fallback_async_test.js b/fluent-sequence/test/fallback_async_test.js index be6146335..9d00f87e6 100644 --- a/fluent-sequence/test/fallback_async_test.js +++ b/fluent-sequence/test/fallback_async_test.js @@ -2,7 +2,7 @@ import assert from 'assert'; import {CachedAsyncIterable} from 'cached-iterable'; import FluentBundle from './bundle_stub'; -import {mapBundleAsync} from '../src/index'; +import {mapBundleAsync} from '../esm/index'; suite('Async Fallback — single id', function() { let bundle1, bundle2, generateBundles; diff --git a/fluent-sequence/test/fallback_sync_test.js b/fluent-sequence/test/fallback_sync_test.js index b28382bb8..4dab3d376 100644 --- a/fluent-sequence/test/fallback_sync_test.js +++ b/fluent-sequence/test/fallback_sync_test.js @@ -2,7 +2,7 @@ import assert from 'assert'; import {CachedSyncIterable} from 'cached-iterable'; import FluentBundle from './bundle_stub'; -import {mapBundleSync} from '../src/index'; +import {mapBundleSync} from '../esm/index'; suite('Sync Fallback — single id', function() { let bundle1, bundle2; diff --git a/fluent-sequence/tsconfig.json b/fluent-sequence/tsconfig.json new file mode 100644 index 000000000..45fefaee8 --- /dev/null +++ b/fluent-sequence/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es2019", + "module": "es2015", + "strict": true, + "allowJs": false, + "esModuleInterop": true, + "moduleResolution": "node", + "noEmitHelpers": true, + "declaration": true, + "outDir": "./esm", + }, + "include": [ + "./src/**/*.ts" + ] +} From 0d22a5bc426ca6ef50fb2058f05858d5b618de4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sta=C5=9B=20Ma=C5=82olepszy?= Date: Mon, 27 Jan 2020 16:16:15 +0100 Subject: [PATCH 2/4] (@fluent/sequence) Remove BundleStub from tests --- fluent-sequence/test/bundle_stub.js | 19 ------------------- fluent-sequence/test/fallback_async_test.js | 14 +++++++------- fluent-sequence/test/fallback_sync_test.js | 10 +++++----- 3 files changed, 12 insertions(+), 31 deletions(-) delete mode 100644 fluent-sequence/test/bundle_stub.js diff --git a/fluent-sequence/test/bundle_stub.js b/fluent-sequence/test/bundle_stub.js deleted file mode 100644 index 0eca6671d..000000000 --- a/fluent-sequence/test/bundle_stub.js +++ /dev/null @@ -1,19 +0,0 @@ -export default class BundleStub { - _setMessages(ids) { - this.ids = ids; - } - - hasMessage(id) { - return this.ids.includes(id); - } - - getMessage(id) { - if (this.hasMessage(id)) { - return id.toUpperCase(); - } - } - - format(msg) { - return msg; - } -} diff --git a/fluent-sequence/test/fallback_async_test.js b/fluent-sequence/test/fallback_async_test.js index 9d00f87e6..232f323db 100644 --- a/fluent-sequence/test/fallback_async_test.js +++ b/fluent-sequence/test/fallback_async_test.js @@ -1,7 +1,7 @@ import assert from 'assert'; import {CachedAsyncIterable} from 'cached-iterable'; -import FluentBundle from './bundle_stub'; +import {FluentBundle, FluentResource} from '@fluent/bundle'; import {mapBundleAsync} from '../esm/index'; suite('Async Fallback — single id', function() { @@ -9,9 +9,9 @@ suite('Async Fallback — single id', function() { suiteSetup(function() { bundle1 = new FluentBundle(); - bundle1._setMessages(['bar']); + bundle1.addResource(new FluentResource("bar=Bar")); bundle2 = new FluentBundle(); - bundle2._setMessages(['foo', 'bar']); + bundle2.addResource(new FluentResource("foo=Foo\nbar=Bar")); generateBundles = async function *generateBundles() { yield *[bundle1, bundle2]; @@ -52,9 +52,9 @@ suite('Async Fallback — multiple ids', async function() { suiteSetup(function() { bundle1 = new FluentBundle(); - bundle1._setMessages(['foo', 'bar']); + bundle1.addResource(new FluentResource("foo=Foo\nbar=Bar")); bundle2 = new FluentBundle(); - bundle2._setMessages(['foo', 'bar', 'baz']); + bundle2.addResource(new FluentResource("foo=Foo\nbar=Bar\nbaz=Baz")); generateBundles = async function *generateBundles() { yield *[bundle1, bundle2]; @@ -91,9 +91,9 @@ suite('Async Fallback — early return', async function() { suiteSetup(function() { bundle1 = new FluentBundle(); - bundle1._setMessages(['foo', 'bar']); + bundle1.addResource(new FluentResource("foo=Foo\nbar=Bar")); bundle2 = new FluentBundle(); - bundle2._setMessages(['foo', 'bar', 'baz']); + bundle2.addResource(new FluentResource("foo=Foo\nbar=Bar\nbaz=Baz")); }); test('break early if possible', async function() { diff --git a/fluent-sequence/test/fallback_sync_test.js b/fluent-sequence/test/fallback_sync_test.js index 4dab3d376..ccccc227d 100644 --- a/fluent-sequence/test/fallback_sync_test.js +++ b/fluent-sequence/test/fallback_sync_test.js @@ -1,7 +1,7 @@ import assert from 'assert'; import {CachedSyncIterable} from 'cached-iterable'; -import FluentBundle from './bundle_stub'; +import {FluentBundle, FluentResource} from '@fluent/bundle'; import {mapBundleSync} from '../esm/index'; suite('Sync Fallback — single id', function() { @@ -9,9 +9,9 @@ suite('Sync Fallback — single id', function() { suiteSetup(function() { bundle1 = new FluentBundle(); - bundle1._setMessages(['bar']); + bundle1.addResource(new FluentResource("bar=Bar")); bundle2 = new FluentBundle(); - bundle2._setMessages(['foo', 'bar']); + bundle2.addResource(new FluentResource("foo=Foo\nbar=Bar")); }); test('eager iterable', function() { @@ -56,9 +56,9 @@ suite('Sync Fallback — multiple ids', function() { suiteSetup(function() { bundle1 = new FluentBundle(); - bundle1._setMessages(['foo', 'bar']); + bundle1.addResource(new FluentResource("foo=Foo\nbar=Bar")); bundle2 = new FluentBundle(); - bundle2._setMessages(['foo', 'bar', 'baz']); + bundle2.addResource(new FluentResource("foo=Foo\nbar=Bar\nbaz=Baz")); }); test('existing translations', function() { From a468794a7ebfdeeaf7dbec03a55082791cc9268f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sta=C5=9B=20Ma=C5=82olepszy?= Date: Mon, 27 Jan 2020 16:21:39 +0100 Subject: [PATCH 3/4] Use a common eslint config --- .../eslint_src.json => eslint_ts.json | 2 +- fluent-bundle/makefile | 2 +- fluent-sequence/eslint_src.json | 26 ------------------- fluent-sequence/makefile | 2 +- 4 files changed, 3 insertions(+), 29 deletions(-) rename fluent-bundle/eslint_src.json => eslint_ts.json (96%) delete mode 100644 fluent-sequence/eslint_src.json diff --git a/fluent-bundle/eslint_src.json b/eslint_ts.json similarity index 96% rename from fluent-bundle/eslint_src.json rename to eslint_ts.json index 2aa340b27..5d3433ddd 100644 --- a/fluent-bundle/eslint_src.json +++ b/eslint_ts.json @@ -13,7 +13,7 @@ "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking", - "../eslint_src.json" + "./eslint_src.json" ], "rules": { "prefer-const": "off", diff --git a/fluent-bundle/makefile b/fluent-bundle/makefile index 2b612e19d..c7210775a 100644 --- a/fluent-bundle/makefile +++ b/fluent-bundle/makefile @@ -4,7 +4,7 @@ GLOBAL := FluentBundle include ../common.mk lint: - @eslint --config ./eslint_src.json --max-warnings 0 src/*.ts + @eslint --config $(ROOT)/eslint_ts.json --max-warnings 0 src/*.ts @eslint --config $(ROOT)/eslint_test.json --max-warnings 0 test/ @echo -e " $(OK) lint" diff --git a/fluent-sequence/eslint_src.json b/fluent-sequence/eslint_src.json deleted file mode 100644 index 2aa340b27..000000000 --- a/fluent-sequence/eslint_src.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 9, - "sourceType": "module", - "project": "./tsconfig.json" - }, - "env": { - "es6": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "../eslint_src.json" - ], - "rules": { - "prefer-const": "off", - "no-unused-vars": ["error", {"args": "none"}], - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/no-unused-vars": ["error", {"args": "none"}], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/explicit-function-return-type": "error" - } -} diff --git a/fluent-sequence/makefile b/fluent-sequence/makefile index 4fdd9268e..b7db9dc3b 100644 --- a/fluent-sequence/makefile +++ b/fluent-sequence/makefile @@ -4,7 +4,7 @@ GLOBAL := FluentSequence include ../common.mk lint: - @eslint --config ./eslint_src.json --max-warnings 0 src/*.ts + @eslint --config $(ROOT)/eslint_ts.json --max-warnings 0 src/*.ts @eslint --config $(ROOT)/eslint_test.json --max-warnings 0 test/ @echo -e " $(OK) lint" From baaddaa4f9c452cdab0dc041df90d48114f22d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sta=C5=9B=20Ma=C5=82olepszy?= Date: Mon, 27 Jan 2020 16:33:37 +0100 Subject: [PATCH 4/4] (@fluent/sequence) Overload function signatures --- fluent-sequence/src/map_async.ts | 10 ++++++++++ fluent-sequence/src/map_sync.ts | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/fluent-sequence/src/map_async.ts b/fluent-sequence/src/map_async.ts index bb439a6a3..2b4b1ba0b 100644 --- a/fluent-sequence/src/map_async.ts +++ b/fluent-sequence/src/map_async.ts @@ -1,5 +1,15 @@ import { FluentBundle } from "@fluent/bundle"; +export function mapBundleAsync( + bundles: AsyncIterable, + ids: string +): Promise + +export function mapBundleAsync( + bundles: AsyncIterable, + ids: Array +): Promise>; + /* * Asynchronously map an identifier or an array of identifiers to the best * `FluentBundle` instance(s). diff --git a/fluent-sequence/src/map_sync.ts b/fluent-sequence/src/map_sync.ts index 58de71500..446dc1183 100644 --- a/fluent-sequence/src/map_sync.ts +++ b/fluent-sequence/src/map_sync.ts @@ -1,5 +1,15 @@ import { FluentBundle } from "@fluent/bundle"; +export function mapBundleSync( + bundles: Iterable, + ids: string +): FluentBundle | null; + +export function mapBundleSync( + bundles: Iterable, + ids: Array +): Array; + /* * Synchronously map an identifier or an array of identifiers to the best * `FluentBundle` instance(s).