Skip to content

Commit

Permalink
feat: change custom csp in md2md mode
Browse files Browse the repository at this point in the history
  • Loading branch information
v8tenko committed Nov 11, 2024
1 parent 667893b commit 7ef5a5f
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 36 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"dependencies": {
"@diplodoc/client": "^3.1.6",
"@diplodoc/translation": "^1.4.3",
"csp-header": "^5.2.1",
"katex": "^0.16.9",
"shelljs": "0.8.5",
"threads": "1.7.0",
Expand Down
12 changes: 12 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ export const SINGLE_PAGE_DATA_FILENAME = 'single-page.json';
export const CUSTOM_STYLE = 'custom-style';
export const SEARCH_API = join(ASSETS_FOLDER, 'search', 'index.js');
export const SEARCH_LANGS = join(ASSETS_FOLDER, 'search', 'langs');
export const DEFAULT_CSP_SETTINGS: Record<string, string[]> = {
'default-src': ["'self'"],
'script-src': ["'self'", "'unsafe-inline'"],
'style-src': ["'self'", "'unsafe-inline'"],
'img-src': ["'self'", 'data:'],
'font-src': ["'self'", 'data:'],
'connect-src': ["'self'"],
'frame-src': ["'none'"],
'object-src': ["'none'"],
'base-uri': ["'self'"],
'form-action': ["'self'"],
};

export enum Stage {
NEW = 'new',
Expand Down
4 changes: 3 additions & 1 deletion src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ export interface PathData {
}

export type Resources = {
[key in ResourceType]?: string[];
[key in Exclude<ResourceType, 'csp'>]?: string[];
} & {
csp?: Record<string, string[]>[];
};

export type YandexCloudTranslateGlossaryPair = {
Expand Down
45 changes: 43 additions & 2 deletions src/pages/document.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import {join} from 'path';

import {BUNDLE_FOLDER, CARRIAGE_RETURN, CUSTOM_STYLE, RTL_LANGS} from '../constants';
import {
BUNDLE_FOLDER,
CARRIAGE_RETURN,
CUSTOM_STYLE,
DEFAULT_CSP_SETTINGS,
RTL_LANGS,
} from '../constants';
import {LeadingPage, Resources, TextItems, VarsMetadata} from '../models';
import {ArgvService, PluginService} from '../services';
import {getDepthPath} from '../utils';
Expand All @@ -9,6 +15,7 @@ import {DocInnerProps, DocPageData, render} from '@diplodoc/client/ssr';
import manifest from '@diplodoc/client/manifest';

import {escape} from 'html-escaper';
import {getCSP} from 'csp-header';

export interface TitleMeta {
title?: string;
Expand All @@ -24,7 +31,8 @@ export function generateStaticMarkup(
tocPath: string,
title: string,
): string {
const {style, script, metadata, ...restYamlConfigMeta} = (props.data.meta as Meta) || {};
/* @todo replace rest operator with proper unpacking */
const {style, script, csp, metadata, ...restYamlConfigMeta} = (props.data.meta as Meta) || {};
const resources = getResources({style, script});

const {staticContent} = ArgvService.getConfig();
Expand All @@ -41,6 +49,7 @@ export function generateStaticMarkup(
<meta charset="utf-8">
<base href="${base}" />
${getMetadata(metadata, restYamlConfigMeta)}
${generateCSP(csp)}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title}</title>
<style type="text/css">
Expand Down Expand Up @@ -103,6 +112,38 @@ function getMetadata(metadata: VarsMetadata | undefined, restMeta: LeadingPage['
return result;
}

function generateCSP(csp?: Record<string, string[]>[]) {
if (!csp) {
return '';
}

const collected = [DEFAULT_CSP_SETTINGS].concat(csp).reduce((acc, curr) => {
if (!curr || typeof curr !== 'object') {
return acc;
}

const entries = Object.entries(curr);

for (const [cspRule, value] of entries) {
acc[cspRule] ??= [];

const flat = Array.isArray(value) ? value : [value];

flat.forEach((cspValue) => {
if (!acc[cspRule].includes(cspValue)) {
acc[cspRule].push(cspValue);
}
});
}

return acc;
}, {});

const stringified = getCSP({directives: collected});

return `<meta http-equiv="Content-Security-Policy" content="${stringified}">`;
}

function getResources({style, script}: Resources) {
const resourcesTags: string[] = [];

Expand Down
10 changes: 7 additions & 3 deletions src/steps/processAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,13 @@ function processAssetsMdRun({args, tmpOutputFolder}) {
const resourcePaths: string[] = [];

// collect paths of all resources
Object.keys(resources).forEach((type) =>
resources[type as keyof Resources]?.forEach((path: string) => resourcePaths.push(path)),
);
Object.keys(resources).forEach((type) => {
if (type === 'csp') {
return;
}

resources[type as keyof Resources]?.forEach((path: string) => resourcePaths.push(path));
});

//copy resources
copyFiles(args.input, tmpOutputFolder, resourcePaths);
Expand Down
24 changes: 12 additions & 12 deletions tests/e2e/__snapshots__/load-custom-resources.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ exports[`Allow load custom resources md2html single page with custom resources:
<meta name="noIndex"
content="true"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -136,8 +136,8 @@ exports[`Allow load custom resources md2html single page with custom resources:
<meta name="yfm"
content="builder"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -203,8 +203,8 @@ exports[`Allow load custom resources md2html single page with custom resources:
<head>
<meta charset="utf-8">
<base href="../">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -400,8 +400,8 @@ exports[`Allow load custom resources md2html with custom resources: index.html 1
<meta name="noIndex"
content="true"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -468,8 +468,8 @@ exports[`Allow load custom resources md2html with custom resources: page.html 1`
<meta name="yfm"
content="builder"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -535,8 +535,8 @@ exports[`Allow load custom resources md2html with custom resources: project/conf
<head>
<meta charset="utf-8">
<base href="../">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down
12 changes: 6 additions & 6 deletions tests/e2e/__snapshots__/metadata.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ exports[`Allow load custom resources md2html with metadata: index.html 1`] = `
<meta name="noIndex"
content="true"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -136,8 +136,8 @@ exports[`Allow load custom resources md2html with metadata: page.html 1`] = `
<meta name="yfm-config"
content="config test"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -205,8 +205,8 @@ exports[`Allow load custom resources md2html with metadata: project/config.html
<meta name="yfm-config"
content="config test"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down
24 changes: 12 additions & 12 deletions tests/e2e/__snapshots__/rtl.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<head>
<meta charset="utf-8">
<base href="./">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -114,8 +114,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<head>
<meta charset="utf-8">
<base href="./">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -176,8 +176,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<head>
<meta charset="utf-8">
<base href="../">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -234,8 +234,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<head>
<meta charset="utf-8">
<base href="../">
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -302,8 +302,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<meta name="noIndex"
content="true"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down Expand Up @@ -363,8 +363,8 @@ exports[`Generate html document with correct lang and dir attributes. Load corre
<meta name="yfm"
content="builder"
>
<meta name="csp"
content
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-src 'none'; object-src 'none'; base-uri 'self'; form-action 'self';"
>
<meta name="viewport"
content="width=device-width, initial-scale=1.0"
Expand Down

0 comments on commit 7ef5a5f

Please sign in to comment.