From 5f05818e0e44683ce033110838145aba061f213b Mon Sep 17 00:00:00 2001 From: nobkd <44443899+nobkd@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:47:01 +0100 Subject: [PATCH] merge and deduplicate class names --- packages/nuemark/src/parse-tag.js | 12 ++++++++---- packages/nuemark/test/block.test.js | 6 ++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/nuemark/src/parse-tag.js b/packages/nuemark/src/parse-tag.js index d933d98d..6f8e866b 100644 --- a/packages/nuemark/src/parse-tag.js +++ b/packages/nuemark/src/parse-tag.js @@ -10,9 +10,11 @@ export function parseTag(input) { const specs = strings.filter((s, i) => !i || s.match(/^[#|.]/)).join('') const attribs = strings.filter(s => !specs.includes(s)) const self = { ...parseSpecs(specs), data: {} } - + const classes = new Set((self.attr?.class || '').split(' ')) function set(key, val) { + if (key == 'class') return val.split(' ').forEach(v => classes.add(v)) + const ctx = ATTR.includes(key) || key.startsWith('data-') ? 'attr' : 'data' self[ctx][key] = val } @@ -30,6 +32,8 @@ export function parseTag(input) { else set('_', getValue(key) || key) } + if (classes.size) self.attr.class = [...classes].join(' ') + return self } @@ -76,9 +80,9 @@ export function parseAttr(str) { const attr = {} // classes - const classes = [] - str.replace(/\.([\w\-]+)/g, (_, el) => classes.push(el)) - if (classes[0]) attr.class = classes.join(' ') + const classes = new Set() + str.replace(/\.([\w\-]+)/g, (_, el) => classes.add(el)) + if (classes.size) attr.class = [...classes].join(' ') // id str.replace(/#([\w\-]+)/, (_, el) => attr.id = el) diff --git a/packages/nuemark/test/block.test.js b/packages/nuemark/test/block.test.js index be302ace..bd43c492 100644 --- a/packages/nuemark/test/block.test.js +++ b/packages/nuemark/test/block.test.js @@ -233,6 +233,12 @@ test('complex tag data', () => { expect(comp.data).toEqual({ world: true, size: 10, foo: "bar", }) }) +test('duplicate tag classes', () => { + const { blocks } = parseBlocks(['[hello.c.c.bar class="foo bar" world]']) + expect(blocks[0].attr.class).toBe('c bar foo') + expect(blocks[0].data).toEqual({ world: true }) +}) + test('escaping', () => { const html = renderLines([ '\\[code]', '',