Xplat docs xplat json snippet support and refactor and automated docs testing - #497
Open
gmurray81 wants to merge 80 commits into
Open
Xplat docs xplat json snippet support and refactor and automated docs testing#497gmurray81 wants to merge 80 commits into
gmurray81 wants to merge 80 commits into
Conversation
…ration A ```json-snippet block holds one sample as JSON and becomes this platform's markup as the page is generated, replacing the four or five hand written blocks a topic otherwise carries for the same sample. Purely additive: every other block is left exactly as it was, so a topic can hold both forms and a platform specific snippet with no JSON equivalent keeps working. Verified by generating every platform against the unmodified repo — the platforms whose blocks were not collapsed come out byte identical. The emitter is the locally built renderer, loaded through a CommonJS bundle and only when a page actually contains a json-snippet, so pages without one are untouched. A failure fails the build rather than publishing a page with a hole where a sample should be. Collapses one section of bullet-graph as the first case: three PlatformBlocks and 76 lines become one 22 line block, and Angular, React and Web Components each come out matching what was there before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collapsing a per-platform snippet group into one JSON definition forces a single
answer. Where the platforms already agree that is mechanical; where they differ,
the difference is almost certainly a mistake that has to be fixed first, because
collapsing would otherwise silently pick a winner and change what some platform's
page has always shown.
Compares content rather than dialect: element names, attribute names, quoting and
layout all differ legitimately between platforms, so all of these read the same
and report nothing —
<igx-bullet-graph minimumValue="5"> <IgrBulletGraph minimumValue={5}>
<igc-bullet-graph minimum-value="5"> <IgbBulletGraph MinimumValue="5">
It reports when one of them says 55 and the others say 5.
Two things had to be got right before the output meant anything. Only elements
carrying a platform prefix count, so a topic wrapping a sample in a <div> and
XAML's property elements do not shift everything after them. And a group ends
when a platform repeats, not only when prose intervenes: not every sample carries
a block for every platform, and without that a group missing one swallows the
next sample's first block. That alone took the false "different component"
reports from 534 to 86.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…riance
The generator now states the style a documentation snippet is written in — one
line of attributes, no invented element names, and no dimensions on the XAML
platforms — so a sample only says what is particular to it.
The divergence check now sets aside the differences that are expected rather than
wrong:
* dimensions, which are presentation and now handled by a style option
* property renames, taken from the vendored apiMap rather than a hand kept
list, so ItemsSource and dataSource are recognised as one property
* binding syntax, so {Binding SalesData}, this.state.salesData and SalesData
are recognised as naming the same thing
* an absence explained by binding, where the platforms that do write the
property are binding and another binds in code instead
* colours and numbers, which the topics pick freely as illustration
What is left is content that says something: a field, a data type, an icon, a
class. 747 differences over 246 groups, down from 2008 over 455 when everything
was reported.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Lining elements up by position made one legitimate difference throw off every
comparison after it. A platform carries an element the others do not — XAML
declares the axes a CategoryChart infers, Angular groups columns in a layout —
and everything past that point was reported as different when only one thing was.
That was what "is a different component" and a bare "element count" were: 169
reports that said nothing usable.
Comparing per component instead says what is actually wrong, and where:
how many column: Angular: 0, Blazor: 6, WebComponents: 6, React: 9
column 2 datatype: Blazor: string, React: number
Also splits a platform showing none of a component from the platforms that show
it and disagree about how many. The first is a topic illustrating a feature with
a smaller piece of the sample, which is deliberate; the second is a real
disagreement.
Two further corrections to what the apiMap was doing. A rename was applied
globally, so one type renaming IconName to `name` turned every name attribute in
the docs into an icon — a rename is now ignored when the platform's name is
itself a canonical name elsewhere, or maps to more than one. And the plumbing
attributes are recognised on the name as written, before a rename can disguise
them. Razor's @salesdata now reads as the binding it is.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The product names a web-only description WebGridDescription, WebColumnDescription, WebDatePickerDescription, while a component shared with the XAML platforms has no such prefix — DataGridDescription, BulletGraphDescription. The presence of a Web<Name>Description in the apiMap is therefore the product's own statement that a component is web only, and those are out of scope: collapsing a group into one definition pays where the definition serves every platform, and a web-only component has no XAML counterpart to reconcile against. That takes the field from 710 groups to 153, and the topics to reconcile from 116 to 49. Renames are also looked up per component now rather than globally, since a rename belongs to a type: ItemsSource is written dataSource on some types while DataSource is a property in its own right on others. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The apiMap cannot answer what a XAML attribute is called canonically: its files are generated per transpile target and XAML is the canonical side, so there is nothing there to map from. The description metadata records every platform's name for a property in one entry, and is the only thing that knows dataSource and ItemsSource are one property. The check now asks it, through the snippet emitter it already depends on. A data source is a special case worth stating: the description carries both DataSource and DataSourceRef — the value and a reference to a named one — and a topic writes whichever suits it, XAML almost always the reference and a sample configuring an inline source the value. They are one concept for comparing, so the Ref is folded in. Two things this needed. The metadata is keyed by the description's own casing while a doc tag arrives lowercased, and a web-only description is also reachable by its bare name since <igc-grid> canonicalises to "grid" rather than "webgrid". And a PlatformBlock gates on groups as well as platforms — "Xaml" is not a platform the metadata knows — so the block's audience is resolved to a member of its group. With that, the 25 reports of datagrid's data source splitting into two properties become 14 real ones. The apiMap is still what says a description is Web-prefixed, which is what scopes the check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… peers Decides whether a group can become a json-snippet referencing its sample, by reading each platform's block back into the properties it states, resolving those to their description names, and comparing each with the sample's value. A group that is a subset of its sample can be collapsed mechanically: the sample is provably the source, so the block becomes a reference plus the properties it illustrates, and the topic stops being able to drift from what it shows. A group that is not a subset needs a person, and the tool prints every platform's version so the call is made from what the topic actually says. Three things had to be right before the answer meant anything. A sample writes its properties camel cased while a description names them Pascal cased, so lookups go through a lower cased index. Web Components writes them spinal cased, so the dashes come out before asking the metadata. And a sample sitting between two blocks starts a new section — the topics write some platforms, then the sample, then the rest — which without handling pairs a group with the wrong sample and makes every property look like a disagreement. Current reading: 4 collapsible, 56 needing a decision, 138 with no peered sample. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A platform stating the sample's own values settles that the sample is the scenario the section is about. The others have drifted from it, so the group collapses to the sample and they come back into line — bullet-graph's measures section has React and Web Components on the sample's numbers while Blazor is on an entirely different set and Xaml on a third. Pairing decides which sample a group belongs to, and direction turned out to be the wrong axis: a topic's opening sample sits above its first snippet while a section further down writes the snippets and shows the sample under them. Both orders occur, so pairing uses the enclosing heading section instead — a section is about one thing, including its sample. A section with more than one sample is left unpaired rather than guessed at. --plan prints what each collapse changes, per platform, so the editorial consequence is visible before anything is rewritten. 13 groups collapse on this rule, 14 have no platform agreeing with their sample and need a decision, 171 have no sample in their section. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Splits the unpaired count into its causes: no sample in the section, more than one, or a sample whose file is not in the examples checkout. The last is the one that matters — it is not a property of the docs but of which branch of the examples repo is being read, and the counts move with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… say Three pairing rules were wrong before this one. Nearest by distance pairs a group with the previous section's sample. Looking only backwards, or only forwards, each mispairs about half, because a topic's opening sample sits above its first snippet while a section further down shows the sample under them. Sectioning by heading rejects pairings that are plainly related: of the blocks with a sample within a screen's distance, more than half have a heading in between. What actually separates one sample from another is another snippet group, so a group owns everything between the group before it and the group after. That took paired groups from 27 to 62. Where position cannot decide, content can: a sample of the same component that covers the properties a platform states is likely the one being illustrated. Matched on which properties are set rather than their values, since values are exactly what has drifted — a topic states value=70 beside a sample running value=80, so matching on values finds nothing. Also adds the fallback to igniteui-wc-examples: a sample missing from the examples repo but present there is not missing, it is not yet back ported. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Many snippets appear to be written from scratch rather than narrowed from a sample: for one gauge topic, twenty samples of that component existed and none set even the same properties, let alone the same values. So requiring agreement finds nothing, and the useful question is which sample best covers what the snippet sets, preferring one the topic already shows. That takes content matches from 3 to 26 and paired groups to 88 of 198. Reported separately from positional pairing because the quality differs. It gets the obvious ones right — geo-map-binding-data-csv to the csv sample — and pairs some confidently wrong: a topic about binding multiple sources matches the csv sample, because with values excluded the two set the same properties. A wrong pairing is worse than none when the purpose is to re-anchor a snippet to the sample's values, so these want confirming rather than applying. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t the schema The topic carried five hand-written blocks per section saying the same thing in five spellings, and they had drifted apart. Nine sections become nine JSON definitions, 1374 lines become 418, and en and jp are collapsed together. Every XAML block in the topic turned out to have been written from the hero animation sample rather than each section's own, in all six sections that have one. The XAML in these topics has never been compiled or run, so where it disagreed with the web platforms the web platforms won. SNIPPET-COLLAPSE-DECISIONS.md records that and the three sections that did not collapse trivially. Generation now emits the JSON schema and checks every json-snippet against the description it names before writing any output, reporting all the problems at once rather than failing on the first property the renderer happens to reach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The topics write isScaleInverted={false}, not "false". Matches how React's numbers were
already handled.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…hows chart-annotations displays three data-chart samples while every one of its snippets is a CategoryChart, and the CategoryChart annotation samples it was written from are never mentioned on the page. Pairing on the embedded <Sample> reported it as needing samples back-ported from another repo when the JSON was already in this one. Indexes every sample by the property names it sets, compared without each platform's spelling, and ranks by how much of the snippet a sample covers. Across the 125 DV snippet groups, 42 have a sample covering at least 80% of what they set, and 29 of those name a sample the page never shows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…n from Every snippet on the page is a CategoryChart while the three samples it embeds are DataCharts. The CategoryChart annotation samples the snippets came from are never mentioned on the page, which is why this topic first looked like it needed samples back-ported from another repo. The XAML binding to TemperatureAnnotatedData gives it away — that is annotations-custom's own dataSourceRef. Two of the three callout member paths named fields that do not exist in the data. Taken from the running sample. The XAML callout snippet sat after the Timeline Styling section rather than with the callout markup it duplicates; folded in. en and jp collapsed together. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The emitter was dropping enum collections on every platform but XAML, so the property the Callout Layer section describes appeared in no snippet. Now that it emits, it is in the JSON. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…y tool radial-gauge goes from 1497 lines to 467, ten sections becoming ten JSON definitions in en and jp together. Same cause as bullet-graph: every XAML block carried the hero animation sample's values rather than its own section's. The candidate matcher now prefers a sample of the same component. The gauges share most of their property names, so a radial gauge section about ranges matched the linear gauge's and the bullet graph's ranges samples at 100% on properties alone; only the element being shown says which component the reader is looking at. mirror-collapse-to-jp.mjs replaces the ad hoc scripts. It walks both copies as ordered sequences of snippet positions rather than matching fences to groups, which misaligns as soon as one group in a topic is left hand written — as Dependencies is here — and it refuses to write at all when the counts disagree, since two copies that have drifted need a person. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1448 lines to 413, nine sections in en and jp together. Six matched their own sample outright; the three that did not are recorded in SNIPPET-COLLAPSE-DECISIONS.md. Every XAML block again carried the hero sample's values rather than its section's — NeedleShape="Needle" where every web platform says Custom, #79797a where they say DodgerBlue. Third topic in a row, and the same cause each time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… need code Both topics carried a bare map plus, for every platform, a code block constructing the imagery and assigning it to backgroundContent. backgroundContent is an ordinary described property whose value is another description, so each becomes one JSON with the imagery nested, and the generated markup needs no code at all. check-snippet-code-channels.mjs is what makes that claim checkable rather than hopeful. Some properties cannot be written as an attribute on some platforms — a data source on Web Components is assigned in script — and a topic showing only markup would then tell the reader to bind a source without saying where it comes from. The renderer already decides what it cannot write as an attribute, so the check asks it: 2 of 32 collapsed snippets set something in code, both Web Components in chart-annotations, and both still have a companion code block beside them. The mirror tool now aligns on heading sections rather than snippet positions, since a collapse often replaces several groups with one JSON, which the positional match refused outright. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…dropped something Some properties cannot be written as an attribute on some platforms — a data source or a tooltip template on Web Components is assigned in script — and a topic showing only the markup leaves that platform's reader with a series bound to nothing. The emitter is what decided to leave it out, so it is what says a code block is needed: if anything was dropped it appears, and if nothing was, nothing appears. Angular binds in the template and gets no block; Web Components gets its two assignments. What that block shows is the assignments alone, which is what 149 of the 192 code blocks in the hand written topics show. The 36 that also show how the reference was obtained and the 27 that declare a field are the introductory pages: code="allCode" gets that fuller form, and code="none" turns it off for a topic that would rather write its own. A ref= fence can still name a channel explicitly. geo-map-type-scatter-symbol-series is the first topic collapsed this way: eight hand written blocks become one definition, and the generated shape matches the original per platform — one block for Blazor and XAML, two for Web Components. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bubble series, polygon series, polyline series and the shapefile binding page: 37 hand written blocks become four definitions, en and jp together. The shape data sources nest declaratively, so the shapefile and database URLs are in the markup where the topics used to assign them in code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ode blocks
Creating Series and Map Background collapse; the shapefile loading and per-record processing
sections stay, since they are handlers rather than configuration.
The collapse found a typo the hand written markup had carried: Web Components wrote
shape-memberPath where the attribute is shape-member-path, so that property had been doing
nothing.
Two faults in the mirror, both found by the Map Background section:
- it grouped only markup fences, so a section whose blocks are all ts was not seen and the
snippet was inserted after the blocks it should have replaced, leaving the page with
both. Seven earlier mirrors had silently left the Japanese copy holding code blocks the
English one had dropped; those are re-mirrored here from the pre-collapse originals.
- replacing every group in a collapsed section would have taken the hand written Web
Components block chart-annotations deliberately keeps. A block the English copy still has
is now left alone, recognised by its body, since only the prose is translated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Data aggregations matched its sample outright. Its initialGroups and initialSummaries now read Country and Sum(Sales) as Sales, from the sample, where the page wrote them lowercase; the sample is what runs against the data. The overlay text section had Web Components and XAML declaring a DataAnnotationSliceLayer and Blazor building the same thing in a method with three styling properties the other two did not show. Collapsed to the union, so every platform now shows the border thickness, border radius and padding that only Blazor had. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… was missing The XAML block under Chart Marker Size was the wrong snippet: the section is about MarkerSize on a ScatterLineSeries and XAML showed a LineSeries chart with callout, final value and crosshair layers and no marker size at all. Collapsed to what the three web platforms agree on and the prose describes, so XAML now demonstrates the property the section is named after. The web blocks referred to axes they never declared; the definition declares them. The reset example uses null, which is how the description API spells NaN. The Japanese copy was missing the Chart Checkmark Marker Type section entirely, which is why the mirror refused to run on this topic. Translated and added, so the two copies have the same structure again. The translation is mine and has not been through localisation review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The window coordinate section offers two forms of the same thing — a windowRect, or the three positional properties — so it becomes two snippets with the page's own "or" between them, which is what it already said. Geographic Coordinates is left alone: it calls zoomToGeographic, and a description says what a thing is rather than what to call on it. The library has MapNavigationOnViewInit holding exactly that call, so this wants the handler channel rather than hand written code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t out The Geographic Coordinates section showed a zoomToGeographic call, and the library already holds exactly that call as MapNavigationOnViewInit. The snippet names the handler and the build emits its body, per platform: a Rect literal on Blazor, a constructor on XAML, an object on the web. The new missing library item check earned itself immediately — it caught a dangling tooltipTemplateRef the multiple shapes collapse had introduced, pointing at that page's own ng-template rather than anything in the library, which would have emitted a reference to nothing. The mirror now refreshes a snippet that is already collapsed on both sides but has since changed in English, which is how that stale reference would otherwise have survived in the Japanese copy. Two snippets under one heading still cannot be placed automatically, but they no longer block refreshing a section that has nothing left to place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CSV binding, JSON points binding and high density series pages each build their series in
a routine the library already holds — MapBindingDataCsvOnViewInit and the other two — so the
topics name the handler and the build writes it out per platform. 24 hand written blocks
become three definitions and three handler references.
Two faults in the mirror, both surfaced by these being the first topics with two snippets
under one heading:
- it placed one snippet per section, so the second was silently dropped. A section is now
replaced whole, with its snippets in the order English has them, which also removes the
need to work out which snippet replaced which group.
- its fence pattern required a body, and a ref fence has none, so those were invisible to
it entirely.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e with it A few sections show two components side by side because the point is the comparison — an ordinal axis on a FinancialChart and on a DataChart, markers off on a CategoryChart and on a DataChart's LineSeries — and neither is a child of the other. A snippet body that is a JSON array emits them in order, one blank line between, which is what the hand written block did. This is the case that justified the form; nothing else in the set needed it. The two guideline sections showed property assignments on a chart the reader already has and now show the properties on the components, which is how the rest of the documentation states them and what the comments in the original were already describing. It does change what those sections demonstrate, and SNIPPET-COLLAPSE-DECISIONS.md says so, along with the two faults it corrects: this.Chart.Resolution with a capital R on the platforms where that is not the property, and the Blazor block setting it twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ling The two guideline sections show a property being set on a chart the reader already has. That is the lesson, so they are emitted as code rather than markup: asking for a component's code channel now forces code behind, which is what that work was for. All five platforms show the assignment again rather than a declaration. Also stops two styling differences that the style options exist precisely to prevent: selfCloseEmptyElements was set for React alone, though the topics close an empty element on its own tag in Blazor and XAML as well. An enum qualification option was added and then removed: the docs write MarkerType.Circle 315 times and the bare form never, so the emitter was already right and the one unqualified block in chart-markers was an error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Spreadsheet has no description type — not among the 1190 the schema is generated from, and there are no spreadsheet sample JSONs in the examples repository at all. The renderer has nothing to emit from, so this is a limit of what is described rather than a view about the pages, and they become collapsible the day the component is described. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each page was a class listing kept by hand beside the copy in the library that the samples compile, and the two had drifted: the TypeScript had renamed members and lost methods, the C# had a different shape for WorldConnections and some leftover console writes. One fence per page emits the class the library holds, for the four web platforms the pages are gated to, so the listing is the code that runs. The platform blocks go with them — a fence emits each platform's own language already — and the util page's C# gains the methods its TypeScript had all along.
The check asked the emitter for a composed channel as though "a...b,c" were one token. No such channel exists, so nothing came out and nothing was checked: every codeBehind fence and every Component Modules fence had been passing vacuously. It now emits each region the way the generator composes them, mirrors the generator's rule about marking a definition that marks parts of itself, and understands channel="auto". What that turned up: - The multiple sources Summary asked for code="allCode" — the attribute is channel — so it emitted markup and the page showed the same markup twice. Its imports are empty on Blazor and the XAML platforms, and there is no code behind to show on the XAML platforms at all; both fences are scoped. - The local data page's data block referenced a definition that marks nothing, so it was empty on every platform. It states its own marker. Also collapses the data grid module sections, which were the last hand written ones outside the web only pages, and the remote data source, which the library already holds. --print --platform=<name> prints what each fence emits, which is the only way to read the output of a page gated away from a platform.
The mirror adds fences but leaves what they replace, so the remote data page kept the hand written data source block and a duplicate of its markup fence. Every page's fences match between the two locales again.
The snippet tooling had absolute paths into one developer's home directory in six scripts. That works until anyone else runs them, and it cannot work in CI at all. Resolution is stated once now, in lib/snippet-toolchain.mjs, in the order a run should prefer: an environment variable, then a peer checkout, then a package. With no peer, igniteui-xplat-examples is cloned at the branch matching the branch under check — the same matching dev-tools' own builds use, because a change spanning both repositories is made on same-named branches and a check that read main would review it against the wrong samples. check-snippet-schema.mjs checks every definition on every page, in both locales, against the schema the descriptions declare. The checking itself moves to lib/snippet-schema.mjs, shared with the generator, so the two cannot disagree about what is valid. Its messages name the property, suggest the nearest real one, and list what an enumeration accepts — a misspelled enum value is the most common mistake, and "must be equal to one of the allowed values" does not say which those are. samples-runtime/ loads every sample in the examples repository into chromium with the real component renderer and the published packages, and reports anything that errors. It follows the Web Components test host's discipline, because that host loads hundreds of samples into one page without it falling over: errors collected rather than thrown, unused refs cleaned up on render, the renderer's own teardown between samples, and idle, flush and animation idle waited for in that order. The data and handlers come from the product's own library emission rather than a second implementation that reads the library folder. A failure is retried once. A sample that fails in sequence and passes on its own inherited something from the sample before it, which is a finding about the component rather than about the sample, and it is reported as its own kind. A page that stops answering is restarted, as the xsharp runner restarts a host it cannot reach, and a crash is reported with everything available at that moment: the stage it reached, what the renderer had objected to, what the page logged, the components the sample names, and what the page was holding — a dead tab cannot be revisited. The collapse notes and the WinUI/Uno plan move to dev-tools, beside the emitter they are about.
…derer The harness was loading the samples, which is the other repository's job. What this one publishes is the fences, so that is what it loads: every json-snippet in every topic, wrapped into a page, rendered by the component renderer from the published packages, with the library a fence binds to emitted by the product's own code generating renderer. Where it had drifted from the way the web test host drives the renderer, it now follows it: allowNullForRemove, isProceedOnErrorEnabled, cleanupUnusedOnRender, a member path transformer rather than asking every item to keep its casing, a null description sent for each occupied slot before cleanup, and errors read again after the teardown rather than only after the load. A page that stops answering is restarted, as the host does, and a run that would otherwise sit forever on a flush or an animation gives up and says how far it got. A fence excerpt that draws nothing is only worth reporting when it binds data: a fence that states a component and no data is what an excerpt looks like, so the pixel check now separates the two. Alongside it, check-snippet-casing reports a fence that disagrees with its sample about skipAlterDataCasing. Casing is altered in concert, so a fence emitting from a sample that skips must skip too, or its member paths are re-cased while its data is not, and nothing else notices. The examples clone now only moves onto another branch in CI. A workspace there is made fresh for the run; a directory on someone's machine was put there by them, and fetching over it discards their work without asking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…for them A snippet that excludes a platform disappears there; the heading and the sentence introducing it do not. Every exclusion in the topics was doing that: 45 fences, and not one sat inside a block that hid the prose as well, so a reader on those platforms met "the following code shows" and nothing after it. Most were standing in for a library item nobody had written, which is the thing to write rather than hide. So they are gone, bar module registration — a concept the XAML platforms do not have — and those sections are gated whole, which is what a fence excluding a platform was trying to say. Both checks now read that gating: a section a platform never sees is not that platform's to emit, and not a place it can be stranded. check-snippet-exclusions is new and states the rule: an exclusion is sound only when the section still has a snippet for that platform, or nothing there is shown to it. The emission check reports what the renderer itself could not resolve after a load, rather than what walking the JSON suggests — which cannot tell a library item from a component the definition declares. Found on the way: three topics never closed their web PlatformBlock, so the Blazor instructions nested inside a block Blazor is not in and were never shown, and two more gated a sentence but let its code block through to the platforms the sentence was hidden from. The topics themselves needed the same honesty. A property set in code is set in code everywhere it is taught, so the imagery topics say so rather than naming the web platforms alone; the shape styling resource topic asks for the handler that requires the utility instead of pinning the utility into a list of things to run; and the multiple shapes topic addresses the readers as regions of the supporting item that now holds them. Every one of the 304 fences in the topics loads clean in a browser against the published packages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The topic bound styleShape, which exists for JS alone, so the fence emitted nothing for the XAML platforms and for Blazor. It binds assigningShapeStyle now, with the flag that lets a series take a custom style at all — the library items moved to the same event, and every platform has both. With that, every fence in the topics emits on all five platforms: 763 emissions, none empty. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The emitter these checks run on is the product's own code generating renderer, and it now ships in igniteui-webcomponents-core — 7.1.1-beta.11 carries everything they use, down to the snippet information a description was given this week. So the wrapper around it lives here and is bundled against the package: no dev-tools checkout, no .NET, no token for a private repository. Three things had to change to source it from a package rather than a local build. Its imports name the package. The two places that globbed a directory for description modules — a vite feature, and this is bundled with esbuild — read the package's own export surface instead, which is better than a glob: the set follows the package rather than a folder someone might not have built. And the DOM stub answers a few more calls, because bundling the whole package brings in a lit template built as its module loads. One thing no package ships: the item templates a library item is emitted into. They are copied here, and when a dev-tools checkout is present the two are compared, so a copy that has drifted says so. A local dev-tools build still wins when there is one, so a change to the renderer can be tested before it ships; an unbuilt checkout now falls through to the published emitter with a note, rather than stopping the run. Checked with dev-tools hidden: 763 emissions across five platforms, 308 snippets valid against the schema, 102 fences agreeing with their samples about casing, no platform left with prose and no snippet, and all 304 topic snippets rendering in a browser against the beta packages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One conflict, in the cross-platform table of contents: both sides had said something different about the Avatar entry — this branch which platforms it is shown to, vnext that it was updated recently. Neither replaces the other, so it says both. The topics vnext brought are checked the same as the rest: 763 emissions across five platforms, 308 snippets valid against the schema, no platform left with prose and no snippet, and all 304 topic snippets still rendering in a browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ntime question Four checks were failing for reasons that had nothing to do with the snippets themselves: - ci and check-relative-links generate the site, which emits fences, so both need the emitter built; neither built it, and its own error message was in their logs. - The load check let vite walk up to the site's tsconfig, which extends astro/tsconfigs/strict; astro is not installed in that job. The harness now has its own tsconfig so the search stops there. - The emission check gated on the renderer's unresolved refs. Emitting code never binds a ref -- it writes a reference to a library item -- so every library-backed ref reads as unresolved and the gate said nothing. All 115 it reported are items that exist and emit. A ref that resolves to nothing at run time is a real fault, and the live harness reports it, where a value is actually expected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collapsing per-platform blocks into single fences left fences and tables flush against block tags and left runs of blank lines where the blocks had been. vnext writes a blank line there, so this is the existing convention rather than a new one, and it does not change what renders. The lint job only lints files a PR touches, so the grids/data-grid topics -- new to vnext on this branch -- are linted end to end, including two comment forms they arrived with. Closing the delimiters up, as the rest of the repository writes them, stops the linter reading the pair as emphasis. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… build runs Two faults with one cause: nothing local ran what CI runs. The emission check never exercised item=. It ignored the attribute and marked the definition its own way, so a fence naming a supporting item passed the check and then failed generation -- which is where CI met it, in two jobs. The fence's emission now lives in lib/snippet-emit.mjs and generate and the check both call it, so the check cannot pass something the build refuses. item= names a library item as well as a handler, which is how a region of a supporting item is asked for; a name matching neither is still an error. The checks take --lang and every local run had been --lang=en, so four fences that only the Japanese copies reach were never emitted here. They failed because the Japanese topics had fallen out of step: three commits had changed English topics without their counterpart. Working from those commits, the Japanese copies get the module gate the exclusion scrub added, lose the section the English collapse dropped, and gain the blocks that were split out of a snippet when it was collapsed. Both languages now report the same 763 emissions with the same 22 sections gated away, every platform generates, and all 304 fences load clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The items behind them now exist everywhere, so nothing is hidden: heat imagery's generator call reaches Blazor, and cell editing's two handlers and the sparkline cell template reach the XAML platforms. Both copies lose the gate together. 768 emissions now, against 763, with 17 sections gated rather than 22 -- the same numbers in both languages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mechanism has been learned by reading generate.mjs and asking whoever last touched it. This says it once: the fence and its attributes, the channels and the regions under them, the marker language and what a snippet captures before any marker is written, every style option the renderer reads, and the rule that decides when a platform may be shown less than the others. The validation section is the part that would have saved the most time. It says what each check proves and, more usefully, what it cannot: a schema says nothing about what comes out, emission says nothing about whether the code is right, and only the live harness runs the component. It also names the two traps this week turned up -- that the checks default to --lang=en while CI runs both, and that a built dev-tools checkout beside this repository silently takes precedence over the published emitter CI uses, so a local pass is not automatically a CI pass. Library items are the examples repository's business and are documented there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CodeQL failed the pull request on three high severity alerts, all in scripts that run by hand rather than anything the site ships. They are cheap to fix and each fix is the better code, so they are fixed rather than dismissed. Two are check-then-use on the filesystem. plan-snippet-collapse asked readdir for names and then stat'd each one to learn what it was; readdir already knows, so withFileTypes removes both the second call and the window between them. Three walkers did this and all three are converted, which leaves statSync unused. migrate-toc asked whether a toc existed and then read it; it now reads and lets a missing file say so. The third is the prose stripper in the dossier, which took tags out in one pass. "<a<script>b>" leaves "<script" behind that way -- removing the inner tag closes the outer one around what is left. It now runs until the text stops changing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The twelve collapse scripts move to the emitter spike in dev-tools, where the work they belong to lives. Nothing here referenced them: the import graph from every workflow command, every npm script and the astro config reaches eighteen files, and not one of them is a collapse tool. What stays is the build, the three checks CI runs, the three validators run by hand, and the API link scripts. scripts/README.md says which is which, and where the collapse tools went for whoever collapses the next component. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The load check has been failing in CI roughly one run in three, always with one sample "only in sequence" and never the same one: data-model after data-json-points once, data-json-points after data-csv the next. Every victim ran directly after a geo map binding sample, and those initializers fetch their data from static.infragistics.com. The three waits a load already did -- idle, flush, animation -- all say that nothing is queued. A request that has not come back yet is queued nowhere, so the harness moved on while it was still on the wire, the response landed during the next sample, and its handler reached for a map that had been torn down. The report then blamed whichever sample happened to be loading, which is why the pair changed run to run and why it never reproduced on a fast connection. fetch is counted now, and a sample that ran an initializer waits for its requests before the page is looked at. Waiting too long is a finding rather than a silent pass, on the same timeout as the other waits. 304 of 304 still load clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Auditing what a XAML reader is actually served turned up two topics that are about the web and nothing else. Grid theming is a table of CSS custom properties -- --header-background, --grid-elevation -- for a grid that has no CSS, and the data grid accessibility topic documents ARIA attributes on DOM elements, where WinUI has UI Automation. Both are dropped for now rather than patched; the accessibility one needs a UI Automation version written before it comes back. Neither was gated, and the reason is the same fault. The toc's "Theming" entry pointed at grids/theming-grid.mdx, which no longer exists in English: that topic was split into one copy per grid family and nothing was in the toc for the three real files, so every platform published them. Repointed at the Grid copy, and the other two families -- which had no theming entry at all -- get one. Its Angular exclusion is not carried across, so no web platform changes because of the href. Accessibility sits under a section that is XAML only, so it publishes nowhere until it is rewritten. Deleting one line restores it. The Japanese copy had not been split with the English one: it still held the shared grids/theming-grid.mdx that English had already broken into three. Split the same way, so both languages now publish the same three pages and the toc entries name real files on both sides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…DV ones Generation publishes any source file the toc does not exclude, so a file no toc entry names goes to all six platforms. Thirty-five did. Nothing about them was a decision. Thirteen are web grid topics. grids/grid is the web Grid family, not the XAML data grid, whose topics are the thirty-two under grids/data-grid -- all of which are listed, so nothing there is missing. What a WinUI reader was served instead was the web Grid's validation topic, telling them to use Forms validators and a template-driven configuration against a component they do not have. They are listed now beside their siblings, Web only, which is where the other ninety-odd topics in those sections already sit. Five more are data visualization topics that had never been listed anywhere, in this repository or the docfx-era one: the chart titles topic, three geographic map topics, and the Excel library's grids topic -- that last one Web only, since its siblings are. Four of the five were also linked from nothing at all, so they were published and unreachable by any route. Their names come from their own headings. Seventeen changelogs remain unlisted and are left alone: they are npm package release histories, nothing links to them, and the toc's own four changelog entries are Web only -- so the XAML platforms are offered no changelog by policy. Wiring them up is a decision, not a leak. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An audit of the pages the toc actually offers the XAML platforms found prose
written for the web and never gated. Where the topic is cross-platform the words
are fixed rather than hidden, and only genuinely web-only material is gated.
Reworded: the charts overview promised charts "for your web and mobile apps"
designed "to work on every modern browser" -- now web, mobile and desktop, and
every modern platform, which is what the product does. Nine map topics described
themselves as a "{Platform} JavaScript map", which reads as "WinUI JavaScript
map". The grids topic called itself "The Lightweight {Platform} Web Components
table". None of that needed a second version; it needed to be true.
Gated: the supported browsers list, Internet Explorer 11 and polyfills included,
and the web worker section of the heat imagery topic -- whose per-platform blocks
were gated already while the heading and its paragraph were not, so a XAML reader
was shown a section about workers and then nothing under it.
Also the one Ig$TemplateColumn in the repository, where its four siblings write
TemplateColumn, and four double spaces before an inline link.
Fifty-one findings down to six, and the six are the docs page's own FAQ script,
the acronym in "JavaScript Object Notation", the Azure and Bing key pages saying
to get a key from a website, and a platform list that names WinUI itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A canonical API name in prose now renders as the name the reader's platform uses, and a term that resolves to nothing is reported rather than shipped. That report is the point: it catches a typo, which no amount of proofreading a per-platform fork of the same sentence ever did. Every topic states an apiTerms mode, with no default, so the decision is made per document rather than inherited by accident. `full` looks names up in the maps; `passthrough` resolves by rule for a component no generator describes, still emitting an ApiLink; `none` leaves the code span alone. Resolution tries the canonical spelling first, then reverses the platform affixes, so a topic may write XamDataChart or DataChart and both arrive at the same place. Type context comes from the page: a qualified Type.Member, else the types the prose and its ApiLinks already name, else mentionedTypes. A backticked term that is deliberately not an API name is escaped with a leading backslash. An ambiguous type fold is no longer reported before the page's context has had its say. A name can be both an enum and a property -- TrendLineType is each -- and once case is folded it collides with an unrelated type from another product area. A page that named the chart it is about has already answered which is meant. Hand-exposed API gets an override, because a generator maps what it generated and a member it was told to skip is absent from the map even though the package ships it: ShapefileRecord.Points, whose web spelling comes from the hand-written wrapper rather than a guess, SeriesViewer.CheckmarkMarkerTemplate, whose whole family is suppressed on every platform at once, and TriangulationSource, which reaches the web packages by being exported rather than wrapped. Terms that exist on one platform only are scoped with a PlatformBlock instead of being offered to every reader -- the Blazor-only SetCustomizedStringAsync, and treemap's synthesized NodeStylingScript. An extension-only name that no map will ever hold stays out of a code span. Both languages move together, en as the reference. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A topic is authored once and emitted per platform now, so reading the source no longer tells you what a reader ends up with: the source is smaller than what it replaced, and the question is whether the page still says what it did. review-platform-diff.mjs generates both sides and diffs the output. Changes are separated by the judgement they need. A topic whose only difference is its apiTerms line is set aside as directive-only -- frontmatter rides through to the output, as mentionedTypes and namespace always have, so without that every topic differs and the ones that matter are buried: it was 339 of 339 for WebComponents, and is 78. Comments are counted on their own, because interleaved explanation is the one thing collapsing to a definition drops rather than corrects. A comment is only counted lost when its text appears nowhere in the new page -- emitted code is laid out differently, so a diff shows moved lines as removed and re-added, and counting those overstated the loss by a seventh. Of the 73 genuinely lost on WebComponents, most have a home already: one explaining code inside a handler belongs in that handler's source in the examples checkout, where it is emitted with the code, and an elision marker is what the ... delimiter between channel names already writes. What was left is explanation of generated code, which the renderer's own $comment sidecar places ahead of the element it describes -- restored here for the chart performance blocks, where the line saying which chart each applies to had gone missing. Also document how a backticked API name in prose becomes the reader's own spelling: the required apiTerms modes, the resolution order, how a page says which type it means, when to escape a term, and what the overrides are for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The renderer's own $comment writes a remark ahead of an element, and because elements nest, one on a series already lands mid-block. What it cannot do is annotate a single property, and that is what a hand written block used most: a line saying what the next assignment is for. The chart performance topic had one above each of four blocks saying which chart it applied to, and collapsing the blocks took it with them. $comments is keyed by property, so it cannot be confused with the per platform splay a sidecar value may itself be, and each entry lands above the line that property produced, in the platform's own comment syntax. Anchoring is by assignment rather than by mention: without that a comment on resolution lands above the line declaring the chart, because the emitted variable name contains the property name too. An entry matching nothing is reported rather than dropped, since a property renamed out from under its comment would otherwise take the explanation with it silently. Two other things a block was losing: An elision now separates a region's field declarations from the statements below them. A handler that requires a supporting item is emitted with the field holding it -- a class member -- followed by the handler's body, which is statements inside a method. Those are excerpts from two parts of a file, which is what the ... between channel names marks, but here they arrive inside one region and that delimiter has nothing to sit between. Unmarked, the block reads as one run of statements and a reader copying it puts a field declaration in the middle of a method. And a region is dedented rather than trimmed. trim() strips whitespace from the ends of the string, which is the first line's indentation and no other line's, so a method lifted out of a class emitted with its signature flush and its body still indented -- and with a doc comment above the signature, the comment went flush while the method stayed indented under it. The sidecar table said $comment was never emitted, which is backwards; it also now says where each kind of comment belongs, because a comment explaining code inside a handler belongs in that handler's source and not in a sidecar at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The hand written block a handler fence replaced opened with the imports its types needed, then an elision, then the handler. The fence emitted the handler alone, so a reader who scrolled to the section they wanted saw code using types whose imports were named somewhere further up the page. channel="handlersImports...handler" restores it, and needs nothing new: the ... delimiter already writes the elision between two regions, and a platform whose handler needs no imports drops the region and its delimiter with it. Applied to all twelve handler fences, in both languages. The field elision now looks for a field anywhere in a block's preamble rather than only at its start. With imports composed in front, the field that holds a required supporting item is no longer the first line, and the mark that separates it from the statements below stopped appearing exactly where it had just started being needed. A region of a supporting item cannot do the same. The item's file has an imports region and the renderer publishes a doc:imports key for it, but the content is empty -- the region is consumed to build the sample's import list rather than exposed. Reading the file directly is not a way round it, since Web.ts is written in the Web Components names that the renderer translates per platform, so a raw read would put Igc types on the React and Angular pages. Left as it stands and written down; it wants the renderer to fill that key in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
handlersImports beside a supporting item's region gives the requiring handler's imports -- a list for code the block does not show, missing the types the shown code casts to. Better to name the region alone than to print an import block a reader would copy and find incomplete. The renderer now writes those imports to a region of their own, supportingImports, so these three fences can compose it once a build carrying that is vendored here. Recorded in JSON-SNIPPETS.md so the next person reaching for handlersImports on a supporting item finds out why it is the wrong one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"loaded in ShapefileRecord with of countries of the world" -- the sibling sections either side of it read "with communication routes between major cities" and "with locations of major cities", so the stray "of" is all that was wrong. English only. The Japanese copy of the sentence is a translation and reads correctly already. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #
Checklist:
preview/beta./page.mdxor../relative/path.mdx(.mdxextension required)IgxSelectComponent,<igx-combo>code blocksfor the names of classes / tags / propertiescode blockscheck-api/mdxnpm commandsllms.descriptionmetadata and runnpm run check:llms-metadata