mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-16 02:27:21 +02:00
fix(v2): fix code block title parsing, support multiple metastring attributes (#4541)
* feat: lazy match classic theme code block title * feat: allow single quotes for classic theme code block title * refactor(v2): extract parseCodeBlockTitle function extract `parseCodeBlockTitle` function to add tests for title parsing * test(v2): add tests for parseCodeBlockTitle * move code block title parser to theme-common Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
8119de105a
commit
1abadbaeca
4 changed files with 71 additions and 9 deletions
|
@ -15,7 +15,8 @@ import type {Props} from '@theme/CodeBlock';
|
||||||
import Translate, {translate} from '@docusaurus/Translate';
|
import Translate, {translate} from '@docusaurus/Translate';
|
||||||
|
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
import {useThemeConfig} from '@docusaurus/theme-common';
|
|
||||||
|
import {useThemeConfig, parseCodeBlockTitle} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||||
const getHighlightDirectiveRegex = (
|
const getHighlightDirectiveRegex = (
|
||||||
|
@ -85,7 +86,6 @@ const highlightDirectiveRegex = (lang) => {
|
||||||
return getHighlightDirectiveRegex();
|
return getHighlightDirectiveRegex();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const codeBlockTitleRegex = /(?:title=")(.*)(?:")/;
|
|
||||||
|
|
||||||
export default function CodeBlock({
|
export default function CodeBlock({
|
||||||
children,
|
children,
|
||||||
|
@ -109,7 +109,7 @@ export default function CodeBlock({
|
||||||
|
|
||||||
const button = useRef(null);
|
const button = useRef(null);
|
||||||
let highlightLines: number[] = [];
|
let highlightLines: number[] = [];
|
||||||
let codeBlockTitle = '';
|
const codeBlockTitle = parseCodeBlockTitle(metastring);
|
||||||
|
|
||||||
const prismTheme = usePrismTheme();
|
const prismTheme = usePrismTheme();
|
||||||
|
|
||||||
|
@ -123,12 +123,6 @@ export default function CodeBlock({
|
||||||
highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0);
|
highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metastring && codeBlockTitleRegex.test(metastring)) {
|
|
||||||
// Tested above
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, prefer-destructuring
|
|
||||||
codeBlockTitle = metastring.match(codeBlockTitleRegex)![1];
|
|
||||||
}
|
|
||||||
|
|
||||||
let language =
|
let language =
|
||||||
languageClassName &&
|
languageClassName &&
|
||||||
// Force Prism's language union type to `any` because it does not contain all available languages
|
// Force Prism's language union type to `any` because it does not contain all available languages
|
||||||
|
|
|
@ -20,6 +20,8 @@ export {createStorageSlot, listStorageKeys} from './utils/storageUtils';
|
||||||
|
|
||||||
export {useAlternatePageUtils} from './utils/useAlternatePageUtils';
|
export {useAlternatePageUtils} from './utils/useAlternatePageUtils';
|
||||||
|
|
||||||
|
export {parseCodeBlockTitle} from './utils/codeBlockUtils';
|
||||||
|
|
||||||
export {docVersionSearchTag, DEFAULT_SEARCH_TAG} from './utils/searchUtils';
|
export {docVersionSearchTag, DEFAULT_SEARCH_TAG} from './utils/searchUtils';
|
||||||
|
|
||||||
export {isDocsPluginEnabled} from './utils/docsUtils';
|
export {isDocsPluginEnabled} from './utils/docsUtils';
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {parseCodeBlockTitle} from '../codeBlockUtils';
|
||||||
|
|
||||||
|
describe('parseCodeBlockTitle', () => {
|
||||||
|
test('should parse double quote delimited title', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title="index.js"`)).toEqual(`index.js`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse single quote delimited title', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title='index.js'`)).toEqual(`index.js`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not parse mismatched quote delimiters', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title="index.js'`)).toEqual(``);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse undefined metastring', () => {
|
||||||
|
expect(parseCodeBlockTitle(undefined)).toEqual(``);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse metastring with no title specified', () => {
|
||||||
|
expect(parseCodeBlockTitle(`{1,2-3}`)).toEqual(``);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse with multiple metadatas title first', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title="index.js" label="JavaScript"`)).toEqual(
|
||||||
|
`index.js`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse with multiple metadatas title last', () => {
|
||||||
|
expect(parseCodeBlockTitle(`label="JavaScript" title="index.js"`)).toEqual(
|
||||||
|
`index.js`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse double quotes when delimited by single quotes', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title='console.log("Hello, World!")'`)).toEqual(
|
||||||
|
`console.log("Hello, World!")`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should parse single quotes when delimited by double quotes', () => {
|
||||||
|
expect(parseCodeBlockTitle(`title="console.log('Hello, World!')"`)).toEqual(
|
||||||
|
`console.log('Hello, World!')`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
12
packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts
Normal file
12
packages/docusaurus-theme-common/src/utils/codeBlockUtils.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const codeBlockTitleRegex = /title=(["'])(.*?)\1/;
|
||||||
|
|
||||||
|
export function parseCodeBlockTitle(metastring?: string): string {
|
||||||
|
return metastring?.match(codeBlockTitleRegex)?.[2] ?? '';
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue