Skip to content

feat: propagate policies documentation type to gv-documentation #690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const path = require('path');

module.exports = {
features: {
previewCsfV3: true,
},
stories: ['../stories/**/*.stories.@(js|ts|mdx)', '../src/**/*.stories.@(js|ts|mdx)'],

addons: ['@storybook/addon-essentials', '@storybook/addon-a11y'],

babel: async (options) => {
Expand All @@ -15,4 +16,19 @@ module.exports = {
});
return options;
},

webpackFinal: async (config) => {
config.module.rules.push({
test: /\.js$/,
include: [path.resolve(__dirname, '../node_modules/marked')],
use: {
loader: require.resolve('babel-loader'),
options: {
presets: [require.resolve('@babel/preset-env')],
},
},
});

return config;
},
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
"lint-staged": "12.5.0",
"lit-html": "2.6.1",
"markdown-it": "12.3.2",
"marked": "15.0.12",
"node-static": "0.7.11",
"nodemon": "2.0.21",
"pascal-case": "3.1.2",
Expand Down
73 changes: 35 additions & 38 deletions src/lib/text-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import DOMPurify from 'dompurify';
import { marked } from 'marked';

export async function loadAsciiDoctor() {
let _gvAsciidoctor = window._gvAsciidoctor;
Expand All @@ -34,44 +35,40 @@ export async function loadAsciiDoctor() {
return _gvAsciidoctor;
}

export function toDom(text, type = 'adoc', small = false) {
return loadAsciiDoctor().then((asciidoctor) => {
if (text) {
let innerHTML = '';
if (type === 'adoc') {
const htmlContent = asciidoctor
.convert(text, {
attributes: {
showtitle: true,
'source-highlighter': 'highlightjs-ext',
},
})
// Replace href links to include potential parts of the URL that can be set by Angular router or
// any other routing framework. By default, href will have the following format:
// href="[SERVER_BASE]/#a_link" i.e. href="https://apim-master-portal.cloud.gravitee.io/#a_link"
.replace(/href="#/g, `href="${window.location.href}#`);
// Sanitize HTML content to avoid XSS attacks
innerHTML = DOMPurify.sanitize(htmlContent);
} else {
throw new Error(`Library not found for type : '${type}' | ${text}`);
}
export async function toDom(text, type = 'adoc', small = false) {
if (!text) return;

const element = document.createElement('div');
element.innerHTML = innerHTML;
element.style.width = '100%';
element.style.maxWidth = '1000px';
element.style.margin = '0 auto';
element.classList.add('markdown-body');
if (small) {
element.classList.add('small');
}
const titleElement = element.querySelector('h1');
let title = '';
if (titleElement) {
title = titleElement.textContent;
}
let innerHTML = '';
if (type === 'adoc') {
const asciidoctor = await loadAsciiDoctor();
const htmlContent = asciidoctor
.convert(text, {
attributes: {
showtitle: true,
'source-highlighter': 'highlightjs-ext',
},
})
.replace(/href="#/g, `href="${window.location.href}#`);
innerHTML = DOMPurify.sanitize(htmlContent);
} else if (type === 'md' || type === 'markdown') {
const htmlContent = marked.parse(text).replace(/href="#/g, `href="${window.location.href}#`);
innerHTML = DOMPurify.sanitize(htmlContent);
} else {
throw new Error(`Unsupported documentation type: '${type}'`);
}

const element = document.createElement('div');
element.innerHTML = innerHTML;
element.style.width = '100%';
element.style.maxWidth = '1000px';
element.style.margin = '5px auto';
element.classList.add('markdown-body');
if (small) {
element.classList.add('small');
}

const titleElement = element.querySelector('h1');
const title = titleElement ? titleElement.textContent : '';

return { title, element };
}
});
return { title, element };
}
4 changes: 3 additions & 1 deletion src/organisms/gv-documentation/gv-documentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ export class GvDocumentation extends LitElement {

constructor() {
super();
this.type = 'adoc';
if (!this.type) {
this.type = 'adoc';
}
}

_onCloseDocumentation() {
Expand Down
5 changes: 5 additions & 0 deletions src/organisms/gv-documentation/gv-documentation.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import './gv-documentation';
import { policyMockReadme } from '../../../testing/resources/adoc/policy-mock-readme';
import { makeStory, storyWait } from '../../../testing/lib/make-story';
import { policyCalloutReadme } from '../../../testing/resources/md/policy-mock-readme';

export default {
title: 'Organisms/gv-documentation',
Expand Down Expand Up @@ -66,6 +67,10 @@ export const Async = makeStory(conf, {
],
});

export const MarkdownDoc = makeStory(conf, {
items: [{ text: policyCalloutReadme, type: 'md' }],
});

const maliciousAsciidoc = '```test"><img src=x onerror=alert(1)></img>';
export const SanitizedMaliciousDoc = makeStory(conf, {
items: [{ text: maliciousAsciidoc }],
Expand Down
2 changes: 2 additions & 0 deletions src/policy-studio/gv-design/gv-design.js
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ export class GvDesign extends KeyboardElement(LitElement) {
<gv-documentation
.text="${this.documentation.content}"
.image="${this.documentation.image}"
.type="${this.documentation.type}"
?disabled="${this._currentAskConfirmation}"
@gv-documentation:close="${this._onCloseDocumentation}"
></gv-documentation>
Expand All @@ -897,6 +898,7 @@ export class GvDesign extends KeyboardElement(LitElement) {
return html`<gv-documentation
.text="${this.documentation.content}"
.image="${this.documentation.image}"
.type="${this.documentation.type}"
?disabled="${this._currentAskConfirmation}"
@gv-documentation:close="${this._onCloseDocumentation}"
></gv-documentation>`;
Expand Down
42 changes: 42 additions & 0 deletions testing/resources/md/policy-mock-readme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2021 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable no-useless-escape */
export const policyCalloutReadme = `= Callout Policy
## Overview
You can use the \`callout-http\` policy to invoke an HTTP(S) URL and place a subset or all of the content in
one or more variables of the request execution context.

This can be useful if you need some data from an external service and want to inject it during request
processing.

The result of the callout is placed in a variable called \`calloutResponse\` and is only available during policy
execution. If no variable is configured the result of the callout is no longer available.





## Errors
You can use the response template feature to override the default response provided by the policy.
These templates are be defined at the API level, in "Entrypoint" section for V4 Apis, or in "Response Templates" for V2 APIs.

The error keys sent by this policy are as follows:

| Key |
| --- |
| CALLOUT_EXIT_ON_ERROR |
| CALLOUT_HTTP_ERROR |
`;
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4119,6 +4119,7 @@ __metadata:
lit: ^2.0.2
lit-html: 2.6.1
markdown-it: 12.3.2
marked: 15.0.12
node-static: 0.7.11
nodemon: 2.0.21
object-path: ^0.11.8
Expand Down Expand Up @@ -17141,6 +17142,15 @@ __metadata:
languageName: node
linkType: hard

"marked@npm:15.0.12":
version: 15.0.12
resolution: "marked@npm:15.0.12"
bin:
marked: bin/marked.js
checksum: 2ac72fc0bc7ecb47de246e396c7054d311f55379957e4e01796c12d196cb84480e8d53e54948f957a078f9166692fea8b0309fc597f26f855573e7ba5c1ec7eb
languageName: node
linkType: hard

"marked@npm:^2.0.0":
version: 2.1.3
resolution: "marked@npm:2.1.3"
Expand Down
Loading