Merge pull request #48852 from nextcloud/fix/app-store-markdown

fix(app-store): Correctly render Markdown in app description
This commit is contained in:
Ferdinand Thiessen 2024-10-23 19:51:47 +02:00 committed by GitHub
commit 8bdf8bc7f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 80 additions and 54 deletions

View file

@ -0,0 +1,58 @@
/*!
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Markdown from './Markdown.vue'
describe('Markdown component', () => {
it('renders links', () => {
cy.mount(Markdown, {
propsData: {
text: 'This is [a link](http://example.com)!',
},
})
cy.contains('This is')
.find('a')
.should('exist')
.and('have.attr', 'href', 'http://example.com')
.and('contain.text', 'a link')
})
it('renders headings', () => {
cy.mount(Markdown, {
propsData: {
text: '# level 1\nText\n## level 2\nText\n### level 3\nText\n#### level 4\nText\n##### level 5\nText\n###### level 6\nText\n',
},
})
for (let level = 1; level <= 6; level++) {
cy.contains(`h${level}`, `level ${level}`)
.should('be.visible')
}
})
it('can limit headings', () => {
cy.mount(Markdown, {
propsData: {
text: '# level 1\nText\n## level 2\nText\n### level 3\nText\n#### level 4\nText\n##### level 5\nText\n###### level 6\nText\n',
minHeading: 4,
},
})
cy.get('h1').should('not.exist')
cy.get('h2').should('not.exist')
cy.get('h3').should('not.exist')
cy.get('h4')
.should('exist')
.and('contain.text', 'level 1')
cy.get('h5')
.should('exist')
.and('contain.text', 'level 2')
cy.contains('h6', 'level 3').should('exist')
cy.contains('h6', 'level 4').should('exist')
cy.contains('h6', 'level 5').should('exist')
cy.contains('h6', 'level 6').should('exist')
})
})

View file

@ -27,7 +27,7 @@ export default {
computed: {
renderMarkdown() {
const renderer = new marked.Renderer()
renderer.link = function(href, title, text) {
renderer.link = function({ href, title, text }) {
let prot
try {
prot = decodeURIComponent(unescape(href))
@ -48,18 +48,18 @@ export default {
out += '>' + text + '</a>'
return out
}
renderer.heading = (text, level) => {
level = Math.min(6, level + (this.minHeading - 1))
return `<h${level}>${text}</h${level}>`
renderer.heading = ({ text, depth }) => {
depth = Math.min(6, depth + (this.minHeading - 1))
return `<h${depth}>${text}</h${depth}>`
}
renderer.image = function(href, title, text) {
renderer.image = ({ title, text }) => {
if (text) {
return text
}
return title
}
renderer.blockquote = function(quote) {
return quote
renderer.blockquote = ({ text }) => {
return `<blockquote>${text}</blockquote>`
}
return dompurify.sanitize(
marked(this.text.trim(), {
@ -100,45 +100,13 @@ export default {
</script>
<style scoped lang="scss">
.settings-markdown::v-deep {
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 600;
line-height: 120%;
margin-top: 24px;
margin-bottom: 12px;
color: var(--color-main-text);
}
h1 {
font-size: 36px;
margin-top: 48px;
}
h2 {
font-size: 28px;
margin-top: 48px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 21px;
}
h5 {
font-size: 17px;
}
h6 {
font-size: var(--default-font-size);
.settings-markdown::v-deep {
a {
text-decoration: underline;
&::after {
content: '↗';
padding-inline: calc(var(--default-grid-baseline) / 2);
}
}
pre {
@ -183,6 +151,5 @@ export default {
color: var(--color-text-maxcontrast);
margin-inline: 0;
}
}
}
</style>

View file

@ -123,6 +123,7 @@ export default defineConfig({
},
component: {
specPattern: ['core/**/*.cy.ts', 'apps/**/*.cy.ts'],
devServer: {
framework: 'vue',
bundler: 'webpack',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long