Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@docusaurus/utils

Package Overview
Dependencies
Maintainers
6
Versions
1839
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@docusaurus/utils - npm Package Compare versions

Comparing version 2.0.0-alpha.69 to 2.0.0-alpha.378053ac5

src/__tests__/__snapshots__/index.test.ts.snap

16

lib/index.d.ts

@@ -7,3 +7,3 @@ /**

*/
import { ReportingSeverity } from '@docusaurus/types';
import { ReportingSeverity, TranslationFileContent, TranslationFile } from '@docusaurus/types';
export declare function generate(generatedFilesDir: string, file: string, content: any, skipCache?: boolean): Promise<void>;

@@ -79,5 +79,19 @@ export declare function objectWithKeySorted(obj: {

};
export declare function getPluginI18nPath({ siteDir, locale, pluginName, pluginId, // TODO duplicated constant
subPaths, }: {
siteDir: string;
locale: string;
pluginName: string;
pluginId?: string | undefined;
subPaths?: string[];
}): string;
export declare function mapAsyncSequencial<T extends unknown, R extends unknown>(array: T[], action: (t: T) => Promise<R>): Promise<R[]>;
export declare function findAsyncSequential<T>(array: T[], predicate: (t: T) => Promise<boolean>): Promise<T | undefined>;
export declare function findFolderContainingFile(folderPaths: string[], relativeFilePath: string): Promise<string | undefined>;
export declare function getFolderContainingFile(folderPaths: string[], relativeFilePath: string): Promise<string>;
export declare function reportMessage(message: string, reportingSeverity: ReportingSeverity): void;
export declare function mergeTranslations(contents: TranslationFileContent[]): TranslationFileContent;
export declare function getSwizzledComponent(componentPath: string): string | undefined;
export declare function updateTranslationFileMessages(translationFile: TranslationFile, updateMessage: (message: string) => string): TranslationFile;
export {};
//# sourceMappingURL=index.d.ts.map

@@ -12,3 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.getSwizzledComponent = exports.reportMessage = exports.getElementsAround = exports.getFilePathForRoutePath = exports.removePrefix = exports.removeSuffix = exports.removeTrailingSlash = exports.addTrailingSlash = exports.addLeadingSlash = exports.resolvePathname = exports.isValidPathname = exports.getEditUrl = exports.aliasedSitePath = exports.normalizeUrl = exports.parseMarkdownFile = exports.parseMarkdownString = exports.createExcerpt = exports.getSubFolder = exports.idx = exports.genChunkName = exports.posixPath = exports.genComponentName = exports.upperFirst = exports.docuHash = exports.simpleHash = exports.encodePath = exports.fileToPath = exports.objectWithKeySorted = exports.generate = void 0;
exports.updateTranslationFileMessages = exports.getSwizzledComponent = exports.mergeTranslations = exports.reportMessage = exports.getFolderContainingFile = exports.findFolderContainingFile = exports.findAsyncSequential = exports.mapAsyncSequencial = exports.getPluginI18nPath = exports.getElementsAround = exports.getFilePathForRoutePath = exports.removePrefix = exports.removeSuffix = exports.removeTrailingSlash = exports.addTrailingSlash = exports.addLeadingSlash = exports.resolvePathname = exports.isValidPathname = exports.getEditUrl = exports.aliasedSitePath = exports.normalizeUrl = exports.parseMarkdownFile = exports.parseMarkdownString = exports.createExcerpt = exports.getSubFolder = exports.idx = exports.genChunkName = exports.posixPath = exports.genComponentName = exports.upperFirst = exports.docuHash = exports.simpleHash = exports.encodePath = exports.fileToPath = exports.objectWithKeySorted = exports.generate = void 0;
const chalk_1 = __importDefault(require("chalk"));

@@ -25,2 +25,3 @@ const path_1 = __importDefault(require("path"));

const resolve_pathname_1 = __importDefault(require("resolve-pathname"));
const lodash_1 = require("lodash");
const fileHash = new Map();

@@ -381,2 +382,48 @@ async function generate(generatedFilesDir, file, content, skipCache = process.env.NODE_ENV === 'production') {

exports.getElementsAround = getElementsAround;
function getPluginI18nPath({ siteDir, locale, pluginName, pluginId = 'default', // TODO duplicated constant
subPaths = [], }) {
return path_1.default.join(siteDir, 'i18n',
// namespace first by locale: convenient to work in a single folder for a translator
locale,
// Make it convenient to use for single-instance
// ie: return "docs", not "docs-default" nor "docs/default"
`${pluginName}${
// TODO duplicate constant :(
pluginId === 'default' ? '' : `-${pluginId}`}`, ...subPaths);
}
exports.getPluginI18nPath = getPluginI18nPath;
async function mapAsyncSequencial(array, action) {
const results = [];
for (const t of array) {
// eslint-disable-next-line no-await-in-loop
const result = await action(t);
results.push(result);
}
return results;
}
exports.mapAsyncSequencial = mapAsyncSequencial;
async function findAsyncSequential(array, predicate) {
for (const t of array) {
// eslint-disable-next-line no-await-in-loop
if (await predicate(t)) {
return t;
}
}
return undefined;
}
exports.findAsyncSequential = findAsyncSequential;
// return the first folder path in which the file exists in
async function findFolderContainingFile(folderPaths, relativeFilePath) {
return findAsyncSequential(folderPaths, (folderPath) => fs_extra_1.default.pathExists(path_1.default.join(folderPath, relativeFilePath)));
}
exports.findFolderContainingFile = findFolderContainingFile;
async function getFolderContainingFile(folderPaths, relativeFilePath) {
const maybeFolderPath = await findFolderContainingFile(folderPaths, relativeFilePath);
// should never happen, as the source was read from the FS anyway...
if (!maybeFolderPath) {
throw new Error(`relativeFilePath=[${relativeFilePath}] does not exist in any of these folders: \n- ${folderPaths.join('\n- ')}]`);
}
return maybeFolderPath;
}
exports.getFolderContainingFile = getFolderContainingFile;
function reportMessage(message, reportingSeverity) {

@@ -402,2 +449,8 @@ switch (reportingSeverity) {

exports.reportMessage = reportMessage;
function mergeTranslations(contents) {
return contents.reduce((acc, content) => {
return Object.assign(Object.assign({}, acc), content);
}, {});
}
exports.mergeTranslations = mergeTranslations;
function getSwizzledComponent(componentPath) {

@@ -410,1 +463,7 @@ const swizzledComponentPath = path_1.default.resolve(process.cwd(), 'src', componentPath);

exports.getSwizzledComponent = getSwizzledComponent;
// Useful to update all the messages of a translation file
// Used in tests to simulate translations
function updateTranslationFileMessages(translationFile, updateMessage) {
return Object.assign(Object.assign({}, translationFile), { content: lodash_1.mapValues(translationFile.content, (translation) => (Object.assign(Object.assign({}, translation), { message: updateMessage(translation.message) }))) });
}
exports.updateTranslationFileMessages = updateTranslationFileMessages;

7

package.json
{
"name": "@docusaurus/utils",
"version": "2.0.0-alpha.69",
"version": "2.0.0-alpha.378053ac5",
"description": "Node utility functions for Docusaurus packages",

@@ -21,3 +21,3 @@ "main": "./lib/index.js",

"dependencies": {
"@docusaurus/types": "2.0.0-alpha.69",
"@docusaurus/types": "2.0.0-alpha.378053ac5",
"chalk": "^3.0.0",

@@ -27,2 +27,3 @@ "escape-string-regexp": "^2.0.0",

"gray-matter": "^4.0.2",
"lodash": "^4.17.20",
"lodash.camelcase": "^4.3.0",

@@ -35,3 +36,3 @@ "lodash.kebabcase": "^4.1.1",

},
"gitHead": "4410a9eb01b87c2df664986ba37e748ed34a3c78"
"gitHead": "de6131ca7167543245c4a468122559901a442519"
}

@@ -30,3 +30,10 @@ /**

getElementsAround,
mergeTranslations,
mapAsyncSequencial,
findAsyncSequential,
findFolderContainingFile,
getFolderContainingFile,
updateTranslationFileMessages,
} from '../index';
import {sum} from 'lodash';

@@ -564,1 +571,149 @@ describe('load utils', () => {

});
describe('mergeTranslations', () => {
test('should merge translations', () => {
expect(
mergeTranslations([
{
T1: {message: 'T1 message', description: 'T1 desc'},
T2: {message: 'T2 message', description: 'T2 desc'},
T3: {message: 'T3 message', description: 'T3 desc'},
},
{
T4: {message: 'T4 message', description: 'T4 desc'},
},
{T2: {message: 'T2 message 2', description: 'T2 desc 2'}},
]),
).toEqual({
T1: {message: 'T1 message', description: 'T1 desc'},
T2: {message: 'T2 message 2', description: 'T2 desc 2'},
T3: {message: 'T3 message', description: 'T3 desc'},
T4: {message: 'T4 message', description: 'T4 desc'},
});
});
});
describe('mapAsyncSequencial', () => {
function sleep(timeout: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, timeout));
}
test('map sequentially', async () => {
const itemToTimeout: Record<string, number> = {
'1': 50,
'2': 150,
'3': 100,
};
const items = Object.keys(itemToTimeout);
const itemMapStartsAt: Record<string, number> = {};
const itemMapEndsAt: Record<string, number> = {};
const timeBefore = Date.now();
await expect(
mapAsyncSequencial(items, async (item) => {
const itemTimeout = itemToTimeout[item];
itemMapStartsAt[item] = Date.now();
await sleep(itemTimeout);
itemMapEndsAt[item] = Date.now();
return `${item} mapped`;
}),
).resolves.toEqual(['1 mapped', '2 mapped', '3 mapped']);
const timeAfter = Date.now();
const timeTotal = timeAfter - timeBefore;
const totalTimeouts = sum(Object.values(itemToTimeout));
expect(timeTotal > totalTimeouts);
expect(itemMapStartsAt['1'] > 0);
expect(itemMapStartsAt['2'] > itemMapEndsAt['1']);
expect(itemMapStartsAt['3'] > itemMapEndsAt['2']);
});
});
describe('findAsyncSequencial', () => {
function sleep(timeout: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, timeout));
}
test('find sequentially', async () => {
const items = ['1', '2', '3'];
const findFn = jest.fn(async (item: string) => {
await sleep(50);
return item === '2';
});
const timeBefore = Date.now();
await expect(findAsyncSequential(items, findFn)).resolves.toEqual('2');
const timeAfter = Date.now();
expect(findFn).toHaveBeenCalledTimes(2);
expect(findFn).toHaveBeenNthCalledWith(1, '1');
expect(findFn).toHaveBeenNthCalledWith(2, '2');
const timeTotal = timeAfter - timeBefore;
expect(timeTotal > 100);
expect(timeTotal < 150);
});
});
describe('findFolderContainingFile', () => {
test('find appropriate folder', async () => {
await expect(
findFolderContainingFile(
['/abcdef', '/gehij', __dirname, '/klmn'],
'index.test.ts',
),
).resolves.toEqual(__dirname);
});
test('return undefined if no folder contain such file', async () => {
await expect(
findFolderContainingFile(['/abcdef', '/gehij', '/klmn'], 'index.test.ts'),
).resolves.toBeUndefined();
});
});
describe('getFolderContainingFile', () => {
test('get appropriate folder', async () => {
await expect(
getFolderContainingFile(
['/abcdef', '/gehij', __dirname, '/klmn'],
'index.test.ts',
),
).resolves.toEqual(__dirname);
});
test('throw if no folder contain such file', async () => {
await expect(
getFolderContainingFile(['/abcdef', '/gehij', '/klmn'], 'index.test.ts'),
).rejects.toThrowErrorMatchingSnapshot();
});
});
describe('updateTranslationFileMessages', () => {
test('should update messages', () => {
expect(
updateTranslationFileMessages(
{
path: 'abc',
content: {
t1: {message: 't1 message', description: 't1 desc'},
t2: {message: 't2 message', description: 't2 desc'},
t3: {message: 't3 message', description: 't3 desc'},
},
},
(message) => `prefix ${message} suffix`,
),
).toEqual({
path: 'abc',
content: {
t1: {message: 'prefix t1 message suffix', description: 't1 desc'},
t2: {message: 'prefix t2 message suffix', description: 't2 desc'},
t3: {message: 'prefix t3 message suffix', description: 't3 desc'},
},
});
});
});

@@ -17,6 +17,11 @@ /**

import {URL} from 'url';
import {ReportingSeverity} from '@docusaurus/types';
import {
ReportingSeverity,
TranslationFileContent,
TranslationFile,
} from '@docusaurus/types';
// @ts-expect-error: no typedefs :s
import resolvePathnameUnsafe from 'resolve-pathname';
import {mapValues} from 'lodash';

@@ -265,3 +270,3 @@ const fileHash = new Map();

throw new Error(`Error while parsing markdown front matter.
This can happen if you use special characteres like : in frontmatter values (try using "" around that value)
This can happen if you use special characters like : in frontmatter values (try using "" around that value)
${e.message}`);

@@ -394,3 +399,3 @@ }

// resolve pathname and fail fast if resolution fails
export function resolvePathname(to: string, from?: string) {
export function resolvePathname(to: string, from?: string): string {
return resolvePathnameUnsafe(to, from);

@@ -445,2 +450,85 @@ }

export function getPluginI18nPath({
siteDir,
locale,
pluginName,
pluginId = 'default', // TODO duplicated constant
subPaths = [],
}: {
siteDir: string;
locale: string;
pluginName: string;
pluginId?: string | undefined;
subPaths?: string[];
}): string {
return path.join(
siteDir,
'i18n',
// namespace first by locale: convenient to work in a single folder for a translator
locale,
// Make it convenient to use for single-instance
// ie: return "docs", not "docs-default" nor "docs/default"
`${pluginName}${
// TODO duplicate constant :(
pluginId === 'default' ? '' : `-${pluginId}`
}`,
...subPaths,
);
}
export async function mapAsyncSequencial<T extends unknown, R extends unknown>(
array: T[],
action: (t: T) => Promise<R>,
): Promise<R[]> {
const results: R[] = [];
for (const t of array) {
// eslint-disable-next-line no-await-in-loop
const result = await action(t);
results.push(result);
}
return results;
}
export async function findAsyncSequential<T>(
array: T[],
predicate: (t: T) => Promise<boolean>,
): Promise<T | undefined> {
for (const t of array) {
// eslint-disable-next-line no-await-in-loop
if (await predicate(t)) {
return t;
}
}
return undefined;
}
// return the first folder path in which the file exists in
export async function findFolderContainingFile(
folderPaths: string[],
relativeFilePath: string,
): Promise<string | undefined> {
return findAsyncSequential(folderPaths, (folderPath) =>
fs.pathExists(path.join(folderPath, relativeFilePath)),
);
}
export async function getFolderContainingFile(
folderPaths: string[],
relativeFilePath: string,
): Promise<string> {
const maybeFolderPath = await findFolderContainingFile(
folderPaths,
relativeFilePath,
);
// should never happen, as the source was read from the FS anyway...
if (!maybeFolderPath) {
throw new Error(
`relativeFilePath=[${relativeFilePath}] does not exist in any of these folders: \n- ${folderPaths.join(
'\n- ',
)}]`,
);
}
return maybeFolderPath;
}
export function reportMessage(

@@ -471,2 +559,10 @@ message: string,

export function mergeTranslations(
contents: TranslationFileContent[],
): TranslationFileContent {
return contents.reduce((acc, content) => {
return {...acc, ...content};
}, {});
}
export function getSwizzledComponent(

@@ -485,1 +581,16 @@ componentPath: string,

}
// Useful to update all the messages of a translation file
// Used in tests to simulate translations
export function updateTranslationFileMessages(
translationFile: TranslationFile,
updateMessage: (message: string) => string,
): TranslationFile {
return {
...translationFile,
content: mapValues(translationFile.content, (translation) => ({
...translation,
message: updateMessage(translation.message),
})),
};
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc