MishkaCmsMigration.Sources.WordPress.Elementor (Mishka CMS Migration v0.0.1)

Copy Markdown View Source

A WordPress page or post laid out with Elementor as its item's content pieces (MishkaCmsMigration.Source.Item), and the widgets in it the CMS has no equivalent for.

Elementor keeps an entry's layout as JSON in its _elementor_data meta, and marks an entry it lays out with the _elementor_edit_mode meta "builder". The REST API answers both from Elementor 3.27 on, and an export carries them. call/3 reads an entry so marked whose data is a list of elements. Any other entry is :none, and so is one whose data is not JSON: it is read from its content (MishkaCmsMigration.Sources.WordPress.Content), where Elementor keeps a rough HTML fallback of the layout. A site on an older Elementor answers no data over the REST API, so its Elementor entries are read from that fallback; its export carries the data.

The data is a tree of elements: sections holding columns, and containers (Elementor 3.6 on) holding containers, each holding widgets. A section or a container at the top is drawn across the page; one nested in another ("isInner") is drawn inside it.

A page

A page is laid out with the plain HTML the CMS's page builder places (MishkaCmsCore.Runtime.Authoring.Elements), each element with the builder's own classes, so it opens in the builder as though it had been built there:

  • a section or a container at the top — a Section, holding a Container (centred and width capped) unless it is full width;
  • the columns of a section, and the children of a container laid out in a row — a grid with a column for each, 12 at most (the widest grid Tailwind has), side by side from the md width, as the builder's 2, 3 and 4 columns are; one column alone, and the children of a container laid out in a column — a Stack, one under the next;
  • a heading — the H1 to H6 its size names (H2 by default; a paragraph for a div, span or p), linked when it links, centred, right-aligned or justified as it is;
  • a text editor — its HTML in a box, converted as classic content is (paragraphs, shortcodes, a YouTube or Vimeo address alone on its line);
  • an image — an Image, or a Figure with its caption (its own, or its file's), linked to its file or to its own address;
  • a button — a link drawn as the builder's button, centred or right-aligned as it is;
  • a video — the player of a YouTube or Vimeo video (MishkaCmsMigration.Sources.WordPress.Content.embed/1), a link to a Dailymotion or VideoPress one, and a <video> of a file the site hosts or of another address; a video whose address was never set is Elementor's demo video, as Elementor draws it, and one whose address was cleared is none;
  • an icon list — a Bulleted list, each item linked when it links, without its icons;
  • an image gallery, and Elementor Pro's gallery — a grid of as many columns as it says (1 to 12, and 4 when it says none), of Figures each linked to its file or to its attachment page;
  • a spacer — a Spacer, and a divider a Divider;
  • HTML — the author's markup as it is;
  • a shortcode — its shortcodes, converted as classic content's are.

The paragraphs, lists, quotes, links, images, figures and rules of these take the classes of the builder's element of the same tag (Paragraph, Bulleted list, Link, ...), with the builder's slate colours swapped for the site's colour tokens (text-fg dark:text-fg-dark, ...): slate does not change in the dark theme, and the tokens do.

What of Elementor's styling is carried over

Through the builder's own style settings (MishkaCmsCore.Runtime.Authoring.Tree.Styles, what its Inspector writes and reads back), never an inline style: a property and a value for each width (Elementor's own, tablet and mobile settings are the builder's base, tablet and mobile), compiled to the Tailwind classes the Inspector would have written, after the element's own.

  • alignment (align) — a heading's, a text editor's and a button's text-align;
  • the padding and margin of a section and a container (on the Section at the top, on the grid or the stack an inner one becomes), of a column (on the Stack its cell becomes, wrapped in one even when it holds one widget), of a widget (its Advanced tab's _padding and _margin, on the element it draws, or on a box around it when it draws more than one, or a link) and a button's own (text_padding) — by side (py/px when both sides match, else pt, pb, pl, pr), exact, not rounded to a spacing step;
  • a section's content_width and a container's boxed_width — the Container's max-width;
  • a container's flex_gap — the gap of the grid or stack it becomes; a section's named column gap — the grid's gap in the pixels Elementor documents for it (no 0, narrow 5, default 10, extended 15, wide 20, wider 30), or its gap_columns_custom;
  • an image's width, and its own size (width: auto) when Elementor gives none, in place of the builder's full width, and its align — its margins (mx: auto centred, ml: auto to the right, mx: 0 to the left), centred when Elementor says nothing, as Elementor draws it;
  • a heading's, a text editor's and a button's typography — its font's font-size, in the unit Elementor has (px, em, rem, %, vw, vh), font-weight (300 to 800), line-height, letter-spacing and text-transform, each at the widths Elementor has them;
  • colours — a heading's (title_color), a text editor's (text_color) and a button's (button_text_color) color, and the background of a button, a section, a column and a container whose background is a colour (background_background classic).

Elementor's global colours and fonts

A colour or a font a widget names in its __globals__ is one of the kit's, which the site has as theme tokens (MishkaCmsMigration.Sources.WordPress.ElementorKit), and the page names the token:

  • a colour is the style setting var(--color-el-<id>,<value>), and its dark twin the class dark:text-[var(--color-el-<id>-dark,var(--color-el-<id>,<value>))] (or dark:bg-… for a background) in place of the theme's own pair (text-fg dark:text-fg-dark, ...): the dark theme shows the twin, which an admin sets once in the stylesheet for every page;
  • a font is the class of its family, font-[family-name:var(--font-el-<id>,'<family>',sans-serif)], and its weight, size, line height, letter spacing and case are the style settings above. Elementor applies a global font whole, so the widget's own typography is not read beside it.

Each token has the kit's own colour or family behind it, so a page reads while the stylesheet is missing, not yet active, or archived.

A family a widget sets itself is the class of the kit's font in that family, the one the stylesheet loads; any other family is left out, as nothing on the site would load it. A global the kit does not have, such as a custom colour since deleted, draws nothing, as on WordPress.

A colour of the widget's own is the style setting with its value (text-[#0f766e]), in place of the theme's light colour, and the element keeps the theme's dark twin, so it reads in the dark theme (dark:bg-page-dark for the background of a section, a column or a container, which has none); a colour that is exactly the light value of one of the theme's text tokens (fg, dim, subtle, faint, brand) is that token's classes with their dark twins. A text editor's colour, size and line height are its box's, so its paragraphs, lists and quotes leave theirs out and take the box's.

Not carried over: a family no font of the kit has, gradients and pictures behind an element, borders, shadows and hover colours. Elementor's tablet (1024) and mobile (767) widths become the builder's (900 and 560).

A post

A post is the Blog's HTML, as a post written in the block editor is: the same elements without the builder's classes, Sections or Stacks, the columns of a grid as <div class="grid gap-6 md:grid-cols-N">, a gallery as a <figure> of figures, a button as a link in a paragraph, and no spacer.

Widgets the CMS has no equivalent for

Any other widget, such as Elementor Pro's form or slides, an image carousel or a map, and an element of another kind (Elementor 4's atomic elements), stands in its place as what Elementor drew for it: its part of the entry's content.rendered, found by its data-id, without classes, styles, data- attributes, the srcset of other sizes, scripts and decorative (aria-hidden) parts. Its name (widgetType, or the element's elType) is among the names call/3 answers, each once, in the order they come, for the target to ask an admin before it writes the fallback (MishkaCmsMigration.Targets.Helpers.Widgets). One Elementor drew nothing for has no fallback, and nothing stands in its place: one whose data-id the rendering does not have, one whose part holds nothing but empty boxes, such as a Pro widget on a site without Pro, and every such widget read from an export, which carries no rendering. call/3 names those apart.

The images of the image and gallery widgets are read from WordPress with fetch (/wp/v2/media), all in one request, for their alt text, caption and attachment page.

Summary

Functions

The content pieces of row, an entry Elementor laid out, made as a kind ("page" or "post") is, the names of the widgets in it the CMS has no equivalent for, and the names of those of them Elementor drew nothing for, reading its images with fetch and naming the site's globals (MishkaCmsMigration.Sources.WordPress.ElementorKit); :none for an entry Elementor did not lay out.

Functions

call(row, kind, fetch, globals \\ %{})

The content pieces of row, an entry Elementor laid out, made as a kind ("page" or "post") is, the names of the widgets in it the CMS has no equivalent for, and the names of those of them Elementor drew nothing for, reading its images with fetch and naming the site's globals (MishkaCmsMigration.Sources.WordPress.ElementorKit); :none for an entry Elementor did not lay out.