mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
fix(editor): Render checkboxes in markdown (#9549)
This commit is contained in:
parent
a221215b87
commit
47d774100b
|
@ -51,3 +51,18 @@ Markdown.args = {
|
|||
},
|
||||
],
|
||||
};
|
||||
|
||||
const TemplateWithCheckboxes: StoryFn = (args, { argTypes }) => ({
|
||||
setup: () => ({ args }),
|
||||
props: Object.keys(argTypes),
|
||||
components: {
|
||||
N8nMarkdown,
|
||||
},
|
||||
template: '<n8n-markdown v-bind="args"></n8n-markdown>',
|
||||
});
|
||||
|
||||
export const WithCheckboxes = TemplateWithCheckboxes.bind({});
|
||||
WithCheckboxes.args = {
|
||||
content: '__TODO__\n- [ ] Buy milk\n- [X] Buy socks\n',
|
||||
loading: false,
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ import Markdown from 'markdown-it';
|
|||
import markdownLink from 'markdown-it-link-attributes';
|
||||
import markdownEmoji from 'markdown-it-emoji';
|
||||
import markdownTaskLists from 'markdown-it-task-lists';
|
||||
import xss, { friendlyAttrValue } from 'xss';
|
||||
import xss, { friendlyAttrValue, whiteList } from 'xss';
|
||||
|
||||
import N8nLoading from '../N8nLoading';
|
||||
import { escapeMarkdown } from '../../utils/markdown';
|
||||
|
@ -72,6 +72,7 @@ const props = withDefaults(defineProps<MarkdownProps>(), {
|
|||
},
|
||||
},
|
||||
tasklists: {
|
||||
enabled: true,
|
||||
label: true,
|
||||
labelAfter: true,
|
||||
},
|
||||
|
@ -84,6 +85,11 @@ const md = new Markdown(options.markdown)
|
|||
.use(markdownEmoji)
|
||||
.use(markdownTaskLists, options.tasklists);
|
||||
|
||||
const xssWhiteList = {
|
||||
...whiteList,
|
||||
label: ['class', 'for'],
|
||||
};
|
||||
|
||||
const htmlContent = computed(() => {
|
||||
if (!props.content) {
|
||||
return '';
|
||||
|
@ -130,6 +136,13 @@ const htmlContent = computed(() => {
|
|||
}
|
||||
// return nothing, keep tag
|
||||
},
|
||||
onIgnoreTag(tag, tagHTML) {
|
||||
// Allow checkboxes
|
||||
if (tag === 'input' && tagHTML.includes('type="checkbox"')) {
|
||||
return tagHTML;
|
||||
}
|
||||
},
|
||||
whiteList: xssWhiteList,
|
||||
});
|
||||
|
||||
return safeHtml;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import { render } from '@testing-library/vue';
|
||||
import N8nMarkdown from '../Markdown.vue';
|
||||
|
||||
describe('components', () => {
|
||||
describe('N8nMarkdown', () => {
|
||||
it('should render unchecked checkboxes', () => {
|
||||
const wrapper = render(N8nMarkdown, {
|
||||
props: {
|
||||
content: '__TODO__\n- [ ] Buy milk\n- [ ] Buy socks\n',
|
||||
},
|
||||
});
|
||||
const checkboxes = wrapper.getAllByRole('checkbox');
|
||||
expect(checkboxes).toHaveLength(2);
|
||||
checkboxes.forEach((checkbox) => {
|
||||
expect(checkbox).not.toBeChecked();
|
||||
});
|
||||
});
|
||||
it('should render checked checkboxes', () => {
|
||||
const wrapper = render(N8nMarkdown, {
|
||||
props: {
|
||||
content: '__TODO__\n- [X] Buy milk\n- [X] Buy socks\n',
|
||||
},
|
||||
});
|
||||
const checkboxes = wrapper.getAllByRole('checkbox');
|
||||
expect(checkboxes).toHaveLength(2);
|
||||
checkboxes.forEach((checkbox) => {
|
||||
expect(checkbox).toBeChecked();
|
||||
});
|
||||
});
|
||||
it('should render inputs as plain text', () => {
|
||||
const wrapper = render(N8nMarkdown, {
|
||||
props: {
|
||||
content:
|
||||
'__TODO__\n- [X] Buy milk\n- <input type="text" data-testid="text-input" value="Something"/>\n',
|
||||
},
|
||||
});
|
||||
const checkboxes = wrapper.getAllByRole('checkbox');
|
||||
expect(checkboxes).toHaveLength(1);
|
||||
expect(wrapper.queryByTestId('text-input')).toBeNull();
|
||||
expect(wrapper.html()).toContain(
|
||||
'<input type=“text” data-testid=“text-input” value=“Something”/>',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue