-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Status Chart: Mega TypeScript overhaul, PR/CI checks, libcxx change #2588
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
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 hidden or 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
Member
Author
|
Note: conflicts in |
CaseyCarter
approved these changes
Mar 17, 2022
ab1b671 to
4b43594
Compare
Member
Author
|
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'.
Fixes error TS2531: Object is possibly 'null'. (We know that they always exist.) Fixes error TS2339: Property 'disabled' does not exist on type 'HTMLElement'. (We know that they're always buttons.)
Fixes error TS2531: Object is possibly 'null'. (We know that they always exist.)
Fixes: error TS7006: Parameter 'chart' implicitly has an 'any' type. error TS7006: Parameter 'idx' implicitly has an 'any' type. Using `typeof status_chart` instead of `Chart` avoids: error 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.
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.
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
tscto perform type checking, followed byesbuildto bundle the Status Chart's main script with the daily/weekly/monthly tables. (That bundled output is checked into thegh-pagesbranch 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.tsandstatus_chart.tswill 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
mainbecause 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.tsChangesstatus_chart.jstosrc/status_chart.ts.strictsupersedes'use strict';.chartjs-adapter-date-fnstochartjs-adapter-luxon, asluxonis smaller when unbundled, and we've alreadynpm installed it.status_chartetc. 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'.spanasHTMLSpanElement.error TS2531: Object is possibly 'null'.getElementByIdAs()for safety.Errors (viewable in the console) if the elements don't exist or have the wrong type, which would happen ifindex.htmlisn't kept in sync with the script.legend_click_handler().error TS7006: Parameter '_event' implicitly has an 'any' type.(etc.)Timeframetype.error TS7006: Parameter 'timeframe' implicitly has an 'any' type.update_chart_timeframe().error TS7006: Parameter 'chart' implicitly has an 'any' type.(etc.)typeof status_chartinstead ofChartavoidserror 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.constassertions 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.hiddenasboolean.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 constinmerge_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.onloadwithload_charts().status_chart.jswas executed immediately, so we could setwindow.onloadand it would take effect later.max/stepSize.🛠️ Other Changes
npm install [dependencies]@latestnpm install chart.js chartjs-adapter-luxon esbuild http-serverspanGapsnot recognized inoptions.elements.linechartjs/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.mjswill be checked in.src/weekly_table.ts: Move, manually change to TypeScript.'use strict';.WeeklyRowtype, wherecxx17,cxx20, andlwgare optional (as we stopped recording them here when the GitHub era began).weekly_table, with a type ofWeeklyRow[].gather_stats.ts: Simplifymonthly_tableprinting.daily_tableused the same technique. Thedaily_tablestopped 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.tsis 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';.DailyRowproperties 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.compilerOptionstotsconfig.universal.json.src_gather/tsconfig.jsonis forgather_stats.tsin that directory.src/tsconfig.jsonis forstatus_chart.tsin that directory and adds thenoEmitoption, becauseesbuildwill perform codegen aftertscperforms type checking."moduleResolution": "node", the modern strategy.gather_stats.tsstill wants"module": "CommonJS"(although it could be upgraded in the future).status_chart.tswants"module": "ES2020"(technically, this option doesn't matter becauseesbuildperforms codegen, but I thought it would be confusing to omit).tsconfig.jsonin 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--noEmitbecause we want only type checking, not codegen.status_chart.ts, it's already configured with"noEmit": true.README.md: Update instructions.gh-pagesis the default, but can be customized now. (The instructions don't attempt to cover such customization.)token-formatslink for readability.importmap(used in the browser) should be kept in sync with thenode_modulesupdated bynpm update/npm install(and used when compiling TypeScript).npm run gatheris the new way to compile and rungather_stats.ts.npm run makeandnpm run viewscripts.built/status_chart.mjs.📈 Live Preview: stephantlavavej.github.io/STL/
Tested in Edge, Chrome, and mobile Safari (this is significant because
importmaps are supported by only Chromium at this time, soes-module-shimsmagic 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.