Skip to content

Mixed quotes in component attributes breaks nesting #96

@jschilli

Description

@jschilli

Version

module: 3.6.0
nuxt: 3..16.2

Nuxt configuration

mode:

  • universal
  • spa

Nuxt configuration

Reproduction

⚠️ without a minimal reproduction we wont be able to look into your issue

Link:

What is expected?

nested components with JSON attributes get escaped and break nesting of the containing components

What is actually happening?

When component attributes contain nested JSON with mixed quotes (e.g., data="[{"name": "value"}]"), the parser breaks completely. The component is parsed as a paragraph with fragmented text, and the
component structure is destroyed.

Steps to reproduce

  1. Create a markdown file with nested components
  2. Add attributes containing nested JSON with escaped quotes
  3. Parse with remark-mdc
  4. Observe that the component structure breaks

e.g.

::tabs
  ::tab-item{label="Tab 1"}
    ::chart{data="[{\"name\": \"John\", \"values\": [1,2,3]}]" config='{"type": "bar", "options": {"responsive": true}}'}
    ::
  ::
  ::tab-item{label="Tab 2"}
    Content 2
  ::
::

Additional information

Minimal test case demonstrating the issue:

  import { describe, expect, test } from 'vitest'
  import { runMarkdownTests } from './utils'

  describe('Nested JSON Attributes Issue', () => {
    runMarkdownTests({
      'nested-json-mixed-quotes-parsing-failure': {
        markdown: `:::tabs
  ::::tab-item{label="Tab 1"}
  :::::chart{data="[{\"name\": \"John\", \"values\": [1,2,3]}]" config='{"type": "bar", "options": {"responsive": true}}'}
  :::::
  ::::
  ::::tab-item{label="Tab 2"}
  Content 2
  ::::
  :::`,
        extra(_, ast) {
          const tabs = ast.children[0]
          expect(tabs.type).toBe('containerComponent')
          expect(tabs.name).toBe('tabs')

          const tabItems = tabs.children.filter(child => child.name === 'tab-item')
          expect(tabItems).toHaveLength(2) // FAILS: Only finds 1 tab

          const chartComponent = tabItems[0].children.find(child => child.name === 'chart')
          expect(chartComponent).toBeDefined() // FAILS: Chart not found
          expect(chartComponent.type).toBe('containerComponent') // FAILS: Is paragraph instead
        },
      }
    })
  })

Working example (without nested JSON):

:::tabs
::::tab-item{label="Tab 1"}
:::::chart{data="[]" title="Simple"}
:::::
::::
::::tab-item{label="Tab 2"}
Content 2
::::
:::

###Failing example (with nested JSON):

:::tabs
::::tab-item{label="Tab 1"}
:::::chart{data="[{\"name\": \"John\", \"values\": [1,2,3]}]" config='{"type": "bar"}'}
:::::
::::
::::tab-item{label="Tab 2"}
Content 2
::::
:::

Workaround using YAML frontmatter:

:::tabs
::::tab-item{label="Tab 1"}
:::::chart
---
data: '[{"name": "John", "values": [1,2,3}]'
config: '{"type": "bar"}'
---
:::::
::::
::::tab-item{label="Tab 2"}
Content 2
::::
:::

Root cause:

The parser encounters " in the JSON and incorrectly interprets it as the closing quote for the attribute value, causing premature exit from attribute parsing.

Other

I took a quick swing at a fix but ran into some regressions - putting this up now with workaround so that other's encountering the same have issue have a workaround

Checklist

  • [N/A] I have tested with the latest Nuxt version and the issue still occurs
  • I have tested with the latest module version and the issue still occurs
  • I have searched the issue tracker and this issue hasn't been reported yet

What is actually happening?

Performance analysis?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions