Jump to content

Extension:WikiLambda/Coding Conventions

From mediawiki.org

This page outlines the coding standards for contributing to the WikiLambda extension. Following these guidelines ensures consistency, readability, and maintainability across the codebase.

Topics covered include naming conventions, code structure, documentation, and best practices. Whether you're new or experienced, adhering to these standards will help streamline the contribution process and maintain high code quality.

Styling

[edit]

The WikiLambda extension frontend is built using Vue, Less, and leverages the Codex Wikimedia Design System. To ensure consistent styling, we use Stylelint.

The guidelines below extend the basic MediaWiki Less styling conventions for Vue. These guidelines ensure consistency in class naming, simplify troubleshooting and refactoring, prevent specificity issues, and enhance the clarity and readability of the code.

Why do we need extra conventions?

The existing conventions in MediaWiki are quite limited, especially when applied to extensions, which may require different approaches from the MediaWiki core. Large applications can become disorganized without a well-defined class naming convention. Implementing additional naming and structure conventions offers several key benefits:

  • Consistency: Ensures all class names follow a predictable structure, making the CSS easier to understand and maintain.
  • Lookup: Simplifies finding and fixing styling issues, aiding in quick refactoring.
  • Performance & Specificity: Prevents specificity issues, which can lead to bloated styles when developers add extra classes to override styles.
  • Clarity and Readability: Provides a self-documenting visual hierarchy in the code.

Folder name as prefix for component class

[edit]

Within the /resources folder, we have various subfolders such as:

  • ext-wikilambda-app
  • ext-wikilambda-editpage
  • ext-wikilambda-languageselector
  • ext-wikilambda-viewpage

We will use the folder name as a prefix for each class within that folder. This approach ensures unique class names for components, making it easier to identify their location within the directory structure. This facilitates faster lookup and simpler debugging.

Implementation details

[edit]

Imagine a pagination component within the /resources/ext-wikilambda-app/components/pagination folder.

The top-level class of this component will become:

<div class="ext-wikilambda-app-pagination">
  // implementation
</div>

In Less, this will become:

.ext-wikilambda-app-pagination {}

Enhanced BEM naming convention

[edit]

The BEM (Block Element Modifier) naming convention simplifies CSS readability and maintenance, scales well for large projects, and ensures a consistent approach.

BEM will be used as described in the Codex selectors and structure section, with the following changes:

  • No nested blocks: Avoid using .cdx-component-name__block-name__block-child-name to reduce complexity.
  • Style elements within the top-level component class to avoid specificity issues. This is explained in the next section.

Implementation details

[edit]

Imagine our pagination component. A pagination usually has elements like a next and previous button or a total pages counter.

In Less, this will be:

.ext-wikilambda-app-pagination {
  .ext-wikilambda-app-pagination__input {}
  .ext-wikilambda-app-pagination__view-all {}
  .ext-wikilambda-app-pagination__total-pages {}
  .ext-wikilambda-app-pagination__action {}
  .ext-wikilambda-app-pagination__action--prev {}
  .ext-wikilambda-app-pagination__action--next {}
}

Style elements within the top-level component class

[edit]

To avoid specificity issues where MediaWiki or other third-party libraries might override our styles, we use the top-level component class as the root for styling the elements inside.

Implementation details

[edit]

MediaWiki targets paragraphs with .mw-body p{}. To ensure we can override this, we add the root component class followed by the actual element:

.ext-wikilambda-app-pagination {
  .ext-wikilambda-app-pagination__text { 
    // styles
  }
}

Overriding styles of a component from another component For usage with Codex or third-party components, see next section.

When you need to override the styles of a component within another component, add a custom class to the component root and style it accordingly:

<template>
  <div class="ext-wikilambda-app-chip-container">
    <wl-chip class="ext-wikilambda-app-chip-container__chip"></wl-chip>
  </div>
</template>
.ext-wikilambda-app-chip-container {
  .ext-wikilambda-app-chip-container__chip {
    // styles
  }
}

Overriding styles of a sub-component or third-party component element For usage with Codex or third-party components, see next section.

To override an element within a third-party component, add your own class to the component's root and then target the specific element inside:

<template>
  <div class="ext-wikilambda-app-chip-container">
    <cdx-chip class="ext-wikilambda-app-chip-container__chip"></cdx-chip>
  </div>
</template>
.ext-wikilambda-app-chip-container {
  .ext-wikilambda-app-chip-container__chip {
    .cdx-chip__text {
      // styles
    }
  }
}

Targeting third-party classes

[edit]

If the approach outlined in the previous section is insufficient and results in specificity issues when targeting Codex or other third-party components, a different method is required.

In such cases, add the element class of the Codex or third-party component to our own custom BEM element class.

Implementation details

[edit]

When styling Codex components, add a custom class along with the Codex component class:

.ext-wikilambda-app-pagination {
  .ext-wikilambda-app-pagination__button.cdx-button {
    // styles
  }
}

For third-party components, a similar approach applies:

.ext-wikilambda-app-code-editor {
  .ext-wikilambda-app-code-editor__editor.ace_editor {
    // styles
  }
}

Directly targeting Codex or third-party classes should be avoided where possible. However, there may be cases where it is necessary due to limitations in component customization.