esupgrade 2025.14.3 → 2025.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/agents/superjoe.agent.md +66 -0
  3. package/.github/copilot-instructions.md +11 -1
  4. package/.github/workflows/ci.yml +1 -1
  5. package/.pre-commit-config.yaml +11 -0
  6. package/AGENTS.md +33 -0
  7. package/CONTRIBUTING.md +4 -0
  8. package/README.md +202 -0
  9. package/bin/esupgrade.js +18 -17
  10. package/eslint.config.cjs +12 -0
  11. package/package.json +3 -4
  12. package/src/index.js +40 -13
  13. package/src/jQuery/HTMLInputElement.json +389 -0
  14. package/src/jQuery/addClassToClassList.js +49 -0
  15. package/src/jQuery/afterToAfter.js +54 -0
  16. package/src/jQuery/appendToAppend.js +55 -0
  17. package/src/jQuery/attrToGetSetRemove.js +52 -0
  18. package/src/jQuery/beforeToBefore.js +47 -0
  19. package/src/jQuery/childrenToChildrenArray.js +48 -0
  20. package/src/jQuery/clickToAddEventListener.js +52 -0
  21. package/src/jQuery/closestToClosest.js +43 -0
  22. package/src/jQuery/cssToStyleAndComputed.js +120 -0
  23. package/src/jQuery/eachToForOf.js +92 -0
  24. package/src/jQuery/emptyToReplaceChildren.js +33 -0
  25. package/src/jQuery/findToQuerySelectorAll.js +57 -0
  26. package/src/jQuery/hasClassToClassListContains.js +36 -0
  27. package/src/jQuery/htmlToInnerHTML.js +61 -0
  28. package/src/jQuery/idSelectorToGetElementById.js +54 -0
  29. package/src/jQuery/inArrayToIncludes.js +77 -0
  30. package/src/jQuery/nextToNextElementSibling.js +79 -0
  31. package/src/jQuery/offToRemoveEventListener.js +36 -0
  32. package/src/jQuery/onToAddEventListener.js +51 -0
  33. package/src/jQuery/parentToParentElement.js +60 -0
  34. package/src/jQuery/prependToPrepend.js +54 -0
  35. package/src/jQuery/prevToPreviousElementSibling.js +77 -0
  36. package/src/jQuery/propToDirectProperty.js +175 -0
  37. package/src/jQuery/readyToDOMContentLoaded.js +79 -0
  38. package/src/jQuery/removeClassToClassList.js +45 -0
  39. package/src/jQuery/removeToRemove.js +49 -0
  40. package/src/jQuery/selectorToQuerySelectorAll.js +68 -0
  41. package/src/jQuery/showHideToStyleDisplay.js +56 -0
  42. package/src/jQuery/siblingsToSiblingsArray.js +71 -0
  43. package/src/jQuery/staticEachToForEach.js +42 -0
  44. package/src/jQuery/staticGrepToFilter.js +36 -0
  45. package/src/jQuery/staticMapToMap.js +33 -0
  46. package/src/jQuery/textToTextContent.js +49 -0
  47. package/src/jQuery/toggleClassToClassList.js +36 -0
  48. package/src/jQuery/triggerToDispatchEvent.js +65 -0
  49. package/src/jQuery/trimToStringTrim.js +30 -0
  50. package/src/jQuery/unwrapJQueryIdentifier.js +51 -0
  51. package/src/jQuery/utils.js +384 -0
  52. package/src/jQuery/valToValue.js +40 -0
  53. package/src/jQuery/widthHeightToClient.js +49 -0
  54. package/src/jQuery.js +46 -0
  55. package/src/types.js +51 -0
  56. package/src/widelyAvailable/arrayFilterToFind.js +80 -0
  57. package/src/widelyAvailable/mathPowToExponentiation.js +29 -1
  58. package/src/widelyAvailable.js +1 -0
  59. package/src/worker.js +2 -2
  60. package/tests/cli.test.js +62 -0
  61. package/tests/general.test.js +16 -0
  62. package/tests/jQuery/addClassToClassList.test.js +34 -0
  63. package/tests/jQuery/afterToAfter.test.js +38 -0
  64. package/tests/jQuery/appendToAppend.test.js +44 -0
  65. package/tests/jQuery/attrToGetSetRemove.test.js +44 -0
  66. package/tests/jQuery/beforeToBefore.test.js +44 -0
  67. package/tests/jQuery/childrenToChildrenArray.test.js +32 -0
  68. package/tests/jQuery/clickToAddEventListener.test.js +44 -0
  69. package/tests/jQuery/closestToClosest.test.js +38 -0
  70. package/tests/jQuery/cssToStyleAndComputed.test.js +71 -0
  71. package/tests/jQuery/eachToForOf.test.js +57 -0
  72. package/tests/jQuery/emptyToReplaceChildren.test.js +26 -0
  73. package/tests/jQuery/findToQuerySelectorAll.test.js +47 -0
  74. package/tests/jQuery/hasClassToClassListContains.test.js +41 -0
  75. package/tests/jQuery/htmlToInnerHTML.test.js +38 -0
  76. package/tests/jQuery/idSelectorToGetElementById.test.js +31 -0
  77. package/tests/jQuery/inArrayToIncludes.test.js +69 -0
  78. package/tests/jQuery/nextToNextElementSibling.test.js +37 -0
  79. package/tests/jQuery/offToRemoveEventListener.test.js +43 -0
  80. package/tests/jQuery/onToAddEventListener.test.js +41 -0
  81. package/tests/jQuery/parentToParentElement.test.js +34 -0
  82. package/tests/jQuery/prependToPrepend.test.js +32 -0
  83. package/tests/jQuery/prevToPreviousElementSibling.test.js +37 -0
  84. package/tests/jQuery/propToDirectProperty.test.js +65 -0
  85. package/tests/jQuery/readyToDOMContentLoaded.test.js +40 -0
  86. package/tests/jQuery/removeClassToClassList.test.js +47 -0
  87. package/tests/jQuery/removeToRemove.test.js +26 -0
  88. package/tests/jQuery/selectorToQuerySelectorAll.test.js +36 -0
  89. package/tests/jQuery/showHideToStyleDisplay.test.js +38 -0
  90. package/tests/jQuery/siblingsToSiblingsArray.test.js +32 -0
  91. package/tests/jQuery/staticEachToForEach.test.js +80 -0
  92. package/tests/jQuery/staticGrepToFilter.test.js +50 -0
  93. package/tests/jQuery/staticMapToMap.test.js +56 -0
  94. package/tests/jQuery/textToTextContent.test.js +38 -0
  95. package/tests/jQuery/toggleClassToClassList.test.js +38 -0
  96. package/tests/jQuery/triggerToDispatchEvent.test.js +45 -0
  97. package/tests/jQuery/trimToStringTrim.test.js +32 -0
  98. package/tests/jQuery/unwrapJQueryIdentifier.test.js +26 -0
  99. package/tests/jQuery/utils.test.js +283 -0
  100. package/tests/jQuery/valToValue.test.js +38 -0
  101. package/tests/jQuery/widthHeightToClient.test.js +38 -0
  102. package/tests/types.test.js +1 -5
  103. package/tests/widelyAvailable/array-filter-to-find.test.js +173 -0
  104. package/tests/widelyAvailable/math-pow-to-exponentiation.test.js +21 -2
  105. package/tests/widelyAvailable/string-concat-to-template.test.js +1 -1
  106. package/tests/widelyAvailable/substr-to-slice.test.js +4 -1
package/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ package-lock.json linguist-generated
2
+ src/jQuery/HTMLInputElement.json linguist-generated
@@ -0,0 +1,66 @@
1
+ ---
2
+ # For format details, see: https://gh.io/customagents/config
3
+
4
+ name: SuperJoe
5
+ description: CodingJoe's digital clone following his coding guidelines and best practices.
6
+ ---
7
+
8
+
9
+ # SuperJoe
10
+
11
+ ## Planning
12
+
13
+ You MUST ALWAYS follow the `naming-things` guidelines. Use the following command to access the guidelines:
14
+ ```console
15
+ curl -sSL https://raw.githubusercontent.com/codingjoe/naming-things/refs/heads/main/README.md | cat
16
+ ```
17
+
18
+ You MUST ALWAYS read the `CONTRIBUTING.md` file before planning or writing any code.
19
+ You MUST ALWAYS search the documentation and amend or update it as necessary.
20
+ You MUST ALWAYS check for pre-commit hooks and run them before committing code.
21
+ You MUST ALWAYS ensure that all new code is fully tested with 100% coverage. Unreachable code branches MUST be removed.
22
+
23
+ ## Writing Code
24
+
25
+ Less code is more! Use the latest language features and libraries to achieve more with less code.
26
+
27
+ Do not add new dependencies, but if you do, they must be widely adopted and well-maintained in the open-source community.
28
+
29
+ You are a strong FOSS advocate with a preference for permissive licenses like BSD or MIT.
30
+
31
+ Use generators instead of adding items to lists or arrays.
32
+
33
+ Use class syntax for all object-oriented code.
34
+ Use named functions instead of anonymous functions whenever possible.
35
+ Avoid overly complex functions. Break them into smaller functions if necessary.
36
+ Docstrings should be written in present tense imperative mood.
37
+ They must start with a capital letter and end with a period.
38
+ Docstrings must describe the external behavior of the function, class, or method.
39
+ Docstrings should avoid redundant phrases like "This function" or "This method".
40
+ Class docstrings must not repeat the class name or start with a verb since they don't do anything themselves.
41
+ Avoid code comments unless they describe behavior of 3rd party code or complex algorithms.
42
+ Avoid loops in favor of recursive functions or generator functions.
43
+ Avoid functions or other code inside functions.
44
+ Avoid if-statements in favor of switch/match-statements or polymorphism.
45
+ Do not assign names to objects which are returned in the next line.
46
+
47
+
48
+ ## Python
49
+
50
+ Follow PEP 8 guidelines for code style.
51
+ EAFP (Easier to Ask Forgiveness than Permission) is preferred over LBYL (Look Before You Leap).
52
+ Use type hints for all public functions, classes, and methods.
53
+ Use dataclasses for simple data structures.
54
+ Use context managers for resource management.
55
+ Use list/set/dict comprehensions instead of loops for creating collections.
56
+ Use generators for large data sets to save memory.
57
+ Use the walrus operator (`:=`) for inline assignments when it improves readability.
58
+
59
+ ### JavaScript
60
+
61
+ Use `#` for private methods.
62
+ Write docstrings with jsdoc type annotations for all functions, classes, and methods.
63
+
64
+ ### TypeScript
65
+
66
+ Use `#` for private methods.
@@ -1,9 +1,15 @@
1
1
  When writing code, you MUST ALWAYS follow the [naming guidelines](https://raw.githubusercontent.com/codingjoe/naming-things/refs/heads/main/README.md).
2
2
 
3
+ Usage:
4
+
5
+ ```console
6
+ curl -sL https://raw.githubusercontent.com/codingjoe/naming-things/refs/heads/main/README.md
7
+ ```
8
+
3
9
  All code must be fully tested with a 100% coverage. Unreachable code must be removed.
4
10
  Follow the [CONTRIBUTING.md](./CONTRIBUTING.md) guidelines for testing and linting.
5
11
  The test suite will fail if the line coverage is below 100%.
6
- The test coverage will be written to stdout or the `lcov.info` file in the project root.
12
+ The test coverage will be written to stdout when running the tests via `npm test | grep -v '100.00'`.
7
13
 
8
14
  All transformers must be documented in the README.md.
9
15
 
@@ -20,3 +26,7 @@ Docstrings must describe the external behavior of the function, class, or method
20
26
  Docstrings should avoid redundant phrases like "This function" or "This method".
21
27
  Class docstrings must not repeat the class name or start with a verb since they don't do anything themselves.
22
28
  Avoid code comments unless they describe behavior of 3rd party code or complex algorithms.
29
+ Avoid loops in favor of recursive functions or generator functions.
30
+ Avoid functions or other code inside functions.
31
+ Avoid if-statements in favor of switch-statements or polymorphism.
32
+ Do not assign names to objects which are returned in the next line.
@@ -28,7 +28,7 @@ jobs:
28
28
  node-version-file: package.json
29
29
  - run: npm ci
30
30
  - run: node --test --experimental-test-coverage --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=lcov.info
31
- - uses: codecov/codecov-action@v5
31
+ - uses: codecov/codecov-action@v6
32
32
  with:
33
33
  token: ${{ secrets.CODECOV_TOKEN }}
34
34
  flags: javascript
@@ -21,6 +21,7 @@ repos:
21
21
  - mdformat-footnote
22
22
  - mdformat-gfm
23
23
  - mdformat-gfm-alerts
24
+ exclude: '.github/agents/'
24
25
  - repo: https://github.com/google/yamlfmt
25
26
  rev: v0.21.0
26
27
  hooks:
@@ -30,6 +31,16 @@ repos:
30
31
  hooks:
31
32
  - id: write-good
32
33
  args: [--no-passive]
34
+ - repo: https://github.com/pre-commit/mirrors-eslint
35
+ rev: v10.3.0
36
+ hooks:
37
+ - id: eslint
38
+ args: ["--fix"]
39
+ require_serial: true
40
+ additional_dependencies:
41
+ - "@eslint/js@9.39.2"
42
+ - "eslint@9.39.2"
43
+ - "globals@17.0.0"
33
44
  - repo: local
34
45
  hooks:
35
46
  - id: esupgrade
package/AGENTS.md ADDED
@@ -0,0 +1,33 @@
1
+ # esupgrade
2
+
3
+ The package includes transformers for upgrading JavaScript syntax.
4
+
5
+ ## Categories
6
+
7
+ - [Widely Available](./src/widelyAvailable/): Transformers for features available in all major browsers for at least 30 months.
8
+ - [Newly Available](./src/newlyAvailable/): Transformers for features available in all major browsers for 0-30 months.
9
+
10
+ For a full list of transformations, see [README.md](./README.md).
11
+
12
+ ## Package Structure
13
+
14
+ - [bin/](./bin/): Command-line interface script.
15
+ - [src/](./src/): Source code and transformers.
16
+ - [tests/](./tests/): Test suite.
17
+
18
+ For contributing guidelines, see [CONTRIBUTING.md](./CONTRIBUTING.md).
19
+
20
+ ## Instructions
21
+
22
+ Use EOF syntax to run node scripts directly from the command line. For example:
23
+
24
+ ```bash
25
+ node --input-type=module <<'EOF'
26
+ import { transform } from './src/index.js';
27
+
28
+ const sample = "const v = $(input).val();";
29
+ const res = transform(sample);
30
+ console.log('modified:', res.modified);
31
+ console.log('code:\n' + res.code);
32
+ EOF
33
+ ```
package/CONTRIBUTING.md CHANGED
@@ -20,3 +20,7 @@ Or instead run the linters once with:
20
20
  ```console
21
21
  uvx pre-commit run --all-files
22
22
  ```
23
+
24
+ ## Naming conversions
25
+
26
+ When writing code, please follow the [naming guidelines](https://raw.githubusercontent.com/codingjoe/naming-things/refs/heads/main/README.md).
package/README.md CHANGED
@@ -15,6 +15,12 @@ Keeping your JavaScript and TypeScript code up to date with full browser compati
15
15
  esupgrade is safe and meant to be used automatically on your codebase.
16
16
  We recommend integrating it into your development workflow using [pre-commit].
17
17
 
18
+ To try it out on a repository without writing changes, run:
19
+
20
+ ```bash
21
+ npx esupgrade $(git ls-files | grep -E -i -w '.*\.(t|j)sx?')
22
+ ```
23
+
18
24
  ### pre-commit
19
25
 
20
26
  ```bash
@@ -218,6 +224,17 @@ Supports:
218
224
  +const clone = [...Array.from(items)];
219
225
  ```
220
226
 
227
+ #### `Array.filter()[0]` → [`Array.find()`][mdn-find]
228
+
229
+ ```diff
230
+ -const first = [1, 2, 3].filter(n => n > 1)[0];
231
+ +const first = [1, 2, 3].find(n => n > 1);
232
+ ```
233
+
234
+ Transforms `filter(predicate)[0]` to the more explicit and performant `find(predicate)`, which stops at the first match instead of filtering the entire array.
235
+
236
+ Transformations are limited to when the receiver can be verified as an array (array literals, `new Array()`, or known array method chains) and `filter()` is called with exactly one argument.
237
+
221
238
  #### `Math.pow()` → [Exponentiation operator \*\*][mdn-exponentiation]
222
239
 
223
240
  ```diff
@@ -565,6 +582,189 @@ These transformations are mainly to harden code for future releases and should b
565
582
  +});
566
583
  ```
567
584
 
585
+ <picture>
586
+ <source media="(prefers-color-scheme: dark)" srcset="https://jquery.com/wp-content/themes/jquery/images/logo-jquery@2x.png">
587
+ <source media="(prefers-color-scheme: light)" srcset="https://upload.wikimedia.org/wikipedia/commons/f/fd/JQuery-Logo.svg">
588
+ <img alt="jQuery logo" src="https://upload.wikimedia.org/wikipedia/commons/f/fd/JQuery-Logo.svg" height="32" align="right">
589
+ </picture>
590
+
591
+ ## jQuery
592
+
593
+ esupgrade can transform common [jQuery] patterns to modern, standards-based DOM APIs via the `--jQuery` argument.
594
+ For further reading, we recommend: [You Might Not Need jQuery](https://youmightnotneedjquery.com/).
595
+
596
+ ```bash
597
+ npx esupgrade --jQuery <files>
598
+ ```
599
+
600
+ > [!WARNING]
601
+ > jQuery transformers are experimental and may produce unsafe code in complex scenarios.
602
+ > Review all changes before applying them to your codebase.
603
+
604
+ ### Selection
605
+
606
+ #### `$(selector)` → `document.querySelectorAll()` / `document.getElementById()`
607
+
608
+ ```diff
609
+ -$('.foo')
610
+ - $('#bar')
611
+ +document.querySelectorAll('.foo')
612
+ +document.getElementById('bar')
613
+ ```
614
+
615
+ Skipped when jQuery chaining is present (e.g. `$('.x').css(...).addClass(...)`).
616
+
617
+ ### Class and Attributes
618
+
619
+ #### Class helpers
620
+
621
+ ```diff
622
+ -$(el).addClass('a b');
623
+ -$(el).removeClass('a');
624
+ -$(el).toggleClass('x');
625
+ -$(el).hasClass('x');
626
+ +el.classList.add('a', 'b');
627
+ +el.classList.remove('a');
628
+ +el.classList.toggle('x');
629
+ +el.classList.contains('x');
630
+ ```
631
+
632
+ #### Attribute helpers
633
+
634
+ ```diff
635
+ -$(el).attr('data');
636
+ -$(el).attr('data', v);
637
+ -$(el).removeAttr('disabled');
638
+ +el.getAttribute('data');
639
+ +el.setAttribute('data', v);
640
+ +el.removeAttribute('disabled');
641
+ ```
642
+
643
+ ### Content and Value
644
+
645
+ #### Text and HTML accessors
646
+
647
+ ```diff
648
+ -const text = $(el).text();
649
+ -$(el).text('new text');
650
+ -const html = $(el).html();
651
+ -$(el).html('<b>bold</b>');
652
+ +const text = el.textContent;
653
+ +el.textContent = 'new text';
654
+ +const html = el.innerHTML;
655
+ +el.innerHTML = '<b>bold</b>';
656
+ ```
657
+
658
+ #### Value accessors
659
+
660
+ ```diff
661
+ -const val = $(el).val();
662
+ -$(el).val('new value');
663
+ +const val = el.value;
664
+ +el.value = 'new value';
665
+ ```
666
+
667
+ ### DOM Manipulation
668
+
669
+ #### Insertion and Removal
670
+
671
+ ```diff
672
+ -$(parent).append(child);
673
+ -$(parent).prepend(child);
674
+ -$(el).before(node);
675
+ -$(el).after(node);
676
+ -$(el).remove();
677
+ -$(el).empty();
678
+ +parent.append(child);
679
+ +parent.prepend(child);
680
+ +el.before(node);
681
+ +el.after(node);
682
+ +el.remove();
683
+ +el.replaceChildren();
684
+ ```
685
+
686
+ ### Events
687
+
688
+ #### Event Listeners
689
+
690
+ ```diff
691
+ -$(el).on('click', handler);
692
+ -$(el).off('click', handler);
693
+ -$(el).click(handler);
694
+ +el.addEventListener('click', handler);
695
+ +el.removeEventListener('click', handler);
696
+ +el.addEventListener('click', handler);
697
+ ```
698
+
699
+ #### Dispatching and Ready
700
+
701
+ ```diff
702
+ -$(el).trigger('custom');
703
+ -$(document).ready(fn);
704
+ +el.dispatchEvent(new CustomEvent('custom'));
705
+ +document.addEventListener('DOMContentLoaded', fn);
706
+ ```
707
+
708
+ ### Traversal
709
+
710
+ #### Traversal helpers
711
+
712
+ ```diff
713
+ -$(el).find('.sel');
714
+ -$(el).parent();
715
+ -$(el).closest('.sel');
716
+ -$(el).next();
717
+ -$(el).prev();
718
+ -$(el).children();
719
+ -$(el).siblings();
720
+ +el.querySelectorAll('.sel');
721
+ +el.parentElement;
722
+ +el.closest('.sel');
723
+ +el.nextElementSibling;
724
+ +el.previousElementSibling;
725
+ +Array.from(el.children);
726
+ +Array.from(el.parentElement.children).filter(c => c !== el);
727
+ ```
728
+
729
+ ### Style and Sizing
730
+
731
+ #### CSS and Display
732
+
733
+ ```diff
734
+ -$(el).css('color');
735
+ -$(el).css('color', 'red');
736
+ -$(el).show();
737
+ -$(el).hide();
738
+ +getComputedStyle(el).color;
739
+ +el.style.color = 'red';
740
+ +el.style.display = '';
741
+ +el.style.display = 'none';
742
+ ```
743
+
744
+ #### Dimensions
745
+
746
+ ```diff
747
+ -$(el).width();
748
+ -$(el).height();
749
+ +el.clientWidth;
750
+ +el.clientHeight;
751
+ ```
752
+
753
+ ### Static Utilities
754
+
755
+ #### Collection and String utilities
756
+
757
+ ```diff
758
+ -$.each(array, fn);
759
+ -$.map(array, fn);
760
+ -$.inArray(val, array) !== -1;
761
+ -$.trim(str);
762
+ +array.forEach(fn);
763
+ +array.map(fn);
764
+ +array.includes(val);
765
+ +str.trim();
766
+ ```
767
+
568
768
  ## Versioning
569
769
 
570
770
  esupgrade uses the [calver] `YYYY.MINOR.PATCH` versioning scheme.
@@ -587,6 +787,7 @@ Furthermore, esupgrade supports JavaScript, TypeScript, and more, while lebab is
587
787
  [baseline]: https://web.dev/baseline/
588
788
  [calver]: https://calver.org/
589
789
  [django-upgrade]: https://github.com/adamchainz/django-upgrade
790
+ [jquery]: https://jquery.com/
590
791
  [mdn-arrow-functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
591
792
  [mdn-async-await]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
592
793
  [mdn-classes]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
@@ -595,6 +796,7 @@ Furthermore, esupgrade supports JavaScript, TypeScript, and more, while lebab is
595
796
  [mdn-default-parameters]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
596
797
  [mdn-endswith]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
597
798
  [mdn-exponentiation]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Exponentiation
799
+ [mdn-find]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
598
800
  [mdn-for-of]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
599
801
  [mdn-functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
600
802
  [mdn-globalthis]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
package/bin/esupgrade.js CHANGED
@@ -30,11 +30,12 @@ class WorkerRunner {
30
30
  * Run a worker thread to process a file.
31
31
  * @param {string} filePath - Path to the file to process.
32
32
  * @param {string} baseline - Baseline level for transformations.
33
+ * @param {boolean} jQuery - Whether to include jQuery transformers.
33
34
  * @returns {Promise<Object>} Worker message result.
34
35
  */
35
- async run(filePath, baseline) {
36
+ async run(filePath, baseline, jQuery) {
36
37
  const worker = new Worker(this.workerPath, {
37
- workerData: { filePath, baseline },
38
+ workerData: { filePath, baseline, jQuery },
38
39
  })
39
40
 
40
41
  const [message] = await once(worker, "message")
@@ -57,6 +58,7 @@ class FileProcessor {
57
58
  * @param {string} options.baseline - Baseline level for transformations.
58
59
  * @param {boolean} options.check - Whether to only check for changes.
59
60
  * @param {boolean} options.write - Whether to write changes to file.
61
+ * @param {boolean} options.jQuery - Whether to include jQuery transformers.
60
62
  * @returns {Promise<{modified: boolean, error: boolean}>} Result of processing.
61
63
  */
62
64
  async processFile(filePath, options) {
@@ -73,7 +75,11 @@ class FileProcessor {
73
75
  }
74
76
 
75
77
  try {
76
- const workerResult = await this.workerRunner.run(filePath, options.baseline)
78
+ const workerResult = await this.workerRunner.run(
79
+ filePath,
80
+ options.baseline,
81
+ options.jQuery,
82
+ )
77
83
 
78
84
  if (!workerResult.success) {
79
85
  console.error(`\x1b[31m✗\x1b[0m Error: ${filePath}: ${workerResult.error}`)
@@ -193,6 +199,7 @@ class CLIRunner {
193
199
  async run(patterns, options) {
194
200
  console.time("Processing")
195
201
  // Hand CLI-provided names directly to the worker pool; file validation occurs in processFile.
202
+ // Pass jQuery to worker pool
196
203
  const results = await this.workerPool.processFiles(patterns, options)
197
204
  console.timeEnd("Processing")
198
205
 
@@ -259,21 +266,15 @@ program
259
266
  .choices(["widely-available", "newly-available"])
260
267
  .default("widely-available"),
261
268
  )
262
- .option("--check", "Report which files need upgrading and exit with code 1 if any do")
263
- .option("--write", "Write changes to files")
269
+ .option(
270
+ "--check",
271
+ "Report which files need upgrading and exit with code 1 if any do",
272
+ false,
273
+ )
274
+ .option("--write", "Write changes to files", false)
275
+ .option("--jquery, --jQuery", "Enable jQuery specific transformers", false)
264
276
  .action(async (files, options) => {
265
- // Handle check/write options - they are not mutually exclusive
266
- // Default: write is false (read-only mode unless --write is specified)
267
- const shouldWrite = options.write || false
268
- const shouldCheck = options.check || false
269
-
270
- const processingOptions = {
271
- baseline: options.baseline,
272
- write: shouldWrite,
273
- check: shouldCheck,
274
- }
275
-
276
- await cliRunner.run(files, processingOptions)
277
+ await cliRunner.run(files, options)
277
278
  })
278
279
 
279
280
  program.parse()
@@ -0,0 +1,12 @@
1
+ const js = require("@eslint/js")
2
+ const globals = require("globals")
3
+ const defineConfig = require("eslint/config").defineConfig
4
+
5
+ module.exports = defineConfig([
6
+ {
7
+ files: ["**/*.{js,mjs,cjs}"],
8
+ plugins: { js },
9
+ extends: ["js/recommended"],
10
+ languageOptions: { globals: globals.node },
11
+ },
12
+ ])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esupgrade",
3
- "version": "2025.14.3",
3
+ "version": "2025.16.0",
4
4
  "description": "Auto-upgrade your JavaScript syntax",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -8,7 +8,7 @@
8
8
  "esupgrade": "./bin/esupgrade.js"
9
9
  },
10
10
  "scripts": {
11
- "test": "node --test --experimental-test-coverage --test-coverage-lines=100 --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=lcov.info --test-coverage-exclude=tests/**/* tests/*.test.js tests/**/*.test.js"
11
+ "test": "node --test --experimental-test-coverage --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=lcov.info --test-coverage-exclude=tests/**/* tests/*.test.js tests/**/*.test.js"
12
12
  },
13
13
  "keywords": [
14
14
  "javascript",
@@ -36,6 +36,5 @@
36
36
  "repository": {
37
37
  "type": "git",
38
38
  "url": "https://github.com/codingjoe/esupgrade.git"
39
- },
40
- "devDependencies": {}
39
+ }
41
40
  }
package/src/index.js CHANGED
@@ -1,6 +1,13 @@
1
1
  import jscodeshift from "jscodeshift"
2
2
  import * as newlyAvailable from "./newlyAvailable.js"
3
3
  import * as widelyAvailable from "./widelyAvailable.js"
4
+ import * as jQueryTransformers from "./jQuery.js"
5
+
6
+ /**
7
+ * Transformer function type.
8
+ *
9
+ * @typedef {function(import('jscodeshift').Collection): boolean} Transformer
10
+ */
4
11
 
5
12
  /**
6
13
  * Result of a transformation.
@@ -10,32 +17,52 @@ import * as widelyAvailable from "./widelyAvailable.js"
10
17
  * @property {boolean} modified - Whether the code was modified
11
18
  */
12
19
 
20
+ /**
21
+ * Apply transformers to code recursively until no changes occur.
22
+ *
23
+ * @param {string} code - The source code to transform.
24
+ * @param {import('jscodeshift').JSCodeshift} j - jscodeshift instance.
25
+ * @param {Transformer[]} transformers - Transformer functions.
26
+ * @param {boolean} globalModified - Whether any modifications have occurred.
27
+ * @returns {TransformResult} Object with transformed code and modification status.
28
+ */
29
+ function applyTransformersRecursively(code, j, transformers, globalModified = false) {
30
+ const root = j(code)
31
+ let passModified = false
32
+
33
+ for (const transformer of transformers) {
34
+ passModified = transformer(root) || passModified
35
+ }
36
+
37
+ if (passModified) {
38
+ return applyTransformersRecursively(root.toSource(), j, transformers, passModified)
39
+ }
40
+
41
+ return {
42
+ code,
43
+ modified: globalModified,
44
+ }
45
+ }
46
+
13
47
  /**
14
48
  * Transform JavaScript code using the specified transformers.
15
49
  *
16
50
  * @param {string} code - The source code to transform.
17
51
  * @param {string} baseline - Baseline level ('widely-available' or 'newly-available').
52
+ * @param {boolean} jQuery - Whether to include jQuery transformers.
18
53
  * @returns {TransformResult} Object with transformed code and modification status.
19
54
  */
20
- export function transform(code, baseline = "widely-available") {
55
+ export function transform(code, baseline = "widely-available", jQuery) {
21
56
  const j = jscodeshift.withParser("tsx")
22
- const root = j(code)
23
-
24
- let modified = false
25
57
 
26
- const transformers =
58
+ let transformers =
27
59
  baseline === "newly-available"
28
60
  ? { ...widelyAvailable, ...newlyAvailable }
29
61
  : widelyAvailable
30
62
 
31
- for (const transformer of Object.values(transformers)) {
32
- if (transformer(root)) {
33
- modified = true
34
- }
63
+ if (jQuery) {
64
+ transformers = { ...transformers, ...jQueryTransformers }
35
65
  }
36
66
 
37
- return {
38
- code: root.toSource(),
39
- modified,
40
- }
67
+ return applyTransformersRecursively(code, j, Object.values(transformers))
41
68
  }