-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Status Chart: Mega TypeScript overhaul, PR/CI checks, libcxx change #2588
Merged
StephanTLavavej
merged 47 commits into
microsoft:gh-pages
from
StephanTLavavej:gh-pages
Mar 19, 2022
Merged
Status Chart: Mega TypeScript overhaul, PR/CI checks, libcxx change #2588
StephanTLavavej
merged 47 commits into
microsoft:gh-pages
from
StephanTLavavej:gh-pages
Mar 19, 2022
Conversation
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
StephanTLavavej
added
documentation
Related to documentation or comments
infrastructure
Related to repository automation
labels
Feb 22, 2022
Note: conflicts in |
CaseyCarter
approved these changes
Mar 17, 2022
StephanTLavavej
force-pushed
the
gh-pages
branch
from
March 18, 2022 20:02
ab1b671
to
4b43594
Compare
I've pushed a weekly update, dependency update, and rebased/regenerated. |
I was being silly.
/built/status_chart.mjs will be checked in.
We've configured TypeScript to be strict, superseding `'use strict';`. This exports a `WeeklyRow` type, where `cxx17`, `cxx20`, and `lwg` are optional (as we stopped recording them here when the GitHub era began). Finally, this exports the `weekly_table`, with a type of `WeeklyRow[]`.
This "join an array of strings" code was added in GH 1170, when the daily_table used the same technique. The daily_table stopped using join() in GH 1895. IIRC, join() allowed me to easily experiment with reordering properties, during the early days when I avoided emitting trailing commas. Now, join() provides no value here, just complexity.
While gather_stats.ts is a CRLF file, JavaScript/TypeScript guarantee that multiline template literals produce LF line endings, so the generated LF files won't be disrupted. * In `write_generated_file()`: + We could use placeholders to expand the warning comment, but it's simpler to just repeat it. + We can now use `const str`. + To improve indentation/appearance, these template literals begin and end with a newline. We don't want the generated file to start with a newline, so we need to call `str.trimStart()`. + We also need to call `table_str.trim()` as `write_generated_file()` is already emitting newlines around it.
Again, we're dropping `'use strict';`. Some `DailyRow` properties can be `null`, when `should_emit_data_point()` detects that a line has fallen to 0.
We're switching from chartjs-adapter-date-fns to chartjs-adapter-luxon, as luxon is smaller when unbundled, and we've already npm installed it.
Instead of being added as properties of `window`. Fixes error TS2339: Property 'status_chart' does not exist on type 'Window & typeof globalThis'.
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions Fixes: error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'DailyRow'. No index signature with a parameter of type 'string' was found on type 'DailyRow'. error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'WeeklyRow'. No index signature with a parameter of type 'string' was found on type 'WeeklyRow'.
Fixes error TS7006: Parameter 'key' implicitly has an 'any' type.
Previously, TypeScript was inferring `any`.
This avoids injecting properties into the chart datasets, fixing: error TS2339: Property 'stl_default_hidden' does not exist on type 'ChartDataset<...>'. error TS2339: Property 'stl_key' does not exist on type 'ChartDataset<...>'.
Fixes errors of the form: error TS2322: Type X is not assignable to type Y. The types of 'hover.mode' are incompatible between these types. Type 'string' is not assignable to type '"index" | "nearest" | "dataset" | "x" | "y" | "point" | undefined'.
Fixes error TS2322: Type X is not assignable to type Y.
…ns.scales.x`. Fixes: error TS2532: Object is possibly 'undefined'. error TS2339: Property 'time' does not exist on type X.
Fixes: error TS7006: Parameter 'table' implicitly has an 'any' type. error TS7006: Parameter 'key' implicitly has an 'any' type. error TS7006: Parameter 'row' implicitly has an 'any' type.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script Previously, status_chart.js was executed immediately, so we could set `window.onload` and it would take effect later. Now, module scripts are deferred by default. (We don't even need to wrap this in a function, but it simplifies the diff.)
This extracts the compilerOptions to tsconfig.universal.json. Now, src_gather/tsconfig.json is for gather_stats.ts in that directory. src/tsconfig.json is for status_chart.ts in that directory and adds the `noEmit` option, because esbuild will perform codegen after tsc performs type checking. Both scripts want `"moduleResolution": "node"`, the modern strategy: https://www.typescriptlang.org/docs/handbook/module-resolution.html#module-resolution-strategies For codegen, gather_stats.ts still wants `"module": "CommonJS"` (although it could be upgraded in the future). status_chart.ts wants `"module": "ES2020"` (technically, this option doesn't matter because esbuild performs codegen, but I thought it would be confusing to omit).
Tested in my fork. For gather_stats.ts, we need to pass `--noEmit` because we want only type checking, not codegen. For status_chart.ts, it's already configured with `"noEmit": true`.
Improve organization with a "Getting Started" header and subheaders. Update Node.js version. Note that `gh-pages` is the default, but can be customized now. (The instructions don't attempt to cover such customization.) Add a section explaining how to enable GitHub Pages. Extract the `token-formats` link for readability. The instructions changed to a "public access" token in GH 1808, which is no longer password-equivalent, but it still should remain secret. Mention that the `importmap` (used in the browser) should be kept in sync with the `node_modules` updated by `npm update`/`npm install` (and used when compiling TypeScript). Update filenames. `npm run gather` is the new way to compile and run `gather_stats.ts`. Explain the new `npm run make` and `npm run view` scripts. Add a reminder about manually updating generated files.
StephanTLavavej
force-pushed
the
gh-pages
branch
from
March 19, 2022 10:44
4b43594
to
5ee763b
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
🗺️ Overview
This upgrades the browser-rendered part of the Status Chart to TypeScript, greatly increasing its maintainability and resistance to bugs (some were found during this conversion and fixed in earlier PRs). This is increasingly important as the Status Chart has grown increasingly elaborate.
Because the browser can't directly interpret TypeScript, we need a build system. This uses
tsc
to perform type checking, followed byesbuild
to bundle the Status Chart's main script with the daily/weekly/monthly tables. (That bundled output is checked into thegh-pages
branch and updated daily. It changes at the same pace as the tables, and although it's minified, it substantially shares their content, so this should be extremely compressible and not a concern for repo bloat.) The Chart.js support machinery is still loaded through CDNs, but now via modern ECMAScript modules. (This was exceedingly difficult to figure out, but the end result is very elegant, and prevents Chart.js code from being committed to the repo in minified form. Otherwise, bundling everything would be simpler.)We no longer have Subresource Integrity checks on the CDN scripts (because the ESMs are dynamically generated), but as this is not a mission-critical page, we'll live.
This also adds PR/CI checks to verify that
gather_stats.ts
andstatus_chart.ts
will compile. These checks run directly in GitHub Actions with no Azure Pipelines involvement, and are very fast.Now that #2499 has merged to
main
, this switches the libcxx line to a new methodology.This will have a companion PR targeted at
main
because the daily automated updates will need new commands.Finally, although I've put extensive effort into organizing weeks of hacking into comprehensible, isolated commits, they aren't in any particular order here (the conversion should be thought of as happening all at once, with intermediate commits not in a buildable state).
📊
src/status_chart.ts
Changesstatus_chart.js
tosrc/status_chart.ts
.strict
supersedes'use strict';
.chartjs-adapter-date-fns
tochartjs-adapter-luxon
, asluxon
is smaller when unbundled, and we've alreadynpm install
ed it.status_chart
etc. should be separate variables.window
.error TS2339: Property 'status_chart' does not exist on type 'Window & typeof globalThis'.
moreHistoryButton
,lessHistoryButton
.error TS2531: Object is possibly 'null'.
error TS2339: Property 'disabled' does not exist on type 'HTMLElement'.
span
asHTMLSpanElement
.error TS2531: Object is possibly 'null'.
getElementByIdAs()
for safety.Error
s (viewable in the console) if the elements don't exist or have the wrong type, which would happen ifindex.html
isn't kept in sync with the script.legend_click_handler()
.error TS7006: Parameter '_event' implicitly has an 'any' type.
(etc.)Timeframe
type.error TS7006: Parameter 'timeframe' implicitly has an 'any' type.
update_chart_timeframe()
.error TS7006: Parameter 'chart' implicitly has an 'any' type.
(etc.)typeof status_chart
instead ofChart
avoidserror TS2379: Argument of type 'Chart<X>' is not assignable to parameter of type 'Chart<Y>' [...] The types of 'config.data' are incompatible between these types.
const
assertions fordaily_keys
,weekly_keys
.error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'DailyRow'. No index signature with a parameter of type 'string' was found on type 'DailyRow'.
(etc.)get_hidden()
.error TS7006: Parameter 'key' implicitly has an 'any' type.
hidden
asboolean
.any
.HiddenInfoMaps.lookup()
.error TS2339: Property 'stl_default_hidden' does not exist on type 'ChartDataset<...>'.
(etc.)const
.error TS2322: Type X is not assignable to type Y. The types of 'hover.mode' are incompatible between these types. Type 'string' is not assignable to type '"index" | "nearest" | "dataset" | "x" | "y" | "point" | undefined'.
type: 'bar' as const
inmerge_data
.error TS2322: Type X is not assignable to type Y.
make_xAxis()
producedchart.options.scales.x
.error TS2532: Object is possibly 'undefined'.
error TS2339: Property 'time' does not exist on type X.
make_xAxis()
again.get_values()
.error TS7006: Parameter 'table' implicitly has an 'any' type.
(etc.)window.onload
withload_charts()
.status_chart.js
was executed immediately, so we could setwindow.onload
and it would take effect later.max
/stepSize
.🛠️ Other Changes
npm install [dependencies]@latest
npm install chart.js chartjs-adapter-luxon esbuild http-server
spanGaps
not recognized inoptions.elements.line
chartjs/Chart.js#10132 and Types: Time scales with string values aren't recognized chartjs/Chart.js#10134..vscode/settings.json
: Removeterminal.integrated.cwd
..gitignore
: Ignore only/built/gather_stats.js
./built/status_chart.mjs
will be checked in.src/weekly_table.ts
: Move, manually change to TypeScript.'use strict';
.WeeklyRow
type, wherecxx17
,cxx20
, andlwg
are optional (as we stopped recording them here when the GitHub era began).weekly_table
, with a type ofWeeklyRow[]
.gather_stats.ts
: Simplifymonthly_table
printing.daily_table
used the same technique. Thedaily_table
stopped usingjoin()
in Status Chart: Avoid emitting consecutive zeros #1895. IIRC,join()
allowed me to easily experiment with reordering properties, during the early days when I avoided emitting trailing commas. Now,join()
provides no value here, just complexity.gather_stats.ts
: Simplify with multiline template literals.gather_stats.ts
is a CRLF file, JavaScript/TypeScript guarantee that multiline template literals produce LF line endings, so the generated LF files won't be disrupted.write_generated_file()
:const str
.str.trimStart()
.table_str.trim()
aswrite_generated_file()
is already emitting newlines around it.gather_stats.ts
: Generate TypeScript tables insrc
.'use strict';
.DailyRow
properties can benull
, whenshould_emit_data_point()
detects that a line has fallen to 0.index.html
: Import modules withes-module-shims
.src_gather/gather_stats.ts
.tsconfig.json
.compilerOptions
totsconfig.universal.json
.src_gather/tsconfig.json
is forgather_stats.ts
in that directory.src/tsconfig.json
is forstatus_chart.ts
in that directory and adds thenoEmit
option, becauseesbuild
will perform codegen aftertsc
performs type checking."moduleResolution": "node"
, the modern strategy.gather_stats.ts
still wants"module": "CommonJS"
(although it could be upgraded in the future).status_chart.ts
wants"module": "ES2020"
(technically, this option doesn't matter becauseesbuild
performs codegen, but I thought it would be confusing to omit).tsconfig.json
in the project root. (In particular, this powers VSCode squiggles, so compiler errors will be accurately diagnosed taking into account our strict settings.)package.json
: Add "gather", "make", "view" scripts..github/workflows/compile-typescript.yml
.gather_stats.ts
, we need to pass--noEmit
because we want only type checking, not codegen.status_chart.ts
, it's already configured with"noEmit": true
.README.md
: Update instructions.gh-pages
is the default, but can be customized now. (The instructions don't attempt to cover such customization.)token-formats
link for readability.importmap
(used in the browser) should be kept in sync with thenode_modules
updated bynpm update
/npm install
(and used when compiling TypeScript).npm run gather
is the new way to compile and rungather_stats.ts
.npm run make
andnpm run view
scripts.built/status_chart.mjs
.📈 Live Preview: stephantlavavej.github.io/STL/
Tested in Edge, Chrome, and mobile Safari (this is significant because
importmap
s are supported by only Chromium at this time, soes-module-shims
magic is required for other browsers). I see no visual differences compared to the state before this PR, except for the new data points and PR Age rescaling.