Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portable Text: Nested lists / bullets render wrong HTML #690

Open
3 tasks done
marco-land opened this issue Feb 23, 2023 · 7 comments
Open
3 tasks done

Portable Text: Nested lists / bullets render wrong HTML #690

marco-land opened this issue Feb 23, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@marco-land
Copy link

Version

module: 1.6.0
nuxt: 3.2.2

What is expected?

Nested lists HTML format such as

<ul>
  <li>Bullet
    <ul>
      <li>Bullet 2</li>
    </ul>
  </li>
</ul>

What is actually happening?

<ul>
  <li>Bullet</li>
  <li>
    <ul>
      <li>Bullet 2</li>
    </ul>
  </li>
</ul>

Steps to reproduce

Standard blocks with list markDefs

Additional information

Checklist

  • 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
@marco-land marco-land added the bug Something isn't working label Feb 23, 2023
@wojtekpiskorz
Copy link

Confirmed I have the same issue.

@danielroe
Copy link
Collaborator

Would you be able to provide some portable text that renders wrongly? 🙏

@wojtekpiskorz
Copy link

documentFile.ts

 defineField({
      name: 'tableOfContent',
      title: 'Table of Content',
      type: 'blockContent',
      hidden: ({ document }) => !document?.isGuidebook,
      description: 'The table of content for the guidebook',
    }),

blockContent.ts is a default one from sanity blog template

import { defineType, defineArrayMember } from 'sanity'

/**
 * This is the schema definition for the rich text fields used for
 * for this blog studio. When you import it in schemas.js it can be
 * reused in other parts of the studio with:
 *  {
 *    name: 'someName',
 *    title: 'Some title',
 *    type: 'blockContent'
 *  }
 */
export default defineType({
  title: 'Block Content',
  name: 'blockContent',
  type: 'array',
  of: [
    defineArrayMember({
      title: 'Block',
      type: 'block',
      // Styles let you set what your user can mark up blocks with. These
      // correspond with HTML tags, but you can set any title or value
      // you want and decide how you want to deal with it where you want to
      // use your content.
      styles: [
        { title: 'Normal', value: 'normal' },
        { title: 'H1', value: 'h1' },
        { title: 'H2', value: 'h2' },
        { title: 'H3', value: 'h3' },
        { title: 'H4', value: 'h4' },
        { title: 'Quote', value: 'blockquote' },
      ],
      lists: [{ title: 'Bullet', value: 'bullet' }, { title: 'Number', value: 'number' }],
      // Marks let you mark up inline text in the block editor.
      marks: {
        // Decorators usually describe a single property – e.g. a typographic
        // preference or highlighting by editors.
        decorators: [
          { title: 'Strong', value: 'strong' },
          { title: 'Emphasis', value: 'em' },
        ],
        // Annotations can be any object structure – e.g. a link or a footnote.
        annotations: [
          {
            title: 'URL',
            name: 'link',
            type: 'object',
            fields: [
              {
                title: 'URL',
                name: 'href',
                type: 'url',
              },
            ],
          },
        ],
      },
    }),
    // You can add additional types here. Note that you can't use
    // primitive types such as 'string' and 'number' in the same array
    // as a block type.
    defineArrayMember({
      type: 'image',
      options: {
        hotspot: true,
      },
      fields: [
        {
          name: 'alt',
          title: 'Alternative text',
          type: 'string',
          options: {
            isHighlighted: true,
          },
        },
      ],
    }),
  ],
})

If I just try to copy-paste from sanity studio body input here it removes all list and it's a plain paragraphs:

Wstęp: o mnie

Przygotowanie do zmiany administratora

Wybór właściwego przewodnika

Metoda 5 kroków

Forma zarządzania nieruchomością wspólną. Dwa rodzaje zarządu we Wspólnocie Mieszkaniowej – od tego trzeba zacząć?

(...)

  • *So Its hard to 1:1 give you exactly the same thing here **
    So here's a 1 min video on the subject :)

[1 min video from my sanity studio](https://komododecks.com/recordings/BQooB3WJBWHe832Niq2n)

Copy link
Collaborator

I think you should be able to copy-paste the JSON by inspecting your document within the studio.

@wojtekpiskorz
Copy link

"tableOfContent": [
{
"_key": "5d4d93dc892d",
"_type": "block",
"children": [
{
"_key": "df7b8b9c4e310",
"_type": "span",
"marks": [],
"text": "Wstęp: o mnie"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "907a62afe950",
"_type": "block",
"children": [
{
"_key": "62adc9e9b87b0",
"_type": "span",
"marks": [],
"text": "Przygotowanie do zmiany administratora"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "c70b758344cb",
"_type": "block",
"children": [
{
"_key": "ef692a14b7310",
"_type": "span",
"marks": [],
"text": "Wybór właściwego przewodnika"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "9df9bf2e5591",
"_type": "block",
"children": [
{
"_key": "e4671c062ed4",
"_type": "span",
"marks": [],
"text": "Metoda 5 kroków"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "de691db0d765",
"_type": "block",
"children": [
{
"_key": "5edd66833aee",
"_type": "span",
"marks": [],
"text": "Forma zarządzania nieruchomością wspólną. Dwa rodzaje zarządu we Wspólnocie Mieszkaniowej – od tego trzeba zacząć?"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "e1b1f2d03e46",
"_type": "block",
"children": [
{
"_key": "ce79d7745b100",
"_type": "span",
"marks": [],
"text": "Zmiana administratora – czy w ogóle trzeba przygotowywać te wszystkie dokumenty?"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "20a199b44517",
"_type": "block",
"children": [
{
"_key": "3277e57ddb600",
"_type": "span",
"marks": [],
"text": "Odwołanie administratora w uchwale podjętej w trybie indywidualnego zbierania głosów"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "a7bc5bad5b93",
"_type": "block",
"children": [
{
"_key": "f89c3d5c47600",
"_type": "span",
"marks": [],
"text": "Czy można odwołać administratora uchwałą zbieraną w trybie obiegowym?"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "5d10ba7f53be",
"_type": "block",
"children": [
{
"_key": "31a44cb68f820",
"_type": "span",
"marks": [],
"text": "W jaki sposób odwołać administratora w trybie indywidualnego zbierania głosów?"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "874dfb025742",
"_type": "block",
"children": [
{
"_key": "2d0d612db0230",
"_type": "span",
"marks": [],
"text": "Podpowiedzi, kiedy lokal może być przedmiotem współwłasności"
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "9c773f441756",
"_type": "block",
"children": [
{
"_key": "78c7a9d1d8d20",
"_type": "span",
"marks": [],
"text": "Głosowanie nad uchwałą w trybie indywidualnego zbierania głosów"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "01dec1e04a6c",
"_type": "block",
"children": [
{
"_key": "4d8f092719eb0",
"_type": "span",
"marks": [],
"text": "Checklista głosowania w trybie indywidualnym"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "afcf7039fdab",
"_type": "block",
"children": [
{
"_key": "e1a9edbed3d50",
"_type": "span",
"marks": [],
"text": "Uchwała rozwiązująca umowę z administratorem podjęta w drodze indywidualnego zbierania głosów a metoda 5 kroków"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "6a5303b84fe9",
"_type": "block",
"children": [
{
"_key": "0c27e86d9e840",
"_type": "span",
"marks": [],
"text": "Odwołanie administratora na zebraniu wspólnoty mieszkaniowej"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "064037ad40d4",
"_type": "block",
"children": [
{
"_key": "5f853d6361f10",
"_type": "span",
"marks": [],
"text": "Czy warto przygotować pełnomocnictwo?"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "d38a940b757b",
"_type": "block",
"children": [
{
"_key": "e2bd9fb1e1ed0",
"_type": "span",
"marks": [],
"text": "Głosowanie 1 właściciel 1 głos."
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "93e99822e427",
"_type": "block",
"children": [
{
"_key": "e30519fe3f1b0",
"_type": "span",
"marks": [],
"text": "Zebranie wspólnoty mieszkaniowej"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "39231bb1043e",
"_type": "block",
"children": [
{
"_key": "33daa202164d0",
"_type": "span",
"marks": [],
"text": "Kto może zwołać zebranie wspólnoty mieszkaniowej?"
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "8fe8a033a686",
"_type": "block",
"children": [
{
"_key": "ff01a723dd4e0",
"_type": "span",
"marks": [],
"text": "Planowe zebranie roczne"
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "f03059b716cb",
"_type": "block",
"children": [
{
"_key": "40b18a2a712b0",
"_type": "span",
"marks": [],
"text": "Złożenie wniosku do administratora o zwołanie zebrania."
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "58b792e52a14",
"_type": "block",
"children": [
{
"_key": "d424026611150",
"_type": "span",
"marks": [],
"text": "Podjęcie uchwały"
}
],
"level": 3,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "09284ef526ba",
"_type": "block",
"children": [
{
"_key": "da207bba61d10",
"_type": "span",
"marks": [],
"text": "Jak złożyć wypowiedzenie administratorowi?"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "25dd7da79b93",
"_type": "block",
"children": [
{
"_key": "4c2fbdbdc6aa0",
"_type": "span",
"marks": [],
"text": "Wzory dokumentów"
}
],
"level": 1,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "8b3ba2eb5420",
"_type": "block",
"children": [
{
"_key": "030e98c21b8f0",
"_type": "span",
"marks": [],
"text": "Pełnomocnictwo"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "c1e6f3cd3a07",
"_type": "block",
"children": [
{
"_key": "fb54244f98310",
"_type": "span",
"marks": [],
"text": "Wniosek o rozszerzenie porządku obrad zebrania wspólnoty mieszkaniowej"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "38cdd64b043b",
"_type": "block",
"children": [
{
"_key": "98fa08c9f32e0",
"_type": "span",
"marks": [],
"text": "Wniosek o zwołanie zebrania wspólnoty mieszkaniowej"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "fe79c33278ce",
"_type": "block",
"children": [
{
"_key": "73a6d66b65250",
"_type": "span",
"marks": [],
"text": "Uchwała wspólnoty mieszkaniowej w sprawie odwołania administratora"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
},
{
"_key": "f3434219c8b2",
"_type": "block",
"children": [
{
"_key": "663ba23514cf0",
"_type": "span",
"marks": [],
"text": "Wypowiedzenie"
}
],
"level": 2,
"listItem": "number",
"markDefs": [],
"style": "normal"
}
],

@joelisfar
Copy link

I'm having the same issue. In case it's of any use, here's a small example of the data and its output:

Nested list JSON output

  "body": [
    {
      "_key": "6910ab1aa5dc",
      "_type": "block",
      "children": [
        {
          "_key": "e1a144d0eb80",
          "_type": "span",
          "marks": [],
          "text": "Item 1 of the Level 1 list"
        }
      ],
      "level": 1,
      "listItem": "bullet",
      "markDefs": [],
      "style": "normal"
    },
    {
      "_key": "56f41e061efa",
      "_type": "block",
      "children": [
        {
          "_key": "82534a0b5bb6",
          "_type": "span",
          "marks": [],
          "text": "Item 1 of the Level 2 list"
        }
      ],
      "level": 2,
      "listItem": "bullet",
      "markDefs": [],
      "style": "normal"
    },
    {
      "_key": "3d6b701f6f7f",
      "_type": "block",
      "children": [
        {
          "_key": "328ea9751c4d",
          "_type": "span",
          "marks": [],
          "text": "Item 2 of the Level 1 list"
        }
      ],
      "level": 1,
      "listItem": "bullet",
      "markDefs": [],
      "style": "normal"
    }
  ],

Nested list HTML output

<ul>
    <li>Item 1 of the Level 1 list</li>
    <li>
        <ul>
            <li>Item 1 of the Level 2 list</li>
        </ul>
    </li>
    <li>Item 2 of the Level 1 list</li>
</ul>

Desired HTML output

<ul>
    <li>Item 1 of the Level 1 list
        <ul>
            <li>Item 1 of the Level 2 list</li>
        </ul>
    </li>
    <li>Item 2 of the Level 1 list</li>
</ul>

Screenshot of "double bullets" issue

Screenshot 2023-06-23 at 6 39 25 PM

@danielroe danielroe removed their assignment Sep 6, 2023
@adalmagro-rs
Copy link

adalmagro-rs commented Aug 27, 2024

Hi, not sure if this is something related to this bug but I am experiencing issues with lists rendering with Nuxt3. I am passing the following serializer to the SanityContent:

const serializers = {
    types: {
        code: Code,
        callout: Callout,
        seoImage: SeoImage,
        video: VideoImage
    },
    list: {
        // Ex. 1: customizing common list types
        bullet: List,
        number: NumberedList,
        // bullet: (_, { slots }) => h('ul', { class: 'simple-list' }, slots.default?.()),
        // number: (_, { slots }) => h('ol', { class: 'digit-list' }, slots.default?.()),
    },
    listItem: {
        // Ex. 1: customizing common list types
        // bullet: ({ slots }) => h('li', { class: 'list-item' }, slots),
        // number: ({ slots }) => h('li', { class: 'list-item' }, slots),
        bullet: ListItem,
        number: ListItem
    },
    styles: {
        'blockquote': BlockQuote,
    },
    marks: {
        'externalLink': Link,
        'internalLink': InternalLink,
        'strike-through': 's',
        'keyboard': 'kbd',
        'highlight': 'mark'
    }
}

I have some custom types, styles and marks that renders fine, but list and listItem do not render as pointed out at all. I have tried the two ways shown in the code: as a Vue Component and as inline definition (commented) but none of both work. In fact, it does not show the list on the rendered HTML.

Is this bug still open? Is this behaviour related o is a new bug?

I am using:
"@nuxtjs/sanity@^1.11.3":
version "1.11.3"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants