mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-02-07 16:11:12 +01:00
Merge pull request #20485 from calixteman/lint_mc_css
Add a new linting task in order to detect unused/unknown css variables in the Firefox build
This commit is contained in:
commit
5b22189c24
3
.github/workflows/lint.yml
vendored
3
.github/workflows/lint.yml
vendored
@ -32,3 +32,6 @@ jobs:
|
||||
|
||||
- name: Run lint-chromium
|
||||
run: npx gulp lint-chromium
|
||||
|
||||
- name: Run lint-mozcentral
|
||||
run: npx gulp lint-mozcentral
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
"float": ["inline-start", "inline-end"]
|
||||
},
|
||||
"length-zero-no-unit": [true, {
|
||||
ignore: ["custom-properties"]
|
||||
"ignore": ["custom-properties"]
|
||||
}],
|
||||
"selector-pseudo-element-colon-notation": "double",
|
||||
"shorthand-property-no-redundant-values": true,
|
||||
},
|
||||
"shorthand-property-no-redundant-values": true
|
||||
}
|
||||
}
|
||||
|
||||
19
external/builder/builder.mjs
vendored
19
external/builder/builder.mjs
vendored
@ -39,15 +39,22 @@ function preprocess(inFilename, outFilename, defines) {
|
||||
}
|
||||
|
||||
function expandCssImports(content, baseUrl) {
|
||||
if (defines.GECKOVIEW) {
|
||||
// In Geckoview, we don't need some styles.
|
||||
const startComment = "/* Ignored in GECKOVIEW: begin */";
|
||||
const endComment = "/* Ignored in GECKOVIEW: end */";
|
||||
const beginIndex = content.indexOf(startComment);
|
||||
const endIndex = content.indexOf(endComment);
|
||||
if (beginIndex >= 0 && endIndex > beginIndex) {
|
||||
content =
|
||||
content.substring(0, beginIndex) +
|
||||
content.substring(endIndex + endComment.length);
|
||||
}
|
||||
}
|
||||
|
||||
return content.replaceAll(
|
||||
/^\s*@import\s+url\(([^)]+)\);\s*$/gm,
|
||||
function (all, url) {
|
||||
if (defines.GECKOVIEW) {
|
||||
switch (url) {
|
||||
case "annotation_editor_layer_builder.css":
|
||||
return "";
|
||||
}
|
||||
}
|
||||
const file = path.join(path.dirname(baseUrl), url);
|
||||
const imported = fs.readFileSync(file, "utf8").toString();
|
||||
return expandCssImports(imported, file);
|
||||
|
||||
110
external/stylelint/no-unused-custom-properties.mjs
vendored
Normal file
110
external/stylelint/no-unused-custom-properties.mjs
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/* Copyright 2025 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO: Remove the exception below once someone figures out how to fix it.
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { parse, registerWalkers, Root } from "postcss-values-parser";
|
||||
import { isString } from "stylelint/lib/utils/validateTypes.mjs";
|
||||
import stylelint from "stylelint";
|
||||
|
||||
const {
|
||||
createPlugin,
|
||||
utils: { report, validateOptions },
|
||||
} = stylelint;
|
||||
|
||||
registerWalkers(Root);
|
||||
|
||||
const ruleName = "pdfjs/no-unused-custom-properties";
|
||||
|
||||
// It's a very basic linter: we don't take into account scopes.
|
||||
// But it should be enough for our use case.
|
||||
|
||||
/** @type {import('stylelint').Plugin} */
|
||||
const ruleFunction =
|
||||
(enabled, { ignoreList = [] } = {}, context = {}) =>
|
||||
(root, result) => {
|
||||
const validOptions = validateOptions(
|
||||
result,
|
||||
ruleName,
|
||||
{
|
||||
actual: enabled,
|
||||
possible: [true],
|
||||
},
|
||||
{
|
||||
actual: ignoreList,
|
||||
possible: [isString],
|
||||
optional: true,
|
||||
}
|
||||
);
|
||||
|
||||
if (!validOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
ignoreList = ignoreList.map(s => (s.startsWith("--") ? s : `--${s}`));
|
||||
|
||||
const usedCustomProperties = new Set(ignoreList);
|
||||
const definedCustomProperties = new Set();
|
||||
const usedBy = new Map();
|
||||
root.walkDecls(decl => {
|
||||
let definingProperty = null;
|
||||
if (decl.prop.startsWith("--")) {
|
||||
// This is a custom property definition.
|
||||
definingProperty = decl.prop;
|
||||
definedCustomProperties.add(definingProperty);
|
||||
}
|
||||
// Parse the declaration value to find var() usages.
|
||||
const parsedValue = parse(decl.value);
|
||||
parsedValue.walkFuncs(node => {
|
||||
if (!node.isVar || node.nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
// This is a var() function; get the custom property name.
|
||||
const property = node.nodes[0].value;
|
||||
if (!definingProperty) {
|
||||
// This is a usage of a custom property but not in a definition.
|
||||
// width: var(--foo);
|
||||
usedCustomProperties.add(property);
|
||||
return;
|
||||
}
|
||||
let usages = usedBy.get(property);
|
||||
if (!usages) {
|
||||
usages = [];
|
||||
usedBy.set(property, usages);
|
||||
}
|
||||
// Record that this custom property is used by the defining property.
|
||||
// --foo: var(--bar);
|
||||
// bar is really used only if foo is.
|
||||
usages.push(definingProperty);
|
||||
});
|
||||
});
|
||||
const isUsed = p =>
|
||||
usedCustomProperties.has(p) || (usedBy.get(p) || []).some(isUsed);
|
||||
for (const customProperty of definedCustomProperties) {
|
||||
if (isUsed(customProperty)) {
|
||||
continue;
|
||||
}
|
||||
report({
|
||||
message: `Custom property "${customProperty}" is defined but never used.`,
|
||||
node: root,
|
||||
result,
|
||||
ruleName,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ruleFunction.ruleName = ruleName;
|
||||
|
||||
export default createPlugin(ruleName, ruleFunction);
|
||||
29
gulpfile.mjs
29
gulpfile.mjs
@ -2099,6 +2099,35 @@ gulp.task("lint", function (done) {
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
"lint-mozcentral",
|
||||
gulp.series("mozcentral", function runLintMozcentral(done) {
|
||||
console.log();
|
||||
console.log("### Checking mozilla-central files");
|
||||
|
||||
const styleLintOptions = [
|
||||
"../../node_modules/stylelint/bin/stylelint.mjs",
|
||||
"**/*.css",
|
||||
"--report-needless-disables",
|
||||
"--config",
|
||||
"../../stylelint-mozcentral.json",
|
||||
];
|
||||
|
||||
const styleLintProcess = startNode(styleLintOptions, {
|
||||
stdio: "inherit",
|
||||
cwd: BUILD_DIR + "mozcentral/",
|
||||
});
|
||||
styleLintProcess.on("close", function (styleLintCode) {
|
||||
if (styleLintCode !== 0) {
|
||||
done(new Error("Stylelint failed."));
|
||||
return;
|
||||
}
|
||||
console.log("files checked, no errors found");
|
||||
done();
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
"lint-chromium",
|
||||
gulp.series(
|
||||
|
||||
1032
package-lock.json
generated
1032
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@
|
||||
"postcss-dir-pseudo-class": "^9.0.1",
|
||||
"postcss-discard-comments": "^7.0.5",
|
||||
"postcss-nesting": "^13.0.2",
|
||||
"postcss-values-parser": "^7.0.0",
|
||||
"prettier": "^3.7.2",
|
||||
"puppeteer": "^24.31.0",
|
||||
"stylelint": "^16.26.1",
|
||||
|
||||
12
stylelint-mozcentral.json
Normal file
12
stylelint-mozcentral.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"plugins": ["./external/stylelint/no-unused-custom-properties.mjs"],
|
||||
"rules": {
|
||||
"no-unknown-custom-properties": true,
|
||||
"pdfjs/no-unused-custom-properties": [
|
||||
true,
|
||||
{
|
||||
"ignoreList": ["scale-round-x", "scale-round-y", "input-width"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
17
web/menu.css
17
web/menu.css
@ -33,6 +33,23 @@
|
||||
--menuitem-focus-outline-color: light-dark(#0062fa, #00cadb);
|
||||
--menuitem-focus-border-color: light-dark(white, black);
|
||||
|
||||
--menu-bg: light-dark(white, #23222b);
|
||||
--menu-background-blend-mode: normal;
|
||||
--menu-box-shadow:
|
||||
0 0.375px 1.5px 0 light-dark(rgb(0 0 0 / 0.05), rgb(0 0 0 / 0.2)),
|
||||
0 3px 12px 0 light-dark(rgb(0 0 0 / 0.1), rgb(0 0 0 / 0.4));
|
||||
--menu-border-color: light-dark(rgb(21 20 26 / 0.1), rgb(251 251 254 / 0.1));
|
||||
--menuitem-border-radius: 8px;
|
||||
--menu-backdrop-filter: none;
|
||||
--menu-text-color: light-dark(#15141a, #fbfbfe);
|
||||
--menuitem-text-hover-fg: var(--menu-text-color);
|
||||
--menuitem-hover-bg: color-mix(
|
||||
in srgb,
|
||||
var(--menu-text-color),
|
||||
transparent 86%
|
||||
);
|
||||
--menuitem-hover-background-blend-mode: normal;
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
--menu-bg: Canvas;
|
||||
--menu-background-blend-mode: normal;
|
||||
|
||||
@ -17,10 +17,11 @@
|
||||
@import url(text_layer_builder.css);
|
||||
@import url(annotation_layer_builder.css);
|
||||
@import url(xfa_layer_builder.css);
|
||||
/* Ignored in GECKOVIEW builds: */
|
||||
/* Ignored in GECKOVIEW: begin */
|
||||
@import url(annotation_editor_layer_builder.css);
|
||||
@import url(sidebar.css);
|
||||
@import url(menu.css);
|
||||
/* Ignored in GECKOVIEW: end */
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
--border-color-interactive: light-dark(#8f8f9d, #f9f9fa);
|
||||
--border-color-interactive-hover: var(--border-color-interactive);
|
||||
--border-color-interactive-active: var(--border-color-interactive);
|
||||
--focus-outline-offset: 2px;
|
||||
|
||||
@media (forced-colors: active) {
|
||||
--color-accent-primary: ButtonText;
|
||||
|
||||
@ -16,12 +16,6 @@
|
||||
@import url(pdf_viewer.css);
|
||||
|
||||
:root {
|
||||
--dir-factor: 1;
|
||||
--scale-select-width: 140px;
|
||||
|
||||
--toolbar-icon-opacity: 1;
|
||||
--doorhanger-icon-opacity: 0.9;
|
||||
|
||||
--main-color: light-dark(rgb(12 12 13), rgb(249 249 250));
|
||||
--body-bg-color: light-dark(rgb(212 212 215), rgb(42 42 46));
|
||||
--scrollbar-color: light-dark(auto, rgb(121 121 123));
|
||||
@ -46,10 +40,6 @@
|
||||
--toolbarButton-download-icon: url(images/gv-toolbarButton-download.svg);
|
||||
}
|
||||
|
||||
:root:dir(rtl) {
|
||||
--dir-factor: -1;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
:root {
|
||||
--dialog-button-border: 1px solid Highlight;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user