Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance, debug, and clean up scripts for CSS migration (BL-12857) #1

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

StephenMcConnel
Copy link

@StephenMcConnel StephenMcConnel commented Dec 4, 2023

This change is Reviewable

@StephenMcConnel StephenMcConnel marked this pull request as draft December 6, 2023 15:16
@StephenMcConnel StephenMcConnel force-pushed the BL-12857-ImproveCssMigrationScripts branch from 92e7652 to 66da708 Compare December 6, 2023 19:38
@StephenMcConnel StephenMcConnel marked this pull request as ready for review December 6, 2023 19:39
@StephenMcConnel StephenMcConnel force-pushed the BL-12857-ImproveCssMigrationScripts branch from 66da708 to 6908abb Compare December 6, 2023 22:17
Copy link

@JohnThomson JohnThomson 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 possible problems to think about. I've never seen the whole code, so some of them may be unhelpful.

let cssPath = `${folder}/customBookStyles.css`;
if (fs.existsSync(cssPath)) {
cssPath = `${folder}/customBookStyles2.css`;
console.log(`WARNING: multiple migrations in ${folder}`);

Choose a reason for hiding this comment

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

I'm not clear why we would not want to override earlier output...or if there really is a good reason not to, why it would be OK to overwrite every previous output except the first. (Same for appearance.json)

Copy link
Author

Choose a reason for hiding this comment

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

This handles the case where both customCollectionStyles.css and customBookStyles.css have css that need to be migrated. By the time this code runs, the original filename is lost, so I compromised by providing two different output files. The migration code erases any earlier output when it starts, so a duplicate has to happen in this run.
It's quite possible I've been overly paranoid in this instance, and the problem never arises in practice.

Copy link
Author

Choose a reason for hiding this comment

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

Now that I think about it, I think this situation never arises in the migration output folder because the migration is specific to a single file matching a specific checksum. So this code can be simplified here.

}
}
if (cssCount > 1)
console.log(`WARNING: multiple CSS files with content in ${dir}`);

Choose a reason for hiding this comment

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

That would be, customBookStyles.css and customCollectionStyles.css both have content? That's all we're downloading? Because it would be common, and not a problem, to have lots of others like basePage.css.

Copy link
Author

@StephenMcConnel StephenMcConnel Dec 7, 2023

Choose a reason for hiding this comment

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

Yes, that would be referring to customCollectionStyles.css and customBookStyles.css in the folder both having content. I've reworded the message to make that explicit. I've also decided it's not really a problem warranting a warning. It's quite reasonable for a collection to have a customized look, but for a single book in the collection to make another adjustment specific to that book.

return; // leave this rule unchanged.
}
// A rule like .marginBox { background-color: red; } is just fine.
// We preserve rules like this and add them after this loop changes the current rules.

Choose a reason for hiding this comment

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

Technically, a rule whose selector includes .marginBox could go on to actually target something inside the marginBox. For example, .marginBox .narrowStyle {width: 200px} is fine. But I can't think of a likely reason for such a rule to mention .marginBox, so no point in improving the code unless we encounter a lot of it. Might just be worth commenting, though?

Copy link
Author

Choose a reason for hiding this comment

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

I've added a comment based on what you wrote here.

// A rule like .marginBox { background-color: red; } is just fine.
// We preserve rules like this and add them after this loop changes the current rules.

const unknownDeclarations = rule.declarations?.filter(

Choose a reason for hiding this comment

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

I think an overall purpose comment would be helpful here. Along the lines
We're looking for rules that affect the marginBox's size and position (top/left/height/width) because the new theme system controls these with variables that affect the .bloom-page margin instead of absolutely positioning the .marginBox, so setting its top or left will have no effect, and setting its height or width will probably do something unwanted. If such a rule also changes safe properties, we split it into two rules, one that has only the problem declarations and one that has only the safe ones. NOW EXPLAIN WHY THIS IS USEFUL. (Maybe some other code later looks for just the problem rules and does something with them?)
(Sorry, maybe it's obvious with more of the context than this review is showing me.)

@@ -134,10 +184,14 @@ export function migrateCssToAppearance(cssFileContent: string): string {
declaration.value = ` ignore /* error: ${rule.declarations?.toString()} */`;
else {
if (key === "width") {
declaration.value = size.width - v - left + "mm";
let val = size.width - v - left; // round off to 0 if less than 0.05

Choose a reason for hiding this comment

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

Please don't tell me WHAT you're doing in a comment, especially when it's easy to tell in the code. Tell me WHY we care about rounding a (surely very unlikely) marginBox width of less than ,05mm to zero.

Copy link
Author

Choose a reason for hiding this comment

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

I've written a more extensive comment that covers both calculations.

// sort the classes in the first selector if appropriate
if (!rule.selectors || !rule.selectors.length) return;
var selector = rule.selectors[0].trim();
if (/^.[A-Za-z][-.A-Za-z0-9]*$/.test(selector))

Choose a reason for hiding this comment

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

I'm puzzled.

  1. Why do we want to sort selectors at all?
  2. If I'm reading the calling code correctly, rule is a CssRule object (could we declare that?). These are not expected to have a selectors property, so maybe this code will never do anything?
  3. Since I can't find any doc on this property, I'm not sure what it contains. For example, given an overall selector like ".bloom-page.A5Portrait .marginBox", is rule.selectors[0].trim() supposed to return ".bloom-page.A5Portrait"? So this would convert it to ".A5Portrait.bloom-page .marginBox"?
  4. Is the first dot actually meant to match a dot, rather than any character? (Should it have a backslash?) So for example it then wouldn't attempt to sort ":not(.frontCover).bloom-page.front-matter"? (Of course it won't anyway because the parens don't match.)
  5. If we need the trim(), it's presumably because rule.selectors[0] includes the space separating it from the next component of the selector. If that's true, so we need to put that space back below?
  6. Assuming there IS a reason to sort them, will it matter than a selector like .bloom-page.A5Portrait:not(.front-matter):not(.back-matter) does not get changed (because the parens don't match)? (If you need to make it handle that, remember that splitting at dots and sorting will do something horrible to :not(.front-matter))

Copy link
Author

@StephenMcConnel StephenMcConnel Dec 8, 2023

Choose a reason for hiding this comment

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

  1. I don't know that we need to, but JohnH's original code was doing this, albeit not as safely.
  2. I haven't been able to find out anything about the classes used here. "bun" (which is how JohnH set things up) has all sorts of things built in that don't have any intellesense type operation.
  3. The selector property is an array of strings that contain the comma separated values from the CSS selector of the rule. The trim() operation would only remove spaces around a comma or the overall beginning or end of the CSS selector.
  4. good catch. :-) Yes, I only try to sort extremely simple selectors: no spaces, no colons, no parentheses...
  5. We don't need to put the space back. The stringify method imported form css has its own ideas of formatting.
  6. I think the only reason to sort the selector is to make simple cases easier to compare visually by human being. This may not be a compelling reason. :-)

if (d.property === "bottom" ||
d.property === "right" ||
d.property?.includes("margin-") ||
d.property?.includes("padding-")) {

Choose a reason for hiding this comment

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

What happens with a rule like margin: 2px or margin: 2px 3px 4px 5px? Will we get a warning (because it translates into four margin-X declarations) or not (if we just get one declaration with property margin)?

Copy link
Author

@StephenMcConnel StephenMcConnel Dec 8, 2023

Choose a reason for hiding this comment

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

Some of these questions need to have JohnH here to answer them because I don't know enough about the appearance / theme setup to know whether margins and paddings are really problematic or not. His original code marked them as problematic, but then did nothing with them. I've added "margin:" and "padding:" to the mix in addition to "margin-" and "padding-".


if (!l || !t) return; // todo log it?
// remove the .marginBox class from the selectors

Choose a reason for hiding this comment

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

You're telling me WHAT you're doing, but not WHY. We now have a rule that sets some or all of top/left/height/width (and nothing else) for not only .marginBox (which we do NOT want to set these on), but potentially many other elements as well, which we also don't want, AFAIK. What good is that?

Copy link
Author

Choose a reason for hiding this comment

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

I've extensively revised and expanded the comment.
The rule being modified has a selector which includes both .marginBox and a size property such as .A5Portrait. Removing the .marginBox from the selector results in variable setting influenced by the page size (and possibly other properties if the rule has other properties in the selector).

Remember, the output from the tool is supposed to be processed by a human being before being put to use. Think computer assisted migration. Quoting from the issue "We do not intend to make some huge AI version of migrate-css-files-to-variable-system.ts. We just want to provide some help to a human creating a replacement custom CSS."

@StephenMcConnel StephenMcConnel force-pushed the BL-12857-ImproveCssMigrationScripts branch from de778c5 to bba77c7 Compare December 8, 2023 14:19
Copy link

@JohnThomson JohnThomson left a comment

Choose a reason for hiding this comment

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

Thanks for clarifying. Just one thing still has questions, and I may be being too picky even there...

Reviewed 1 of 5 files at r1, 4 of 4 files at r2, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @StephenMcConnel)


custom-css-analysis-and-migration/migrateCssToAppearance.ts line 187 at r1 (raw file):

Previously, StephenMcConnel (Steve McConnel) wrote…

I've written a more extensive comment that covers both calculations.

Much better, thanks.


custom-css-analysis-and-migration/migrateCssToAppearance.ts line 263 at r1 (raw file):

Previously, StephenMcConnel (Steve McConnel) wrote…
  1. I don't know that we need to, but JohnH's original code was doing this, albeit not as safely.
  2. I haven't been able to find out anything about the classes used here. "bun" (which is how JohnH set things up) has all sorts of things built in that don't have any intellesense type operation.
  3. The selector property is an array of strings that contain the comma separated values from the CSS selector of the rule. The trim() operation would only remove spaces around a comma or the overall beginning or end of the CSS selector.
  4. good catch. :-) Yes, I only try to sort extremely simple selectors: no spaces, no colons, no parentheses...
  5. We don't need to put the space back. The stringify method imported form css has its own ideas of formatting.
  6. I think the only reason to sort the selector is to make simple cases easier to compare visually by human being. This may not be a compelling reason. :-)

So if the rule started out with something like
.bloom-page.A5Portrait.outside-front-cover .marginBox, .bloom-page.A5Portrait.outside-back-cover .marginBox
The earlier code will remove the .marginBox, and this will sort the first selector. so we end up with
.A5Portrait.bloom-page.outside-front-cover, .bloom-page.A5Portrait.outside-back-cover
Assuming there is some reason to sort the classes in the first selector, why not those in the other?

Since it's not easy to find doc on the selectors property, I think it would be helpful to comment on that, and perhaps also give an example or two of what it is intended to do (and to leave alone).

Normally I would suggest unit tests for something like this, but if JohnH hasn't already done that you'd have to figure out how to set them up for the whole project, and it is a thing we only expect to use once, ourselves, and check the results by hand. So probably not worth it. I'm probably being too picky even trying to improve comments.

Copy link
Author

@StephenMcConnel StephenMcConnel left a comment

Choose a reason for hiding this comment

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

Reviewable status: 4 of 5 files reviewed, 2 unresolved discussions (waiting on @JohnThomson)


custom-css-analysis-and-migration/migrateCssToAppearance.ts line 145 at r1 (raw file):

Previously, JohnThomson (John Thomson) wrote…

I think an overall purpose comment would be helpful here. Along the lines
We're looking for rules that affect the marginBox's size and position (top/left/height/width) because the new theme system controls these with variables that affect the .bloom-page margin instead of absolutely positioning the .marginBox, so setting its top or left will have no effect, and setting its height or width will probably do something unwanted. If such a rule also changes safe properties, we split it into two rules, one that has only the problem declarations and one that has only the safe ones. NOW EXPLAIN WHY THIS IS USEFUL. (Maybe some other code later looks for just the problem rules and does something with them?)
(Sorry, maybe it's obvious with more of the context than this review is showing me.)

Done.


custom-css-analysis-and-migration/migrateCssToAppearance.ts line 263 at r1 (raw file):

Previously, JohnThomson (John Thomson) wrote…

So if the rule started out with something like
.bloom-page.A5Portrait.outside-front-cover .marginBox, .bloom-page.A5Portrait.outside-back-cover .marginBox
The earlier code will remove the .marginBox, and this will sort the first selector. so we end up with
.A5Portrait.bloom-page.outside-front-cover, .bloom-page.A5Portrait.outside-back-cover
Assuming there is some reason to sort the classes in the first selector, why not those in the other?

Since it's not easy to find doc on the selectors property, I think it would be helpful to comment on that, and perhaps also give an example or two of what it is intended to do (and to leave alone).

Normally I would suggest unit tests for something like this, but if JohnH hasn't already done that you'd have to figure out how to set them up for the whole project, and it is a thing we only expect to use once, ourselves, and check the results by hand. So probably not worth it. I'm probably being too picky even trying to improve comments.

I found the documentation for the css package and added a comment pointing to it next to the import statement.
I enhanced the sort function to handle all of the selectors, not just the first one. I also added some comments to the function.

Also fix bugs caused by shortening paths in filter output.
@StephenMcConnel StephenMcConnel force-pushed the BL-12857-ImproveCssMigrationScripts branch from 4cfabd0 to 2d1cffb Compare January 9, 2024 16:38
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.

2 participants