|
|
@@ -19,7 +19,10 @@ import { RehypeSanitizeType } from '~/interfaces/services/rehype-sanitize';
|
|
|
import type { RendererConfig } from '~/interfaces/services/renderer';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
-import { tagNames as recommendedTagNames, attributes as recommendedAttributes } from './recommended-whitelist';
|
|
|
+import {
|
|
|
+ attributes as recommendedAttributes,
|
|
|
+ tagNames as recommendedTagNames,
|
|
|
+} from './recommended-whitelist';
|
|
|
import * as addClass from './rehype-plugins/add-class';
|
|
|
import * as addInlineProperty from './rehype-plugins/add-inline-code-property';
|
|
|
import { relativeLinks } from './rehype-plugins/relative-links';
|
|
|
@@ -30,29 +33,34 @@ import * as emoji from './remark-plugins/emoji';
|
|
|
import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker';
|
|
|
import * as xsvToTable from './remark-plugins/xsv-to-table';
|
|
|
|
|
|
-
|
|
|
// import EasyGrid from './PreProcessor/EasyGrid';
|
|
|
|
|
|
-
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
const logger = loggerFactory('growi:services:renderer');
|
|
|
|
|
|
-
|
|
|
type SanitizePlugin = PluginTuple<[SanitizeOption]>;
|
|
|
|
|
|
-let currentInitializedSanitizeType: RehypeSanitizeType = RehypeSanitizeType.RECOMMENDED;
|
|
|
+let currentInitializedSanitizeType: RehypeSanitizeType =
|
|
|
+ RehypeSanitizeType.RECOMMENDED;
|
|
|
let commonSanitizeOption: SanitizeOption;
|
|
|
-export const getCommonSanitizeOption = (config:RendererConfig): SanitizeOption => {
|
|
|
- if (commonSanitizeOption == null || config.sanitizeType !== currentInitializedSanitizeType) {
|
|
|
+export const getCommonSanitizeOption = (
|
|
|
+ config: RendererConfig,
|
|
|
+): SanitizeOption => {
|
|
|
+ if (
|
|
|
+ commonSanitizeOption == null ||
|
|
|
+ config.sanitizeType !== currentInitializedSanitizeType
|
|
|
+ ) {
|
|
|
// initialize
|
|
|
commonSanitizeOption = deepmerge(
|
|
|
{
|
|
|
- tagNames: config.sanitizeType === RehypeSanitizeType.RECOMMENDED
|
|
|
- ? recommendedTagNames
|
|
|
- : config.customTagWhitelist ?? recommendedTagNames,
|
|
|
- attributes: config.sanitizeType === RehypeSanitizeType.RECOMMENDED
|
|
|
- ? recommendedAttributes
|
|
|
- : config.customAttrWhitelist ?? recommendedAttributes,
|
|
|
+ tagNames:
|
|
|
+ config.sanitizeType === RehypeSanitizeType.RECOMMENDED
|
|
|
+ ? recommendedTagNames
|
|
|
+ : (config.customTagWhitelist ?? recommendedTagNames),
|
|
|
+ attributes:
|
|
|
+ config.sanitizeType === RehypeSanitizeType.RECOMMENDED
|
|
|
+ ? recommendedAttributes
|
|
|
+ : (config.customAttrWhitelist ?? recommendedAttributes),
|
|
|
clobberPrefix: '', // remove clobber prefix
|
|
|
},
|
|
|
codeBlock.sanitizeOption,
|
|
|
@@ -64,8 +72,9 @@ export const getCommonSanitizeOption = (config:RendererConfig): SanitizeOption =
|
|
|
return commonSanitizeOption;
|
|
|
};
|
|
|
|
|
|
-
|
|
|
-const isSanitizePlugin = (pluggable: Pluggable): pluggable is SanitizePlugin => {
|
|
|
+const isSanitizePlugin = (
|
|
|
+ pluggable: Pluggable,
|
|
|
+): pluggable is SanitizePlugin => {
|
|
|
if (!Array.isArray(pluggable) || pluggable.length < 2) {
|
|
|
return false;
|
|
|
}
|
|
|
@@ -73,7 +82,10 @@ const isSanitizePlugin = (pluggable: Pluggable): pluggable is SanitizePlugin =>
|
|
|
return 'tagNames' in sanitizeOption && 'attributes' in sanitizeOption;
|
|
|
};
|
|
|
|
|
|
-const hasSanitizePlugin = (options: RendererOptions, shouldBeTheLastItem: boolean): boolean => {
|
|
|
+const hasSanitizePlugin = (
|
|
|
+ options: RendererOptions,
|
|
|
+ shouldBeTheLastItem: boolean,
|
|
|
+): boolean => {
|
|
|
const { rehypePlugins } = options;
|
|
|
if (rehypePlugins == null || rehypePlugins.length === 0) {
|
|
|
return false;
|
|
|
@@ -81,18 +93,25 @@ const hasSanitizePlugin = (options: RendererOptions, shouldBeTheLastItem: boolea
|
|
|
|
|
|
return shouldBeTheLastItem
|
|
|
? isSanitizePlugin(rehypePlugins.slice(-1)[0]) // evaluate the last one
|
|
|
- : rehypePlugins.some(rehypePlugin => isSanitizePlugin(rehypePlugin));
|
|
|
+ : rehypePlugins.some((rehypePlugin) => isSanitizePlugin(rehypePlugin));
|
|
|
};
|
|
|
|
|
|
-export const verifySanitizePlugin = (options: RendererOptions, shouldBeTheLastItem = true): void => {
|
|
|
+export const verifySanitizePlugin = (
|
|
|
+ options: RendererOptions,
|
|
|
+ shouldBeTheLastItem = true,
|
|
|
+): void => {
|
|
|
if (hasSanitizePlugin(options, shouldBeTheLastItem)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- throw new Error('The specified options does not have sanitize plugin in \'rehypePlugins\'');
|
|
|
+ throw new Error(
|
|
|
+ "The specified options does not have sanitize plugin in 'rehypePlugins'",
|
|
|
+ );
|
|
|
};
|
|
|
|
|
|
-export const generateCommonOptions = (pagePath: string|undefined): RendererOptions => {
|
|
|
+export const generateCommonOptions = (
|
|
|
+ pagePath: string | undefined,
|
|
|
+): RendererOptions => {
|
|
|
return {
|
|
|
remarkPlugins: [
|
|
|
gfm,
|
|
|
@@ -112,9 +131,12 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio
|
|
|
[relativeLinksByPukiwikiLikeLinker, { pagePath }],
|
|
|
[relativeLinks, { pagePath }],
|
|
|
raw,
|
|
|
- [addClass.rehypePlugin, {
|
|
|
- table: 'table table-bordered',
|
|
|
- }],
|
|
|
+ [
|
|
|
+ addClass.rehypePlugin,
|
|
|
+ {
|
|
|
+ table: 'table table-bordered',
|
|
|
+ },
|
|
|
+ ],
|
|
|
addInlineProperty.rehypePlugin,
|
|
|
],
|
|
|
components: {
|
|
|
@@ -124,21 +146,16 @@ export const generateCommonOptions = (pagePath: string|undefined): RendererOptio
|
|
|
};
|
|
|
};
|
|
|
|
|
|
-
|
|
|
export const generateSSRViewOptions = (
|
|
|
- config: RendererConfig,
|
|
|
- pagePath: string,
|
|
|
+ config: RendererConfig,
|
|
|
+ pagePath: string,
|
|
|
): RendererOptions => {
|
|
|
-
|
|
|
const options = generateCommonOptions(pagePath);
|
|
|
|
|
|
const { remarkPlugins, rehypePlugins } = options;
|
|
|
|
|
|
// add remark plugins
|
|
|
- remarkPlugins.push(
|
|
|
- math,
|
|
|
- xsvToTable.remarkPlugin,
|
|
|
- );
|
|
|
+ remarkPlugins.push(math, xsvToTable.remarkPlugin);
|
|
|
|
|
|
const isEnabledLinebreaks = config.isEnabledLinebreaks;
|
|
|
|
|
|
@@ -146,16 +163,13 @@ export const generateSSRViewOptions = (
|
|
|
remarkPlugins.push(breaks);
|
|
|
}
|
|
|
|
|
|
- const rehypeSanitizePlugin: Pluggable | (() => void) = config.isEnabledXssPrevention
|
|
|
- ? [sanitize, getCommonSanitizeOption(config)]
|
|
|
- : () => {};
|
|
|
+ const rehypeSanitizePlugin: Pluggable | (() => void) =
|
|
|
+ config.isEnabledXssPrevention
|
|
|
+ ? [sanitize, getCommonSanitizeOption(config)]
|
|
|
+ : () => {};
|
|
|
|
|
|
// add rehype plugins
|
|
|
- rehypePlugins.push(
|
|
|
- slug,
|
|
|
- rehypeSanitizePlugin,
|
|
|
- katex,
|
|
|
- );
|
|
|
+ rehypePlugins.push(slug, rehypeSanitizePlugin, katex);
|
|
|
|
|
|
// add components
|
|
|
// if (components != null) {
|