Skip to content

Commit

Permalink
Merge pull request #16 from dwyl/v3
Browse files Browse the repository at this point in the history
[PR] Migrate to `v3`
  • Loading branch information
nelsonic authored Oct 14, 2024
2 parents 322f93e + 4f05979 commit 9370efd
Show file tree
Hide file tree
Showing 146 changed files with 9,145 additions and 18,453 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ jobs:
- name: Install dependencies
run: pnpm install --no-frozen-lockfile

# Run `markdownlint-cli2` to lint markdown files
# Run `markdownlint-cli2` to lint markdown files (checks dead links with `remark-lint-no-dead-urls`)
- name: Running `markdownlint-cli2`
run: pnpm run lint:check-markdown

# Run script to check for dead links
- name: Checking for dead links
run: pnpm run lint:check-external-links

# Run build
- name: Build Next.js app
run: pnpm run build
Expand Down
10 changes: 10 additions & 0 deletions .remarkignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# `_app.mdx` and `index.mdx` files are essentially `.js` files that don't need linting.
src/**/_app.mdx
src/**/index.mdx

# Parked/archived directories won't be linted
src/**/**/_*


# Linting rules don't need to apply to `README.md`, only for documentation
README.md
29 changes: 0 additions & 29 deletions contentlayer.config.js

This file was deleted.

4 changes: 2 additions & 2 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const config: Config = {
setupFiles: ["./jest.polyfills.js"],

collectCoverage: true,
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "scripts/*.{mjs,js,jsx,ts,tsx}", "!<rootDir>/node_modules/"],
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "scripts/*.{mjs,js,jsx,ts,tsx}", "!<rootDir>/node_modules/", "!src/generatePrivateRoutes.ts"],
coverageDirectory: "coverage",
coveragePathIgnorePatterns: ["/node_modules/"],
coverageProvider: "v8",
Expand Down Expand Up @@ -44,7 +44,7 @@ const config: Config = {
},

testEnvironment: "jsdom",
testPathIgnorePatterns: ["tests/e2e"],
testPathIgnorePatterns: ["tests/e2e", "tests/unit/link-check.test.ts"],
};

export default createJestConfig(config);
151 changes: 151 additions & 0 deletions lint/lint.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import fs from "fs";
import path from "path";
import yargs from "yargs";
import ignore from "ignore";
import { glob } from "glob";
import { remark } from "remark";
import { reporter } from "vfile-reporter";
import { hideBin } from "yargs/helpers";
import {read} from 'to-vfile'

// Counter to keep track of total warnings
let totalWarnings = 0;

/**
* Load and parse the .remarkignore file.
* @param {string} path path to the ignore file.
* @returns {Promise<ignore>} A promise that resolves with the ignore instance.
*/
async function loadIgnoreFile(path) {
try {
const ignoreFileContent = fs.readFileSync(path, "utf-8");
const ig = ignore().add(ignoreFileContent);
return ig;
} catch (err) {
console.warn("No .remarkignore file found, proceeding without ignoring files.");
return ignore();
}
}

/**
* Process a single file with the given preset and formatting flag.
* @param {string} filePath The path to the file
* @param {string} preset The preset object to use for linting with array of remark plugins
* @param {boolean} shouldFormat Flag to indicate whether formatting (changing markdown files) should be applied
*/
async function formatSingleFile(filePath, preset, shouldFormat) {
try {
// Create a virtual file with metadata like `stem`.
// This is needed for rules related to files.
const vfile = await read(filePath);

// Process the file with the given preset
const file = await remark().use(preset).process(vfile);

// Check if there are any issues
const issues = file.messages.length;

// Print the issues
if (issues === 0) {
console.log(`${filePath}: no issues found`);
} else {
totalWarnings += file.messages.length;
console.error(reporter(file));
}

// Write the file back if formatting is enabled
if (shouldFormat) {
fs.writeFileSync(filePath, file.value.toString());
}
} catch (err) {
console.error(`Error processing file ${filePath}:`, err);
}
}

// Main function to handle glob pattern and process files
/**
* Process files based on the given pattern, preset, and formatting flag.
* @param {string} pattern The glob pattern to match files.
* @param {string} pattern The path to the ignore file.
* @param {string} preset The path to the preset object to use for linting with array of remark plugins.
* @param {boolean} shouldFormat Flag to indicate whether formatting (changing markdown files) should be applied.
* @param {boolean} failOnError Flag to indicate whether to fail command if any error is found.
* @returns {Promise<void>} A promise that resolves when all files are processed.
*/
export async function processFiles(pattern, ignoreFile, preset, shouldFormat, failOnError) {
try {
// Load the ignore file and get the list of files
const ig = await loadIgnoreFile(ignoreFile);
const files = await glob(pattern);

if (files.length === 0) {
console.log("No files matched the given pattern.");
return;
}

// Filter out files that are ignored
const filteredFiles = files.filter((file) => !ig.ignores(file));

if (filteredFiles.length === 0) {
console.log("All matched files are ignored.");
return;
}

// Process each file
for (const file of filteredFiles) {
await formatSingleFile(file, preset, shouldFormat);
}

// Print total warnings and fail command if needed
if (totalWarnings > 0) {
console.log(`⚠️ Total ${totalWarnings} warning(s)`);
if (failOnError) {
process.exit(1);
}
}
} catch (err) {
console.error("Error during file processing:", err);
}
}

// Use yargs to handle command-line arguments
const argv = yargs(hideBin(process.argv))
.option("pattern", {
alias: "p",
type: "string",
description: "Glob pattern to match files",
demandOption: true,
})
.option("preset", {
alias: "r",
type: "string",
description: "Path to the preset file",
demandOption: true,
})
.option("ignoreFile", {
alias: "i",
type: "string",
description: "Path to the ignore file",
demandOption: false,
})
.option("format", {
alias: "f",
type: "boolean",
description: "Flag to indicate whether formatting should be applied",
default: false,
})
.option("failOnError", {
alias: "e",
type: "boolean",
description: "Flag to indicate whether to fail command if any error is found",
default: false,
}).argv;

// Dynamically import the preset file
const presetPath = path.resolve(argv.preset);
import(presetPath)
.then((preset) =>
// Start processing files
processFiles(argv.pattern, argv.ignoreFile, preset.default, argv.format, argv.failOnError)
);

32 changes: 32 additions & 0 deletions lint/remark-preset.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import remarkMdx from "remark-mdx";
import remarkGfm from "remark-gfm";
import remarkLint from "remark-lint";
import remarkValidateLinks from "remark-validate-links";
import remarkLintNoDeadUrls from "remark-lint-no-dead-urls"

// This configuration file is meant to be used in `remark CLI` to check for warnings.
// This means that if any of these fail, the command still succeeds.
// See https://github.com/unifiedjs/unified-engine#options for the options.
const remarkPreset = {
plugins: [
// Support `mdx` and GFM
remarkMdx, // https://mdxjs.com/packages/remark-mdx/
remarkGfm, // https://github.com/remarkjs/remark-gfm

// Introduce remark linting rules
remarkLint,

// Validating URLs
remarkValidateLinks, // https://github.com/remarkjs/remark-validate-links
remarkLintNoDeadUrls // https://github.com/remarkjs/remark-lint-no-dead-urls
],
// Override `remark-stringify` rules when serializing text.
// See https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#options for options.
settings: {
emphasis: "_",
strong: "*",
bullet: "-",
},
};

export default remarkPreset;
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
10 changes: 0 additions & 10 deletions next.config.js

This file was deleted.

12 changes: 12 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import withPlugins from 'next-compose-plugins';
import nextra from 'nextra'

const withNextra = nextra({
theme: "./theme/src/index.tsx",
themeConfig: "./theme.config.tsx",
defaultShowCopyCode: true,
})


export default withPlugins([withNextra]);
Loading

0 comments on commit 9370efd

Please sign in to comment.