css-tokens.js 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. "use strict";
  2. /**
  3. * @license
  4. * Copyright Google LLC All Rights Reserved.
  5. *
  6. * Use of this source code is governed by an MIT-style license that can be
  7. * found in the LICENSE file at https://angular.dev/license
  8. */
  9. Object.defineProperty(exports, "__esModule", { value: true });
  10. exports.CssTokensMigration = void 0;
  11. const ts = require("typescript");
  12. const migration_1 = require("../../update-tool/migration");
  13. const literal_1 = require("../typescript/literal");
  14. const upgrade_data_1 = require("../upgrade-data");
  15. /** Characters that can be part of a valid token name. */
  16. const TOKEN_CHARACTER = /[-_a-z0-9]/i;
  17. /**
  18. * Migration that walks through every string literal, template and stylesheet in
  19. * order to migrate outdated CSS tokens to their new name.
  20. */
  21. class CssTokensMigration extends migration_1.Migration {
  22. constructor() {
  23. super(...arguments);
  24. /** Change data that upgrades to the specified target version. */
  25. this.data = (0, upgrade_data_1.getVersionUpgradeData)(this, 'cssTokens');
  26. // Only enable the migration rule if there is upgrade data.
  27. this.enabled = this.data.length !== 0;
  28. }
  29. visitNode(node) {
  30. if (ts.isStringLiteralLike(node)) {
  31. this._visitStringLiteralLike(node);
  32. }
  33. }
  34. visitTemplate(template) {
  35. this.data.forEach(data => {
  36. if (data.replaceIn && !data.replaceIn.html) {
  37. return;
  38. }
  39. (0, literal_1.findAllSubstringIndices)(template.content, data.replace)
  40. .map(offset => template.start + offset)
  41. // Filter out matches that are followed by a valid token character, so that we don't match
  42. // partial token names.
  43. .filter(start => !TOKEN_CHARACTER.test(template.content[start + data.replace.length] || ''))
  44. .forEach(start => this._replaceSelector(template.filePath, start, data));
  45. });
  46. }
  47. visitStylesheet(stylesheet) {
  48. this.data.forEach(data => {
  49. if (data.replaceIn && !data.replaceIn.stylesheet) {
  50. return;
  51. }
  52. (0, literal_1.findAllSubstringIndices)(stylesheet.content, data.replace)
  53. .map(offset => stylesheet.start + offset)
  54. // Filter out matches that are followed by a valid token character, so that we don't match
  55. // partial token names.
  56. .filter(start => !TOKEN_CHARACTER.test(stylesheet.content[start + data.replace.length] || ''))
  57. .forEach(start => this._replaceSelector(stylesheet.filePath, start, data));
  58. });
  59. }
  60. _visitStringLiteralLike(node) {
  61. const textContent = node.getText();
  62. const filePath = this.fileSystem.resolve(node.getSourceFile().fileName);
  63. this.data.forEach(data => {
  64. if (data.replaceIn && !data.replaceIn.tsStringLiterals) {
  65. return;
  66. }
  67. (0, literal_1.findAllSubstringIndices)(textContent, data.replace)
  68. .map(offset => node.getStart() + offset)
  69. // Filter out matches that are followed by a valid token character, so that we don't match
  70. // partial token names.
  71. .filter(start => !TOKEN_CHARACTER.test(textContent[start + data.replace.length] || ''))
  72. .forEach(start => this._replaceSelector(filePath, start, data));
  73. });
  74. }
  75. _replaceSelector(filePath, start, data) {
  76. this.fileSystem
  77. .edit(filePath)
  78. .remove(start, data.replace.length)
  79. .insertRight(start, data.replaceWith);
  80. }
  81. }
  82. exports.CssTokensMigration = CssTokensMigration;
  83. //# sourceMappingURL=css-tokens.js.map