--- name: webui-lit-migration description: >- Guide for migrating Chromium WebUI components from Polymer to Lit. Activate this skill if the user asks to migrate a file or component to Lit. --- # Chromium WebUI Lit Migration ## Step 1: Run scripts/run_codemod_script.sh IMPORTANT: Always do this first, as it automates trivial migration steps. Run the script in this skill's scripts directory. Pass the path to the Polymer based element's TS class definition file as the parameter. Example: ./webui-lit-migration/scripts/run_codemod_script.sh \ chrome/browser/resources/certificate_manager/certificate_entry.ts ## Step 2: .ts file cleanup 1. Replace PolymerElement import The script replaces this import except in cases where multiple things are imported from Polymer. If an import from polymer_bundled.min.js is still present after running the script, remove it and add: import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; 1. Update 'extends PolymerElement' The script will update this in the case that no mixins are used. If there is still a reference to PolymerElement: replace SomeMixin(PolymerElement) with SomeMixinLit(CrLitElement) 1. Address any "TODO: Port this observer to Lit" comments left by the migration script as follows: a. Examine the observer (e.g. 'onFooChanged\_') method. If it does not reference the DOM, add the following in a willUpdate callback. If it does reference the DOM (e.g., this.shadowRoot or this.$), add this in a updated() lifecycle callback instead. ```ts if (changedProperties.has('foo')) { this.onFooChanged_(); } ``` ``` b. If the property being observed is protected or private, the changedProperties lifecycle method parameter will require a cast: ``` ```ts const changedPrivateProperties = changedProperties as Map; if (changedPrivateProperties.has('myProperty_')) { ... } ``` ``` c. Remove the added TODO and the commented out observer line. ``` 4. Address any complex observers in a similar way. Look for an "observers: " line: ```ts observers: ['onFooOrBarChanged_(foo, bar)'] ``` Remove the line and for each observer listed, add to a lifecycle method as described for single property observers, but check changedProperties for any of the properties listed in the observer: ``` if (changedProperties.has('foo') || changedProperties.has('bar')) { this.onFooOrBarChanged_(); } ``` 5. Move value initialization out of 'properties' to the declaration. Replace ``` foo: { type: String, value: 'foo', }, ... value: string; ``` with ``` foo: { type: String, }, ... accessor value: string = 'foo'; ``` For uninitialized properties, if a TS compiler error is thrown on build, initialize to a dummy or default value rather than using a non-null assertion operator or changing the type definition. ## Step 3: Check for any missing shared CSS styles. If any imported style file does not exist, check if the Polymer version (same file path, but without \_lit suffix) exists. If so, generate the Lit version as follows: 1. **Create Lit Version**: Create `[shared_style]_style_lit.css`. 1. **Copy Content**: Copy the CSS rules to the new `*_lit.css` file. 1. **Update Metadata**: Use `#type=style-lit` in the metadata. Update any imported and included styles to the lit version (e.g. cr_shared_style.css.js import --> cr_shared_style_lit.css.js import, include="cr-shared-style" becomes include="cr-shared-style-lit"). 1. **Empty Original**: Clear the original `*_style.css` file, leaving only its\] metadata header and a comment: ```css /* Purposefully empty since this style is generated at build time from the * equivalent Lit version. */ ``` 1. **Import in Component**: Component CSS should import the new `*_lit.css.js` and include it. 1. **BUILD.gn**: Add the new `*_lit.css` to `css_files`. ## Step 4: Update .html.ts template file 1. Replace any