Skip to content

Commit

Permalink
Feature: Add <BUILTIN_MODULES> Special Word
Browse files Browse the repository at this point in the history
- This allows users to specify a gap between built-ins and third-party in a slightly less wonky way.
- This also allows users to move the built-ins around relative to other imports.
  • Loading branch information
fbartho committed May 16, 2023
1 parent 1616925 commit a04e7a5
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 21 deletions.
11 changes: 7 additions & 4 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ export const mergeableImportFlavors = [
importFlavorType,
] as const;

/*
* Used to mark the position between RegExps,
* where the not matched imports should be placed
export const BUILTIN_MODULES_REGEX_STR = `^(?:node:)?(?:${builtinModules.join(
'|',
)})$`;

export const BUILTIN_MODULES_SPECIAL_WORD = '<BUILTIN_MODULES>';
/**
* Used to mark not otherwise matched imports should be placed
*/
export const BUILTIN_MODULES = `^(?:node:)?(?:${builtinModules.join('|')})$`;
export const THIRD_PARTY_MODULES_SPECIAL_WORD = '<THIRD_PARTY_MODULES>';
export const TYPES_SPECIAL_WORD = '<TYPES>';

Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { parsers as flowParsers } from 'prettier/parser-flow';
import { parsers as htmlParsers } from 'prettier/parser-html';
import { parsers as typescriptParsers } from 'prettier/parser-typescript';

import { THIRD_PARTY_MODULES_SPECIAL_WORD } from './constants';
import {
BUILTIN_MODULES_SPECIAL_WORD,
THIRD_PARTY_MODULES_SPECIAL_WORD,
} from './constants';
import { defaultPreprocessor } from './preprocessors/default';
import { vuePreprocessor } from './preprocessors/vue';
import type { PrettierOptions } from './types';
Expand All @@ -29,7 +32,7 @@ export const options: Record<
default: [
{
value: [
// node.js built-ins are always first
BUILTIN_MODULES_SPECIAL_WORD,
THIRD_PARTY_MODULES_SPECIAL_WORD, // Everything not matching relative imports
'^[.]', // relative imports
],
Expand Down
1 change: 0 additions & 1 deletion src/utils/get-comment-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
type ImportDeclaration,
} from '@babel/types';

import { newLineNode } from '../constants';
import { ImportOrLine, ImportRelated, SomeSpecifier } from '../types';

const SpecifierTypes = [
Expand Down
17 changes: 4 additions & 13 deletions src/utils/get-sorted-nodes-by-import-order.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import {
BUILTIN_MODULES,
newLineNode,
THIRD_PARTY_MODULES_SPECIAL_WORD,
} from '../constants';
import { newLineNode, THIRD_PARTY_MODULES_SPECIAL_WORD } from '../constants';
import type { GetSortedNodes, ImportGroups, ImportOrLine } from '../types';
import { getImportNodesMatchedGroup } from './get-import-nodes-matched-group';
import { getSortedImportSpecifiers } from './get-sorted-import-specifiers';
import { getSortedNodesGroup } from './get-sorted-nodes-group';
import { normalizeImportOrderOption } from './normalize-import-order-options';

/**
* This function returns the given nodes, sorted in the order as indicated by
Expand All @@ -19,17 +16,11 @@ export const getSortedNodesByImportOrder: GetSortedNodes = (
originalNodes,
options,
) => {
let { importOrder } = options;
// This normalization is safe even if the option is already correct.
const importOrder = normalizeImportOrderOption(options.importOrder);

const finalNodes: ImportOrLine[] = [];

if (!importOrder.includes(THIRD_PARTY_MODULES_SPECIAL_WORD)) {
importOrder = [THIRD_PARTY_MODULES_SPECIAL_WORD, ...importOrder];
}

// Opinionated decision: builtin modules should always be first
importOrder = [BUILTIN_MODULES, ...importOrder];

const importOrderGroups = importOrder.reduce<ImportGroups>(
(groups, regexp) =>
// Don't create a new group for explicit import separators
Expand Down
33 changes: 33 additions & 0 deletions src/utils/normalize-import-order-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
BUILTIN_MODULES_REGEX_STR,
BUILTIN_MODULES_SPECIAL_WORD,
THIRD_PARTY_MODULES_SPECIAL_WORD,
} from '../constants';
import { PrettierOptions } from '../types';

export function normalizeImportOrderOption(
importOrder: PrettierOptions['importOrder'],
) {
// THIRD_PARTY_MODULES_SPECIAL_WORD is magic because "everything not matched by other groups goes here"
// So it must always be present.
if (!importOrder.includes(THIRD_PARTY_MODULES_SPECIAL_WORD)) {
importOrder = [THIRD_PARTY_MODULES_SPECIAL_WORD, ...importOrder];
}

// Opinionated Decision: NodeJS Builtin modules should always be separate from third party modules
// Users may want to add their own separators around them or insert other modules above them though
if (
!(
importOrder.includes(BUILTIN_MODULES_SPECIAL_WORD) ||
importOrder.includes(BUILTIN_MODULES_REGEX_STR)
)
) {
importOrder = [BUILTIN_MODULES_SPECIAL_WORD, ...importOrder];
}

importOrder = importOrder.map((g) =>
g === BUILTIN_MODULES_SPECIAL_WORD ? BUILTIN_MODULES_REGEX_STR : g,
);

return importOrder;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`exercise-custom-builtin-modules-spacing.ts - typescript-verify > exercise-custom-builtin-modules-spacing.ts 1`] = `
// Top-of-file-comment
import path from "path"
import b from 'b';
import foo from './foo';
import thirdParty from 'third-party';
import fs from "node:fs"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Top-of-file-comment
import b from "b";
import thirdParty from "third-party";
import fs from "node:fs";
import path from "path";
import foo from "./foo";
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Top-of-file-comment
import path from "path"
import b from 'b';
import foo from './foo';
import thirdParty from 'third-party';
import fs from "node:fs"
5 changes: 5 additions & 0 deletions tests/ImportOrderBuiltinModulesToCustom/ppsi.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {run_spec} from '../../test-setup/run_spec';

run_spec(__dirname, ['typescript'], {
importOrder: ['<THIRD_PARTY_MODULES>','','<BUILTIN_MODULES>','','^[./]'],
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
exports[`relative-import-with-builtin-substring.ts - typescript-verify > relative-import-with-builtin-substring.ts 1`] = `
import foo from './constants/foo';
import thirdParty from 'third-party';
import fs from "fs"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import fs from "fs";
import thirdParty from "third-party";
import foo from "./constants/foo";
Expand Down
2 changes: 1 addition & 1 deletion tests/ImportOrderBuiltinModulesToTop/ppsi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {run_spec} from '../../test-setup/run_spec';

run_spec(__dirname, ['typescript'], {
importOrder: ['^[./]'],
importOrder: ['','<THIRD_PARTY_MODULES>','^[./]'],
});
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import foo from './constants/foo';
import thirdParty from 'third-party';
import fs from "fs"

0 comments on commit a04e7a5

Please sign in to comment.