Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(@formatjs/intl-segmenter): Intl.Segmenter polyfill (stage 4) (#3917
- Loading branch information
1 parent
cc3a81f
commit 3020876
Showing
36 changed files
with
18,805 additions
and
43 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
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
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,175 @@ | ||
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files") | ||
load("@aspect_rules_js//npm/private:npm_package.bzl", "npm_package") | ||
load("@aspect_rules_ts//ts:defs.bzl", "ts_project") | ||
load("@npm//:defs.bzl", "npm_link_all_packages") | ||
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild") | ||
load("//:index.bzl", "ZONES") | ||
load("@npm//:test262-harness/package_json.bzl", test262_harness_bin = "bin") | ||
load("//tools:index.bzl", "check_format", "generate_src_file", "ts_compile") | ||
load("//tools:jest.bzl", "jest_test") | ||
|
||
npm_link_all_packages(name = "node_modules") | ||
|
||
PACKAGE_NAME = "intl-segmenter" | ||
|
||
npm_package( | ||
name = PACKAGE_NAME, | ||
srcs = [ | ||
"LICENSE.md", | ||
"README.md", | ||
"package.json", | ||
":dist", | ||
# polyfill-library uses this | ||
"polyfill.iife.js", | ||
], | ||
package = "@formatjs/%s" % PACKAGE_NAME, | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
SRC_DEPS = [ | ||
":node_modules/@formatjs/ecma402-abstract", | ||
":node_modules/@formatjs/intl-localematcher", | ||
] | ||
|
||
TEST_DEPS = SRC_DEPS + [ | ||
"//:node_modules/@types/node", | ||
"tests/test-utils.ts", | ||
"unicodeFiles/GraphemeBreakTest.txt", | ||
"unicodeFiles/WordBreakTest.txt", | ||
"unicodeFiles/SentenceBreakTest.txt", | ||
] | ||
|
||
SRCS = glob( | ||
[ | ||
"src/**/*.ts", | ||
"*.ts", | ||
], | ||
exclude = [ | ||
#for development only | ||
"debug.ts", | ||
"benchmark.ts", | ||
"tests/**/*", | ||
], | ||
) | ||
|
||
TESTS = glob([ | ||
"tests/*.test.ts", | ||
]) | ||
|
||
ts_compile( | ||
name = "dist", | ||
srcs = SRCS, | ||
package = "@formatjs/%s" % PACKAGE_NAME, | ||
skip_esm = False, | ||
deps = SRC_DEPS, | ||
) | ||
|
||
jest_test( | ||
name = "unit", | ||
srcs = SRCS + TESTS, | ||
deps = TEST_DEPS, | ||
) | ||
|
||
generate_src_file( | ||
name = "test262-main", | ||
src = "test262-main.ts", | ||
entry_point = "scripts/test262-main-gen.ts", | ||
visibility = [ | ||
"//:__pkg__", | ||
], | ||
) | ||
|
||
# Test262 | ||
ts_project( | ||
name = "test262-main-bundle", | ||
srcs = SRCS, | ||
declaration = True, | ||
declaration_map = True, | ||
out_dir = "test262", | ||
resolve_json_module = True, | ||
tsconfig = "//:tsconfig.es6", | ||
deps = SRC_DEPS, | ||
) | ||
|
||
esbuild( | ||
name = "test262-polyfill", | ||
entry_point = "test262/test262-main.js", | ||
target = "es6", | ||
deps = [ | ||
":test262-main-bundle", | ||
] + SRC_DEPS, | ||
) | ||
|
||
test262_harness_bin.test262_harness_test( | ||
name = "test262", | ||
size = "large", | ||
args = [ | ||
"--reporter-keys", | ||
"file,attrs,result", | ||
"--errorForFailures", | ||
"--timeout", | ||
"30000", | ||
"--prelude", | ||
"$(rootpath test262-polyfill.js)", | ||
"--test262Dir", | ||
"../com_github_tc39_test262", | ||
"../com_github_tc39_test262/test/intl402/Segmenter/**/*.js", | ||
], | ||
data = [ | ||
"test262-polyfill.js", | ||
"@com_github_tc39_test262//:test262-harness-copy", | ||
"@com_github_tc39_test262//:test262-segmenter-copy", | ||
], | ||
# TODO: fix | ||
tags = ["manual"], | ||
) | ||
|
||
write_source_files( | ||
name = "generated-files", | ||
files = {"tsconfig.json": "//tools:tsconfig.golden.json"}, | ||
visibility = ["//:__pkg__"], | ||
) | ||
|
||
esbuild( | ||
name = "polyfill.iife", | ||
entry_point = "lib/polyfill.js", | ||
target = "es6", | ||
# TODO: fix this and set it back to es5 | ||
deps = [ | ||
":dist-esm", | ||
"//:node_modules/tslib", | ||
] + SRC_DEPS, | ||
) | ||
|
||
check_format( | ||
name = "prettier", | ||
srcs = glob( | ||
[ | ||
"**/*", | ||
], | ||
exclude = [ | ||
"CHANGELOG.md", | ||
"src/*.generated.*", | ||
"unicodeFiles/*.txt", | ||
"test262-main.ts", | ||
], | ||
), | ||
) | ||
|
||
# Segmentation UCDs | ||
generate_src_file( | ||
name = "generate-cldr-segmentation-rules", | ||
src = "src/cldr-segmentation-rules.generated.ts", | ||
data = [ | ||
"unicodeFiles/DerivedCombiningClass.txt", | ||
"unicodeFiles/DerivedEastAsianWidth.txt", | ||
"unicodeFiles/GraphemeBreakProperty.txt", | ||
"unicodeFiles/IndicSyllabicCategory.txt", | ||
"unicodeFiles/SentenceBreakProperty.txt", | ||
"unicodeFiles/WordBreakProperty.txt", | ||
"//:node_modules/@types/regenerate", | ||
"//:node_modules/cldr-segments-full", | ||
"//:node_modules/regexpu-core", | ||
], | ||
entry_point = "scripts/generate-cldr-segmentation-rules.ts", | ||
) |
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,9 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 FormatJS | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
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,99 @@ | ||
# Notes and links | ||
|
||
## Unicode Text Segmentation (UAX29) | ||
|
||
The official document describing the unicode segmentation | ||
<http://unicode.org/reports/tr29/> | ||
|
||
## CLDR locale segmentation rules | ||
|
||
Unicode Common Locale Data Repository where locale (and root) segmentation rules are specified | ||
|
||
CLDR segmentation rules: <https://github.com/unicode-org/cldr/tree/main/common/segments> | ||
|
||
information about the rules: <https://unicode.org/reports/tr35/tr35-general.html#Segmentations> | ||
|
||
JSON CLDR: <https://github.com/unicode-org/cldr-json/tree/main/cldr-json/cldr-segments-full> (`und` is the root ruleset) | ||
|
||
### CLDR Rules notes | ||
|
||
CLDR Rules use unicode flavuored regex (<https://unicode.org/reports/tr18/>) which is not directly compatible with js regex. | ||
|
||
Modern JS (es6) implements `/u` flag that allows some unicode regex features: [property escapes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes) `\p{..}`, handling of 4 bytes characters. (`regexpu` can transpile them to es5) | ||
There is also the `/v` flag proposal (<https://github.com/tc39/proposal-regexp-v-flag>) that adds set operations (`--` and `&&`) and nested character groups (both used by the CLDR rules), `regexpu` can transpile those too | ||
|
||
CLDR rules use some character classes that are not implemented by `regexpu`, but the code lists are avalible in the UCD files (see [UCD](#UCD) Notes) | ||
|
||
More details about syntax incompatiblities in [CLDR Rules RegExes](#CLDRRulesRegex) | ||
|
||
## <a name="UCD"></a>UCD | ||
|
||
unicode character database: <https://unicode.org/ucd/> | ||
|
||
UCD Files: <https://www.unicode.org/Public/15.0.0/ucd/> | ||
|
||
Segmentation properties and tests: <https://www.unicode.org/Public/15.0.0/ucd/auxiliary/> | ||
|
||
Character sets used by the CLDRs, that are missing from es5 regex and regexpu-core: | ||
|
||
- `Grapheme_Cluster_Break` : <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt> (more information @ <https://unicode.org/reports/tr29/#Grapheme_Cluster_Break_Property_Values>) | ||
- `Sentence_Break`: <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/SentenceBreakProperty> | ||
- `Word_Break`: <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/WordBreakProperty.txt> | ||
- `Indic_Syllabic_Category`: <https://unicode.org/Public/UCD/latest/ucd/IndicSyllabicCategory.txt> | ||
- `ea=` => East_Asian_Width => : <https://unicode.org/Public/UCD/latest/ucd/extracted/DerivedEastAsianWidth.txt> | ||
- `ccc` => Canonical_Combining_Class => <https://unicode.org/Public/UCD/latest/ucd/extracted/DerivedCombiningClass.txt> | ||
|
||
Properties can use aliases: [PropertyAliases.txt](https://unicode.org/Public/UCD/latest/ucd/PropertyAliases.txt) | ||
|
||
Property values can use aliases: [PropertyValueAliases.txt](https://unicode.org/Public/UCD/latest/ucd/PropertyValueAliases.txt) | ||
|
||
### Segmentation Tests | ||
|
||
<https://unicode.org/reports/tr41/tr41-26.html#Tests29> | ||
|
||
About test files: <https://www.unicode.org/reports/tr44/#Segmentation_Test_Files> | ||
|
||
Grapheme segmentation tests: <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt> | ||
Sentence segmentation tests: <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/SentenceBreakTest.txt> | ||
Word break segmentation tests: <https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/WordBreakTest.txt> | ||
|
||
## Other segmentation implementations found | ||
|
||
- JS: <https://github.com/orling/grapheme-splitter> | ||
- JS Polyfill: <https://www.npmjs.com/package/intl-segmenter-polyfill> (using icu C compiled in wasm+) | ||
- GO: <https://github.com/clipperhouse/uax29> | ||
- Rust: <https://github.com/unicode-rs/unicode-segmentation> | ||
|
||
- Java <https://github.com/unicode-org/unicodetools/blob/70dce2c89f185c65b436c28404ae5b7bdb32c2d1/unicodetools/src/main/java/org/unicode/tools/Segmenter.java#L485> | ||
<https://github.com/unicode-org/unicodetools/blob/70dce2c89f185c65b436c28404ae5b7bdb32c2d1/unicodetools/src/test/java/org/unicode/test/CompareBoundaries.java#L473> | ||
|
||
## <a name="CLDRRulesRegex"></a>CLDR Rules RegExes | ||
|
||
CLDR Rules use unicode regex (unsupported by JS). | ||
|
||
There is a set of utils in the unicode repo that allows transformation of unicode regex to java compatible regex: | ||
|
||
<https://github.com/unicode-org/unicodetools> | ||
|
||
and UnicodeJsps hosted on the unicode.org: <https://util.unicode.org/UnicodeJsps> | ||
|
||
### JS Regex utils for unicode | ||
|
||
<https://github.com/mathiasbynens/regenerate> can generate es5 regex given a list of unicode symbols | ||
<https://github.com/mathiasbynens/regexpu-core> Can transpile es2015 (`/u`) regex to es5 and `/v` to unicode regex (with [some limitations](https://github.com/mathiasbynens/regexpu-core#caveats)) | ||
|
||
The unicode regexs have other syntax incompatiblities: | ||
|
||
- set operands are single character `-` instead of `--` | ||
- there are spaces in the regex that need to be ignored `[[$Extend-\\\\p{ccc=0}] $ZWJ]` | ||
- Some properties in CLDR do not seem to follow the spec strictly: `\p{Gujr}` should be `\{sc=Gujr}` | ||
- it seems muliple character classes in a row are treated as signle class when performing set operations: `\p{..}\p{...}&[..]` in unicode is treated as `[...]&[...]` but regexpu `\v` treates it as `[...][...]&[...]` | ||
- The way rules are constructed, have issues with negated and normal transpiled character classes `[^(?:...)]` `[(?:..)]`. | ||
|
||
Even after accounting for all of those, there are issues left: | ||
|
||
`cldr-segments-full/segments/el/suppressions.json` has a rule `"$STerm": "[[$STerm] [\\u003B \\u037E]]"` which I currently do not know how to correctly process. | ||
|
||
## isWordLike | ||
|
||
<https://github.com/tc39/proposal-intl-segmenter/issues/100> |
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,3 @@ | ||
# `intl-segmenter` | ||
|
||
We've migrated the docs to https://formatjs.io/docs/polyfills/intl-segmenter. |
Oops, something went wrong.