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/.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..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" @@ -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/makefile b/fluent-sequence/makefile index 8d79d8a6c..b7db9dc3b 100644 --- a/fluent-sequence/makefile +++ b/fluent-sequence/makefile @@ -3,7 +3,21 @@ GLOBAL := FluentSequence include ../common.mk -test: +lint: + @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" + +.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.js deleted file mode 100644 index ebd2abe77..000000000 --- a/fluent-sequence/src/map_async.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Asynchronously map an identifier or an array of identifiers to the best - * `FluentBundle` instance(s). - * - * @param {AsyncIterable} iterable - * @param {string|Array} ids - * @returns {Promise>} - */ -export default async function mapBundleAsync(iterable, ids) { - if (!Array.isArray(ids)) { - for await (const bundle of iterable) { - if (bundle.hasMessage(ids)) { - return bundle; - } - } - } - - let remainingCount = ids.length; - const foundBundles = new Array(remainingCount).fill(null); - - for await (const bundle of iterable) { - 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. - if (remainingCount === 0) { - return foundBundles; - } - } - } - - return foundBundles; -} diff --git a/fluent-sequence/src/map_async.ts b/fluent-sequence/src/map_async.ts new file mode 100644 index 000000000..2b4b1ba0b --- /dev/null +++ b/fluent-sequence/src/map_async.ts @@ -0,0 +1,52 @@ +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). + * + * @param bundles - An iterable of bundles to sift through. + * @param ids - An id or ids to map. + */ +export async function mapBundleAsync( + bundles: AsyncIterable, + ids: string | Array +): Promise> { + if (!Array.isArray(ids)) { + 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; + + 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 bundles. + if (remainingCount === 0) { + return foundBundles; + } + } + } + + 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..446dc1183 --- /dev/null +++ b/fluent-sequence/src/map_sync.ts @@ -0,0 +1,47 @@ +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). + * + * @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/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 be6146335..232f323db 100644 --- a/fluent-sequence/test/fallback_async_test.js +++ b/fluent-sequence/test/fallback_async_test.js @@ -1,17 +1,17 @@ import assert from 'assert'; import {CachedAsyncIterable} from 'cached-iterable'; -import FluentBundle from './bundle_stub'; -import {mapBundleAsync} from '../src/index'; +import {FluentBundle, FluentResource} from '@fluent/bundle'; +import {mapBundleAsync} from '../esm/index'; suite('Async Fallback — single id', function() { let bundle1, bundle2, generateBundles; 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 b28382bb8..ccccc227d 100644 --- a/fluent-sequence/test/fallback_sync_test.js +++ b/fluent-sequence/test/fallback_sync_test.js @@ -1,17 +1,17 @@ import assert from 'assert'; import {CachedSyncIterable} from 'cached-iterable'; -import FluentBundle from './bundle_stub'; -import {mapBundleSync} from '../src/index'; +import {FluentBundle, FluentResource} from '@fluent/bundle'; +import {mapBundleSync} from '../esm/index'; suite('Sync Fallback — single id', function() { let bundle1, bundle2; 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() { 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" + ] +}