mirror of
https://github.com/nextcloud/server.git
synced 2026-04-05 09:06:35 -04:00
fix(app-store): Correctly render Markdown in app description
This seems to be broken by an update because the renderer now passes an object instead of multiple arguments to the render functions. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
parent
1f1760454f
commit
6e98faae91
3 changed files with 74 additions and 48 deletions
58
apps/settings/src/components/Markdown.cy.ts
Normal file
58
apps/settings/src/components/Markdown.cy.ts
Normal 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')
|
||||
})
|
||||
})
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ export default defineConfig({
|
|||
},
|
||||
|
||||
component: {
|
||||
specPattern: ['core/**/*.cy.ts', 'apps/**/*.cy.ts'],
|
||||
devServer: {
|
||||
framework: 'vue',
|
||||
bundler: 'webpack',
|
||||
|
|
|
|||
Loading…
Reference in a new issue