Migrate Utils
Shared utilities for the Ghost migration tooling.
Install
To use this package in your own project:
npm install @tryghost/mg-utils --save
or
pnpm add @tryghost/mg-utils
Usage
DOM Utilities
Lightweight HTML parsing and manipulation powered by linkedom. Use processFragment for most cases — it parses HTML, passes the fragment to your callback, and automatically cleans up:
import {domUtils} from '@tryghost/mg-utils';
const {processFragment, processFragmentAsync} = domUtils;
// Parse, manipulate, and get the result in one step
const html = processFragment('<p>Hello</p><p class="remove">World</p>', (parsed) => {
for (const el of parsed.$('.remove')) {
el.remove();
}
return parsed.html();
});
// => '<p>Hello</p>'
// Extract data from HTML
const title = processFragment(rawHtml, parsed => parsed.$('h1')[0]?.textContent || '');
// Async version for callbacks that need to await
const result = await processFragmentAsync(html, async (parsed) => {
for (const img of parsed.$('img')) {
const newSrc = await processImage(img.getAttribute('src'));
img.setAttribute('src', newSrc);
}
return parsed.html();
});
The parsed fragment provides:
parsed.$(selector, context?)— query elements (returnsElement[])parsed.html()— serialize the fragment back to an HTML stringparsed.text()— get text contentparsed.document— access the underlyingDocumentparsed.body— access the<body>element
For long-lived or complex processing where a callback doesn't fit, use parseFragment directly:
const {parseFragment} = domUtils;
const parsed = parseFragment(html);
// ... extensive manipulation ...
const result = parsed.html();
DOM Manipulation Helpers
const {replaceWith, insertBefore, insertAfter, wrap, createElement, attr} = domUtils;
const parsed = parseFragment('<div><p>Old</p></div>');
const p = parsed.$('p')[0];
replaceWith(p, '<span>New</span>'); // Replace element with HTML string or Node
insertBefore(el, '<!--kg-card-begin-->'); // Insert before element
insertAfter(el, '<!--kg-card-end-->'); // Insert after element
wrap(el, '<figure></figure>'); // Wrap element in a new parent
const div = createElement(parsed.document, 'div', {class: 'wrapper'});
attr(el, 'href'); // Get attribute (returns '' if missing)
attr(el, 'href', '/new-url'); // Set attribute
Additional Element Utilities
is(el, selector)— check if element matches a CSS selectorparents(el, selector?)— get all parent elements, optionally filteredlastParent(el, selector)— get the furthest parent matching selectorsetStyle(el, property, value)— set a CSS style propertyisComment(node)/getCommentData(node)— comment node helpersserializeNode(node)/serializeChildren(node)— HTML5-compliant serialization
XML Utilities
Parse XML strings or files into JavaScript objects using fast-xml-parser:
import {xmlUtils} from '@tryghost/mg-utils';
const {parseXml} = xmlUtils;
// Parse an XML string
const data = await parseXml('<root><item>hello</item></root>');
// Parse from a file path
const data = await parseXml('/path/to/file.xml');
// Override parser options
const data = await parseXml(xmlString, {attributeNamePrefix: ''});
Develop
This is a mono repository, managed with Nx and pnpm workspaces.
Follow the instructions for the top-level repo.
git clonethis repo &cdinto it as usual- Run
pnpm installto install top-level dependencies.
Test
pnpm testruns the package tests- Linting and formatting are run from the repo root (
pnpm lint,pnpm format)
Copyright & License
Copyright (c) 2013-2026 Ghost Foundation - Released under the MIT license.