Converting Text Table into Multi-column layouts

This script turns static Text Tables into Multi-column layouts

Why needed

Text tables in Fibery rich text fields are not responsive in that they will not auto-size in the visible field (the are not responsive). Read more about this issue here A deep dive into the unresponsive Text Table issue - Bugs & Issues - Fibery.io Community

What it does

The script converts the table to a Multi-column layout.
Read more about this Fibery feature:
Multi-columns layout — Guide | Fibery

Example

msedge_M4qXQsXrXS

Script

const fibery = context.getService('fibery');
const PAGE_TYPE = 'YourSpace/Page';
const BODY_FIELD = 'Body';
const DEBUG_FIELD = 'Debug';
const currentPageEntity = args.currentEntities[0];

function generateGuid() {
  let guid = '', chars = '0123456789abcdef';
  for (let i = 0; i < 36; i++) {
    guid += i === 8 || i === 13 || i === 18 || i === 23 ? '-' : chars[Math.floor(Math.random() * 16)];
  }
  return guid;
}

async function convertTableToColumns() {
  let bodyJson = (await fibery.getEntityById(PAGE_TYPE, currentPageEntity.id, [BODY_FIELD]))[BODY_FIELD];
  if (bodyJson && bodyJson.Secret) {
    bodyJson = await fibery.getDocumentContent(bodyJson.Secret, 'json');
  }
  const newDoc = { doc: { type: "doc", content: [] }, comments: bodyJson.comments || [] };
  for (const node of bodyJson.doc.content) {
    if (node.type !== "table") {
      newDoc.doc.content.push(node);
      continue;
    }
    for (const row of node.content.filter(n => n.type === "table_row")) {
      const columnsBlock = {
        type: "columns",
        attrs: { id: "", nodeHeight: 400, nodeWidth: 900, nodePageWidth: true, nodeFullWidth: false },
        content: []
      };
      const columnRatio = 1 / Math.max(1, row.content.length);
      for (const cell of row.content.filter(n => n.type === "table_header" || n.type === "table_cell")) {
        const column = {
          type: "column",
          attrs: { columnRatio },
          content: cell.content.map(node => ({
            ...node,
            attrs: node.attrs ? { ...node.attrs, guid: generateGuid() } : { guid: generateGuid() }
          }))
        };
        columnsBlock.content.push(column);
      }
      newDoc.doc.content.push(columnsBlock);
    }
  }
  const debugField = (await fibery.getEntityById(PAGE_TYPE, currentPageEntity.id, [DEBUG_FIELD]))[DEBUG_FIELD];
  if (debugField && debugField.Secret) {
    await fibery.setDocumentContent(debugField.Secret, newDoc, 'json');
  } else {
    await fibery.updateEntity(PAGE_TYPE, currentPageEntity.id, { [DEBUG_FIELD]: newDoc });
  }
}

await convertTableToColumns();

Explanation

  1. Fetches the Body field JSON from an Amuri/Page entity.
  2. Retrieves document content if Body contains a Secret ID.
  3. Creates a new JSON structure with an empty doc.content array and copies comments.
  4. Generates unique GUIDs for content nodes.
  5. Iterates through all nodes in the input JSON.
  6. Copies non-table nodes (e.g., paragraphs, headings, lists) to the new JSON structure.
  7. Converts each table row (including headers and cells) into a columns block with fixed attributes.
  8. Calculates equal columnRatio for each cell or header in a row.
  9. Transforms each table header or cell into a column with new GUIDs for content nodes.
  10. Adds column blocks to the new JSON structure.
  11. Updates the Debug field with the new JSON, using setDocumentContent if it has a Secret ID, or updateEntity otherwise.

Note:

  • The script is a prototype that inserts the output in another rich text field, to make sure you don’t lose your work.
  • The script does not yet support complex tables with merged cells (e.g., colspan, rowspan), but could be adapted to handle that.
  • Fibery’s Multi-column layouts are not included when the field is copied as markdown. This is another issue (see Multi-columns Layouts cannot be copy-pasted using the markdown copy button - Bugs & Issues - Fibery.io Community) that needs addressed by Fibery. But you can workaround that by making the button automation overwrite the existing field JSON (instead of inserting the JSON in another field like done in the script above), or to have an extra button automation that overwrites it back to the source field as JSON (safest option).
1 Like