Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This document summarizes the contribution process.
- Your local branch containing changes for the website should be based off of the [master](https://github.com/apache/ozone-site/tree/master) branch.

2. Use your favorite editor to write markdown content under the [docs/](docs/) and [src/pages/](src/pages/) directories.
- A good option is [Visual Studio Code](https://code.visualstudio.com/) with [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) and [cspell](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) plugins, which will automatically detect the website's configuration files and give feedback as you type.
- A good option is [Visual Studio Code](https://code.visualstudio.com/) with [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) and [cspell](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) plugins, which will automatically detect the website's configuration files and give feedback as you type.

3. Preview your changes locally by running `docker compose up` and opening `localhost:3001` in your browser.
- Make sure [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) are installed on your system.
Expand Down Expand Up @@ -52,8 +52,8 @@ pnpm run lint
pnpm run lint:fix
```

- `pnpm run lint` runs checks only from markdownlint and yamllint (no files are modified).
- `pnpm run lint:fix` applies auto-fixes from markdownlint.
- `pnpm run lint` runs checks only from eslint, markdownlint and yamllint (no files are modified).
- `pnpm run lint:fix` applies auto-fixes from eslint and markdownlint.

**Prerequisites**: The lint scripts require `yamllint`, which is not a Node.js package and must be installed separately. Install it via pip (`pip install yamllint`) or your system package manager (e.g. `brew install yamllint` on macOS).

Expand Down
2 changes: 1 addition & 1 deletion docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ const config = {
const items = await defaultCreateSitemapItems(rest);

const validUrlRegex = /^https:\/\/ozone\.apache\.org\/([a-z0-9][a-z0-9./-]*[a-z0-9/])?$/;
items.forEach((item, index) => {
items.forEach((item) => {
if (!validUrlRegex.test(item.url)) {
console.error('Generated URL', item.url, 'does not match the allowed RegEx:', validUrlRegex);
console.error('All URLs should use kebab case and lowercase letters.');
Expand Down
170 changes: 170 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

import js from "@eslint/js";
import globals from "globals";
import pluginReact from "eslint-plugin-react";
import css from "@eslint/css";
import { defineConfig } from "eslint/config";
import pluginDocusaurus from "@docusaurus/eslint-plugin";
import pluginUnusedImports from "eslint-plugin-unused-imports";
import pluginImport from "eslint-plugin-import";

const apacheLicenseRule = {
meta: {
type: "problem",
docs: {
description: "Enforce Apache License header in source files",
},
fixable: "code",
messages: {
missingHeader: "Missing Apache License header at the top of the file",
},
},
create(context) {
const REQUIRED_HEADER = `/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/`;

return {
Program(node) {
const sourceCode = context.sourceCode || context.getSourceCode();
const text = sourceCode.getText();

if (!text.startsWith(REQUIRED_HEADER)) {
context.report({
node,
messageId: "missingHeader",
fix(fixer) {
return fixer.insertTextBefore(node, REQUIRED_HEADER + "\n\n");
},
});
}
},
};
},
};

export default defineConfig([
// General
{
ignores: [
"static/**",
"node_modules/**",
"build/**",
"dist/**",
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see a dist directory in the repo. Does something generate this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

dist accidentally slipped in, I can remove it. Usually many modern projects use dist instead of build, but we don't

".docusaurus/**",
".github/**",
],
},

// JS
{
files: ["**/*.{js,mjs,cjs,jsx}"],
...js.configs.recommended,
languageOptions: { globals: { ...globals.browser, ...globals.node } },
Copy link
Contributor

Choose a reason for hiding this comment

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

Cursor made this suggestion, although I don't know enough about javascript to really understand the implications:


Medium: browser and node globals are both enabled for all JS files, which can hide environment mistakes.
This permits Node globals in browser code and browser globals in Node-only files without lint failures.
Better practice is split overrides by file location (src/** browser, config/scripts Node).

files: ["**/*.{js,mjs,cjs,jsx}"],
...js.configs.recommended,
languageOptions: { globals: { ...globals.browser, ...globals.node } },
plugins: {
  "unused-imports": pluginUnusedImports,
  import: pluginImport,
},
files: ["**/*.{js,mjs,cjs,jsx}"],...js.configs.recommended,languageOptions: { globals: { ...globals.browser, ...globals.node } },plugins: {  "unused-imports": pluginUnusedImports,  import: pluginImport,},

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, it might be valid, but not for this project. Docusaurus has SSR/browser duality by design, the mixed globals are intentional and splitting them could produce spurious lint errors in components that legitimately need awareness of both environments. We cannot clearly separate the use of node/browser globals by the file extension/location.

You may want to check this out https://docusaurus.io/docs/advanced/ssg

plugins: {
"unused-imports": pluginUnusedImports,
import: pluginImport,
},
rules: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to add a rule to enforce import order?

Copy link
Contributor Author

@yuriipalam yuriipalam Mar 6, 2026

Choose a reason for hiding this comment

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

we can have it like this

"import/order": [
  "error",
  {
    groups: [
      "builtin",      // Node built-ins (path, fs, etc.)
      "external",     // npm packages (react, @docusaurus/*, etc.)
      "internal",     // paths configured as internal (e.g. @site/*)
      ["parent", "sibling", "index"], // relative imports
    ],
    alphabetize: { order: "asc", caseInsensitive: true },
  },
],

"unused-imports/no-unused-imports": "error",
// unused vars (but ignore underscore-prefixed)
"unused-imports/no-unused-vars": [
"warn",
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think warning are useful, people will only check if the command passes or fails. If we care about something we should make it an error. Unused variables should fail linting I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I agree

{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_",
},
],
"import/no-duplicates": "error",
"no-unused-vars": "off",
},
},

// React
{
files: ["**/*.{js,jsx}"],
...pluginReact.configs.flat.recommended,
settings: {
react: { version: "detect" },
},
rules: {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"react/jsx-uses-vars": "error",
},
},

// CSS
{
files: ["**/*.css"],
plugins: { css },
language: "css/css",
extends: ["css/recommended"],
rules: {
"css/no-invalid-properties": "off",
"css/no-important": "off",
"css/use-baseline": "off",
},
},

// Docusaurus
{
files: ["**/*.{js,mjs,cjs,jsx}"],
plugins: { "@docusaurus": pluginDocusaurus },
rules: {
"@docusaurus/no-html-links": "error",
"@docusaurus/prefer-docusaurus-heading": "error",
"@docusaurus/string-literal-i18n-messages": "error",
// for i18n
// "@docusaurus/no-untranslated-text": ["warn", { ignoredStrings: [] }]
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this rule fail even if i18n is disabled? If it passes trivially in this case then we can probably reduce this to just use the default recommended config instead of specifying rules individually.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the i18n rule should pass if i18n is not enabled.

there are just 4 rules in total, and we're basically overriding them.

Default:

'@docusaurus/string-literal-i18n-messages': 'error', // for us it's also error
'@docusaurus/no-html-links': 'warn', // we use error
'@docusaurus/prefer-docusaurus-heading': 'warn',  // we also use error

This one

"@docusaurus/no-untranslated-text": ["warn", { ignoredStrings: [] }]

is commented out right now, since we plan want to start using i18n later, as far as I know
we can uncomment it right now, it won't harm

},
},

// Custom rule to enforce Apache License header
{
files: ["**/*.{js,mjs,cjs,jsx}"],
Comment on lines +158 to +160
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need this. We already have a license header check using skywalking-eyes for all files in CI which is more robust than this strict string constant header check. This does run locally on pnpm lint which is nice, but it only checks javascript files which are rarely modified. I don't think we would want to expand the scope to other file types since it's more brittle than skywalking eyes anyways.

I think we can remove this to keep our linting config simple and reduce duplication/conflicts with skywalking-eyes. In a follow-up change it would be good to have skywalking-eyes run locally on lint too, but that would also require a separate install outside of node.js.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I can remove this

plugins: {
custom: {
rules: { "apache-license": apacheLicenseRule },
},
},
rules: {
"custom/apache-license": "error",
},
},
]);
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
"serve": "docusaurus serve --port 3001",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"lint": "markdownlint \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\"",
"lint:fix": "markdownlint --fix \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\""
"lint": "eslint . && markdownlint \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\"",
"lint:fix": "eslint --fix . && markdownlint --fix \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\""
Comment on lines +16 to +17
Copy link
Contributor

Choose a reason for hiding this comment

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

After some testing, it looks like the . is always resolved to the repo root regardless of which tool is used. Also switching && for ; lets us run all linters at once instead of stopping when the first one hits an error.

Suggested change
"lint": "eslint . && markdownlint \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\"",
"lint:fix": "eslint --fix . && markdownlint --fix \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\""
"lint": "eslint . ; markdownlint . ; yamllint --format=colored .",
"lint:fix": "eslint --fix . ; markdownlint --fix . ; yamllint --format=colored ."

To test this I added this diff and ran pnpm lint from the docs directory, which is lower in the directory tree than any of these changes. Linting errors on all three files were correctly flagged.

diff --git a/compose.yml b/compose.yml
index 1a6c84659..32e67770b 100644
--- a/compose.yml
+++ b/compose.yml
@@ -17,7 +17,7 @@ version: "3"
 
 services:
   site:
-    build: .
+     build: .
     image: ozone-site
     ports:
     - 3001:3001
diff --git a/package.json b/package.json
index 4277cbaf5..e0739a14b 100644
--- a/package.json
+++ b/package.json
@@ -13,8 +13,8 @@
     "serve": "docusaurus serve --port 3001",
     "write-translations": "docusaurus write-translations",
     "write-heading-ids": "docusaurus write-heading-ids",
-    "lint": "eslint . && markdownlint \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\"",
-    "lint:fix": "eslint --fix . && markdownlint --fix \"$(git rev-parse --show-toplevel)\" && yamllint --format=colored \"$(git rev-parse --show-toplevel)\""
+    "lint": "eslint . ; markdownlint . ; yamllint --format=colored .",
+    "lint:fix": "eslint --fix . ; markdownlint --fix . ; yamllint --format=colored ."
   },
   "dependencies": {
     "@docusaurus/core": "3.7.0",
diff --git a/src/pages/download.md b/src/pages/download.md
index 2fefd7658..c543ef39e 100644
--- a/src/pages/download.md
+++ b/src/pages/download.md
@@ -6,7 +6,7 @@
 | 2.0.0   | 2025 Apr 30  | [Source](https://www.apache.org/dyn/closer.cgi/ozone/2.0.0/ozone-2.0.0-src.tar.gz)<br/>[Checksum](https://downloads.apache.org/ozone/2.0.0/ozone-2.0.0-src.tar.gz.sha512)<br/>[Signature](https://downloads.apache.org/ozone/2.0.0/ozone-2.0.0-src.tar.gz.asc) | [Binary](https://www.apache.org/dyn/closer.cgi/ozone/2.0.0/ozone-2.0.0.tar.gz)<br/>[Checksum](https://downloads.apache.org/ozone/2.0.0/ozone-2.0.0.tar.gz.sha512)<br/>[Signature](https://downloads.apache.org/ozone/2.0.0/ozone-2.0.0.tar.gz.asc) | [Release Notes](/release-notes/2.0.0) |
 | 1.4.1   | 2024 Nov 24  | [Source](https://www.apache.org/dyn/closer.cgi/ozone/1.4.1/ozone-1.4.1-src.tar.gz)<br/>[Checksum](https://downloads.apache.org/ozone/1.4.1/ozone-1.4.1-src.tar.gz.sha512)<br/>[Signature](https://downloads.apache.org/ozone/1.4.1/ozone-1.4.1-src.tar.gz.asc) | [Binary](https://www.apache.org/dyn/closer.cgi/ozone/1.4.1/ozone-1.4.1.tar.gz)<br/>[Checksum](https://downloads.apache.org/ozone/1.4.1/ozone-1.4.1.tar.gz.sha512)<br/>[Signature](https://downloads.apache.org/ozone/1.4.1/ozone-1.4.1.tar.gz.asc) | [Release Notes](/release-notes/1.4.1) |
 
-## Archives
+### Archives
 
 Older releases are available from the [Apache Ozone archive](https://archive.apache.org/dist/ozone/).
 
diff --git a/src/theme/DocSidebar/index.module.css b/src/theme/DocSidebar/index.module.css
index 39601f08f..c3d7447af 100644
--- a/src/theme/DocSidebar/index.module.css
+++ b/src/theme/DocSidebar/index.module.css
@@ -48,6 +48,6 @@ aside .customSidebarInner {
 
 aside .customSidebarVersion p {
     margin-bottom: 0;
-    font-size: var(--fbc-font-size, 13px);
+    font-size: var(--fbc-font-size: 13px;);
     padding: var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal);
 }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. But I'm not sure if just . will work with yamllint, since this tool is not an npm package. Therefore, it might not run from the root of the repo if executed not at the root. I'm not sure though, just an assumption

},
"dependencies": {
"@docusaurus/core": "3.7.0",
Expand All @@ -34,9 +34,17 @@
"@cspell/dict-java": "^5.0.11",
"@cspell/dict-markdown": "^2.0.9",
"@cspell/dict-shell": "^1.1.0",
"@docusaurus/eslint-plugin": "^3.9.2",
"@docusaurus/module-type-aliases": "3.7.0",
"@eslint/css": "^0.14.1",
"@eslint/js": "^10.0.1",
"ajv-cli": "^5.0.0",
"cspell": "^8.17.5",
"eslint": "^10.0.2",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-unused-imports": "^4.4.1",
"globals": "^17.4.0",
"markdownlint-cli": "^0.39.0"
},
"browserslist": {
Expand Down
Loading