Skip to content

Conversation

@codingjoe
Copy link
Contributor

@codingjoe codingjoe commented Dec 29, 2025

https://fosstodon.org/@codingjoe/115803674715881666
@pauloxnet like this?

  • Add esupgrade to pre-commit hooks
  • pre-commit CI applies safe changes
  • small unrelated changes, co-pilot discovered
  • set explicit console log level (debug)

Copy link
Contributor Author

@codingjoe codingjoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that was interesting. I still found some edge cases that need handling. And I'll work on class transformation.

@codingjoe codingjoe marked this pull request as ready for review December 29, 2025 22:45
Copilot AI review requested due to automatic review settings December 29, 2025 22:45
@codingjoe
Copy link
Contributor Author

Ok, there is some name shadowing happening in one file that threw me off. I reviewed all changes again, and they all appear correct.

If anyone thinks this is helpful, go ahead. Otherwise, just close the PR. I am happy to have tested such a history-rich code base. 😉

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds the esupgrade pre-commit hook to automatically modernize JavaScript code, converting ES5 syntax to modern ES6+ patterns. The changes include converting var to const/let, traditional functions to arrow functions, string concatenation to template literals, and forEach loops to for...of loops.

  • Adds esupgrade pre-commit hook configuration with exclusion for library files
  • Modernizes JavaScript across 11 files with ES6+ syntax updates
  • Updates variable declarations, function expressions, and string interpolation patterns

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
.pre-commit-config.yaml Adds esupgrade hook at version 2025.3.4 with library exclusions
djangoproject/static/js/mod/switch-dark-mode.js Converts var to let, arrow functions, and template literals
djangoproject/static/js/mod/stripe-donation.js Updates to const/let, arrow functions, and modern syntax
djangoproject/static/js/mod/stripe-change-card.js Converts to ES6+ with const declarations and arrow functions
djangoproject/static/js/mod/list-collapsing.js Modernizes with const, arrow functions, and cleaner syntax
djangoproject/static/js/main.js Updates function and variable declarations to ES6+
djangoproject/static/js/fundraising-heart.js Converts IIFE and functions to arrow syntax with const/let
djangoproject/static/js/djangoproject.js Replaces forEach with for...of loops and arrow functions
djangoproject/static/js/dashboard/utils.js Updates to const/let and template literals
djangoproject/static/js/dashboard/index.js Modernizes with const and arrow functions
djangoproject/static/js/dashboard/detail.js Converts to ES6+ patterns with proper scoping
djangoproject/static/js/admin_blog_imageupload.js Updates to for...of loops and arrow functions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codingjoe
Copy link
Contributor Author

Those co-pilot comments are all legit too.

@pauloxnet
Copy link
Member

@pauloxnet like this?

Thanks for the PR

I'll ask @adamzap and other @django/django-website to review it and share their feedback

@codingjoe
Copy link
Contributor Author

OK, let me address the co-pilot changes too in a separate commit.

@ulgens
Copy link
Member

ulgens commented Dec 30, 2025

Not a blocker, but I'd recommend limiting this PR to hook change and linter-related safe (automatic) / unsafe (manual) changes. Copilot is doing a poor job of understanding the scope of a PR and it makes many unrelated comments.

Also, I'll recommend installing the hooks locally via prek install so pre-commit.ci won't create those fix commits.

Apart from these two points, LGTM.

@codingjoe
Copy link
Contributor Author

I tried keeping all commits neatly separate. I can split the manual changes into a separate PR if that makes reviewing them easier.

@ulgens
Copy link
Member

ulgens commented Dec 30, 2025

I can split the manual changes into a separate PR if that makes reviewing them easier.

I don't think they make an important difference for the review; it would be a small improvement for the git history. (It was a nitpick 🌻 )

@codingjoe codingjoe force-pushed the main branch 2 times, most recently from 8762e85 to d694899 Compare January 5, 2026 10:24
@codingjoe
Copy link
Contributor Author

@ulgens I kept the upgrade commit separate to add it to .git-blame-ignore-revs once the commit is on main. So that I am to "blame" for adding esupgrade, but not its changes…

But I can squash them. Whatever works for you. I upgrade the commit to include the latest changes on main. I also upgrade esupgrade to 2025.8

@ulgens
Copy link
Member

ulgens commented Jan 5, 2026

@codingjoe Oh okay, that makes sense. We generally see these fix commits from pre-commit.ci when people forget to install hooks locally; I thought it was the case here.

I was about to recommend keeping the commit separate for the reason you shared, but creating the commit yourself and explanining the "blame ignore revs" in commit message, but I see that you already squashed. This was a nitpick to start with, I'm okay with both options.

@ulgens ulgens self-requested a review January 5, 2026 10:45
@pauloxnet
Copy link
Member

@codingjoe thanks for taking care of this PR

Do we have a way to measure performance or feature regression eventually connected with this big PR?

I would really like to read an opinion from @adamzap or @sarahboyce about this PR before approve it

@ulgens
Copy link
Member

ulgens commented Jan 5, 2026

measure performance or feature regression

Could you elaborate on that? I don't see how this PR would affect performance.

@pauloxnet
Copy link
Member

measure performance or feature regression

Could you elaborate on that? I don't see how this PR would affect performance.

Since the PR is quite big, do we have a way compare performance before and after applying the code changes? It would be something interesting to have to prove that a modern Javascript means also better performance or at least to prove that the new code is as fast as before.

@ulgens
Copy link
Member

ulgens commented Jan 5, 2026

I see. I personally don't expect any performance improvements from a lint/styling PR, but I also see your point. Do you consider not having that data as a blocker for this PR?

@adamzap
Copy link
Member

adamzap commented Jan 6, 2026

I think I'd like to go with whatever the WG thinks is best here. I intentionally don't write the most "modern" JavaScript, so it modified some of my code. Regardless, I think a lot of manual testing will need to happen if this is to be merged. Has that been done?

Either way, this is good motivation for me to finish removing jQuery! 😉

@pauloxnet
Copy link
Member

... I intentionally don't write the most "modern" JavaScript, so it modified some of my code.

What's your motivation to avoid some modern JavaScript code?
Do you think some rules need to be reverted here?

Regardless, I think a lot of manual testing will need to happen if this is to be merged. Has that been done?

That's a good point. I think we can write a list of things to be tested manually.

Either way, this is good motivation for me to finish removing jQuery!

This is a good side effect 😀

@codingjoe
Copy link
Contributor Author

codingjoe commented Jan 6, 2026

performance 🔥

Look what I read early on HN: https://waspdev.com/articles/2026-01-01/javascript-for-of-loops-are-actually-fast
Lucky coincidence. TL;DR, maybe a slight uplift, but nothing to crazy.

old-school JS 🧓

All changes are baseline "widely available" and thus have been supported by all browsers for over 30 months. The Baseline project was established to update with confidence.

esupgrade has two modes: this is the "boring" one. 😉

"If you don't touch it, you can't break it." – True, but I already had to rebase twice. So the code is being touched. And the more Pythonic modern syntax will hopefully prevent future errors.

manual testing 🧪

Yes, I have done that to the best of my ability. Yet, I am fairly new to this project, sooo I don't mind a second set of eyes.


Lastly, as mentioned in the DSF-member Discord, I am still looking for members to form a JS work group. 🚀

Copy link
Member

@adamzap adamzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions...

show: function (x, y, message) {
$(() => {
const element = $('#graph');
const url = `${element.data('path') + element.data('metric')}.json?days=365`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be nicer and more consistent as:

`${element.data('path')}${element.data('metric')}.json?days=365`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this transformation isn't automated by esupgrade, since we don't know that element.data doesn't return an integer (where addition would work differently).

unit
);
const format_message = (timestamp, measurement) => {
const unit = measurement == 1 ? response.unit : response.unit_plural;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ===? Maybe that's out of scope here...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are numerous places with incorrect equality checks. This is a case for ESLint.

);
const format_message = (timestamp, measurement) => {
const unit = measurement == 1 ? response.unit : response.unit_plural;
return `${formatTimestamp(timestamp, response.period)}<br>${measurement} ${unit}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to enforce a maximum line length? These files make me think it was 80 previously.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm… yes, more recent versions of esupgrade keep multiline concatenation.
I think this should probably be set up in a linter/formatter (which esupgrade is not).


var url = element.data('path') + element.data('metric') + '.json';
$.getJSON(url, function (response) {
const url = `${element.data('path') + element.data('metric')}.json`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as above.

var pos = $(hash).position();
$(window).scrollTop(pos.top);
const pos = $(hash).position();
$(globalThis).scrollTop(pos.top);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is using globalThis a best practice for web-only code? We don't need to support any other JavaScript environments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the only global context variable that is supported across all environments. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility

success: function (data) {
console.log(data);
success: (data) => {
console.debug(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it bad practice to use console.log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not deprecated if you mean that. However, many new features don't deprecate the old ones. Like the new loops.
In this particular case, log is missing the verbosity level. Browsers, Sentry, and Node.js handle different levels differently.
What you are losing with log is the clear intent. Does that explanation make somewhat sense to you? There is obviously some opinions baked into esupgrade.

document.cookie = `${cname}=${cvalue}; ${sameSiteAttribute} ${expires}; path=/;`;
}

function getCookie(cname) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagging this for deeper review.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is a tricky one. I did test it manually, to be sure.
I could set up a Node.js test suite to write unit tests for JavaScript code too. Maybe in a separate PR ;)

@@ -1,45 +1,41 @@
// Toggle persistent display of documentation version and language options
document.querySelectorAll('.doc-switcher li.current').forEach(function (el) {
for (const el of document.querySelectorAll('.doc-switcher li.current')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a for loop better here for some reason, or are we just conforming to a certain style?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As previously mentioned. There is nothing wrong with it. However, the new features of ECMAScript have a history of why their proposal was drafted and included in an ES release.

In other words, yes, there are opinions baked into the esupgrade, including my own. But since I come from a Python background, I'd presume some might be welcome here.

- id: django-upgrade
args: [--target-version, "6.0"]

- repo: https://github.com/codingjoe/esupgrade
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No offense, @codingjoe, but I'm not sure if a project like Django's website should be relying on a project with seven GitHub stars. During review I assumed that esupgrade was a well-known code formatting tool. I'm curious to hear what other members of the working group think though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully support the goal and the intention of this PR, but I agree that the tool not being widely-accepted yet is a bit concerning. I don't have a strong opinion, but I'd recommend selecting something more established (if there is any) or waiting a bit to see how esupgrade progresses.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None taken; this was inspired by a conversation on Mastodon and meant as a testing ground to harden esupgrade.

I can understand hesitance to introduce this tool to the dev toolchain, and I don't mind either way.

However, I reviewed all automatic changes and, of course, my own in the latter commits.
So if those changes find appreciation, I am happy to make this a one-time thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from the tool's maturity, +1 for merging useful changes from the PR.

@codingjoe
Copy link
Contributor Author

@ulgens @adamzap thanks for your reviews! I updated everything and split the pre-commit config change into a separate commit. So you could go ahead and just cherry-pick the latter commits.

There are numerous blunders in the JS code, none of which are caused by this transformation. I set up ESLint locally… and oh boy… I'd love to fix it, but in a separate PR. Let's get things out of the door in baby steps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants