@tak-ps/vue-tabler 4.20.0 → 4.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ on:
7
7
 
8
8
  permissions:
9
9
  id-token: write # Required for OIDC
10
- contents: read
10
+ contents: write
11
11
 
12
12
  jobs:
13
13
  build:
@@ -31,3 +31,11 @@ jobs:
31
31
 
32
32
  - name: Publish package
33
33
  run: npm publish --provenance --access public
34
+
35
+ - name: Generate CHANGELOG
36
+ run: grep -Pzo "### ${{ github.ref_name }}(?s).*?(?=###)" CHANGELOG.md > RELEASE
37
+
38
+ - name: Github Release
39
+ uses: softprops/action-gh-release@v2
40
+ with:
41
+ body_path: RELEASE
package/CHANGELOG.md CHANGED
@@ -9,6 +9,23 @@
9
9
  - :tada: when adding new features
10
10
 
11
11
  ## Version History
12
+
13
+ ### v4.23.1
14
+
15
+ - :bug: Add sanitize helper fn
16
+
17
+ ### v4.23.0
18
+
19
+ - :pencil2: Add GH Release system
20
+
21
+ ### v4.22.0
22
+
23
+ - :rocket: Migrate to more modern `marked` instead of `showdown`
24
+
25
+ ### v4.20.0
26
+
27
+ - :bug: Fix hover state
28
+
12
29
  ### v4.19.1
13
30
 
14
31
  - :bug: Fix `TablerBorder` `tools` slot not appearing on hover when scoped CSS selector matched the wrong element
package/README.md CHANGED
@@ -96,7 +96,8 @@ import { TablerButton, TablerAlert } from '@tak-ps/vue-tabler';
96
96
  This library relies on the following core dependencies:
97
97
  - [Vue 3](https://vuejs.org/)
98
98
  - [@tabler/icons-vue](https://www.npmjs.com/package/@tabler/icons-vue)
99
- - [showdown](https://www.npmjs.com/package/showdown) (for Markdown rendering)
99
+ - [marked](https://www.npmjs.com/package/marked) (for Markdown rendering)
100
+ - [DOMPurify](https://www.npmjs.com/package/dompurify) (for HTML sanitization)
100
101
 
101
102
  ## 📄 License
102
103
 
@@ -1,14 +1,16 @@
1
1
  <template>
2
+ <!-- eslint-disable vue/no-v-html -->
2
3
  <div
3
4
  :style='autowrap ? `white-space: pre-wrap;` : ``'
4
5
  v-html='html'
5
6
  />
7
+ <!-- eslint-enable vue/no-v-html -->
6
8
  </template>
7
9
 
8
10
  <script setup lang="ts">
9
11
  import { computed } from 'vue'
10
- // @ts-expect-error: showdown types not available
11
- import showdown from 'showdown'
12
+ import DOMPurify from 'dompurify'
13
+ import { marked } from 'marked'
12
14
 
13
15
  export interface MarkdownProps {
14
16
  markdown: string;
@@ -19,12 +21,20 @@ const props = withDefaults(defineProps<MarkdownProps>(), {
19
21
  autowrap: true
20
22
  });
21
23
 
24
+ function sanitizeHtml(html: string): string {
25
+ return DOMPurify.sanitize(html, {
26
+ USE_PROFILES: {
27
+ html: true
28
+ }
29
+ })
30
+ }
31
+
22
32
  const html = computed(() => {
23
- const converter = new showdown.Converter({
24
- tables: true,
25
- tasklists: true,
26
- emoji: true
33
+ const rendered = marked.parse(props.markdown, {
34
+ async: false,
35
+ gfm: true
27
36
  })
28
- return converter.makeHtml(props.markdown)
37
+
38
+ return sanitizeHtml(rendered)
29
39
  })
30
40
  </script>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tak-ps/vue-tabler",
3
3
  "type": "module",
4
- "version": "4.20.0",
4
+ "version": "4.23.1",
5
5
  "lib": "lib.ts",
6
6
  "main": "lib.ts",
7
7
  "module": "lib.ts",
@@ -27,7 +27,8 @@
27
27
  "homepage": "https://github.com/tak-ps/vue-tabler#readme",
28
28
  "dependencies": {
29
29
  "@tabler/icons-vue": "^3.0.0",
30
- "showdown": "^2.1.0"
30
+ "dompurify": "^3.4.1",
31
+ "marked": "^18.0.2"
31
32
  },
32
33
  "peerDependencies": {
33
34
  "vue": "^3.5.12",
@@ -0,0 +1,30 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import Markdown from '../components/Markdown.vue'
4
+
5
+ describe('TablerMarkdown', () => {
6
+ it('renders markdown and basic HTML', () => {
7
+ const wrapper = mount(Markdown, {
8
+ props: {
9
+ markdown: '# Title\n\n<div class="note">Allowed HTML</div>'
10
+ }
11
+ })
12
+
13
+ expect(wrapper.html()).toContain('<h1>Title</h1>')
14
+ expect(wrapper.html()).toContain('<div class="note">Allowed HTML</div>')
15
+ })
16
+
17
+ it('sanitizes unsafe HTML before rendering', () => {
18
+ const wrapper = mount(Markdown, {
19
+ props: {
20
+ markdown: '<img src="x" onerror="alert(1)"><script>alert(2)</script><a href="javascript:alert(3)">bad</a>'
21
+ }
22
+ })
23
+
24
+ expect(wrapper.html()).toContain('<img src="x">')
25
+ expect(wrapper.html()).toContain('<a>bad</a>')
26
+ expect(wrapper.html()).not.toContain('onerror')
27
+ expect(wrapper.html()).not.toContain('<script>')
28
+ expect(wrapper.html()).not.toContain('javascript:')
29
+ })
30
+ })