Emdash source with visual editor image upload fix
Fixes: 1. media.ts: wrap placeholder generation in try-catch 2. toolbar.ts: check r.ok, display error message in popover
This commit is contained in:
281
packages/core/src/import/settings.ts
Normal file
281
packages/core/src/import/settings.ts
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* Site settings import functions
|
||||
*
|
||||
* Import site settings from WordPress (title, tagline, logo, favicon, etc.)
|
||||
*/
|
||||
|
||||
import type { Kysely } from "kysely";
|
||||
|
||||
import type { Database } from "../database/types.js";
|
||||
|
||||
/**
|
||||
* Site settings analysis from import source
|
||||
*/
|
||||
export interface SiteSettingsAnalysis {
|
||||
/** Site title */
|
||||
title?: string;
|
||||
/** Site tagline/description */
|
||||
tagline?: string;
|
||||
/** Custom logo */
|
||||
logo?: { url: string; id?: number };
|
||||
/** Favicon/site icon */
|
||||
favicon?: { url: string; id?: number };
|
||||
/** Front page settings */
|
||||
frontPage?: { type: "posts" | "page"; pageId?: number };
|
||||
/** SEO settings (Yoast, RankMath, etc.) */
|
||||
seo?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget area analysis
|
||||
*/
|
||||
export interface WidgetAreaAnalysis {
|
||||
/** Widget area ID */
|
||||
id: string;
|
||||
/** Widget area name */
|
||||
name: string;
|
||||
/** Widget area label */
|
||||
label: string;
|
||||
/** Number of widgets */
|
||||
widgetCount: number;
|
||||
/** Widget summaries */
|
||||
widgets: Array<{ type: string; title?: string }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of site settings import
|
||||
*/
|
||||
export interface SettingsImportResult {
|
||||
/** Settings that were applied */
|
||||
applied: string[];
|
||||
/** Settings that were skipped (already set) */
|
||||
skipped: string[];
|
||||
/** Errors encountered */
|
||||
errors: Array<{ setting: string; error: string }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import site settings from analysis
|
||||
*
|
||||
* @param settings - Site settings analysis
|
||||
* @param db - Database connection
|
||||
* @param overwrite - Whether to overwrite existing settings
|
||||
* @returns Import result
|
||||
*/
|
||||
export async function importSiteSettings(
|
||||
settings: SiteSettingsAnalysis,
|
||||
db: Kysely<Database>,
|
||||
overwrite = false,
|
||||
): Promise<SettingsImportResult> {
|
||||
const result: SettingsImportResult = {
|
||||
applied: [],
|
||||
skipped: [],
|
||||
errors: [],
|
||||
};
|
||||
|
||||
// Import title
|
||||
if (settings.title) {
|
||||
try {
|
||||
const applied = await setOption(db, "site_title", settings.title, overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("site_title");
|
||||
} else {
|
||||
result.skipped.push("site_title");
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "site_title",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Import tagline
|
||||
if (settings.tagline) {
|
||||
try {
|
||||
const applied = await setOption(db, "site_tagline", settings.tagline, overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("site_tagline");
|
||||
} else {
|
||||
result.skipped.push("site_tagline");
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "site_tagline",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Import logo URL (actual media import handled separately)
|
||||
if (settings.logo?.url) {
|
||||
try {
|
||||
const applied = await setOption(db, "site_logo_url", settings.logo.url, overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("site_logo_url");
|
||||
} else {
|
||||
result.skipped.push("site_logo_url");
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "site_logo_url",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Import favicon URL
|
||||
if (settings.favicon?.url) {
|
||||
try {
|
||||
const applied = await setOption(db, "site_favicon_url", settings.favicon.url, overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("site_favicon_url");
|
||||
} else {
|
||||
result.skipped.push("site_favicon_url");
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "site_favicon_url",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Import front page settings
|
||||
if (settings.frontPage) {
|
||||
try {
|
||||
const applied = await setOption(db, "front_page_type", settings.frontPage.type, overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("front_page_type");
|
||||
} else {
|
||||
result.skipped.push("front_page_type");
|
||||
}
|
||||
|
||||
if (settings.frontPage.pageId) {
|
||||
const pageApplied = await setOption(
|
||||
db,
|
||||
"front_page_id",
|
||||
String(settings.frontPage.pageId),
|
||||
overwrite,
|
||||
);
|
||||
if (pageApplied) {
|
||||
result.applied.push("front_page_id");
|
||||
} else {
|
||||
result.skipped.push("front_page_id");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "front_page",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Import SEO settings as JSON blob
|
||||
if (settings.seo && Object.keys(settings.seo).length > 0) {
|
||||
try {
|
||||
const applied = await setOption(db, "seo_settings", JSON.stringify(settings.seo), overwrite);
|
||||
if (applied) {
|
||||
result.applied.push("seo_settings");
|
||||
} else {
|
||||
result.skipped.push("seo_settings");
|
||||
}
|
||||
} catch (error) {
|
||||
result.errors.push({
|
||||
setting: "seo_settings",
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an option in the database
|
||||
*
|
||||
* @returns true if the option was set, false if skipped (already exists and !overwrite)
|
||||
*/
|
||||
async function setOption(
|
||||
db: Kysely<Database>,
|
||||
key: string,
|
||||
value: string,
|
||||
overwrite: boolean,
|
||||
): Promise<boolean> {
|
||||
const existing = await db
|
||||
.selectFrom("options")
|
||||
.select("value")
|
||||
.where("name", "=", key)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (existing && !overwrite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
await db.updateTable("options").set({ value }).where("name", "=", key).execute();
|
||||
} else {
|
||||
await db.insertInto("options").values({ name: key, value }).execute();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse site settings from WordPress plugin options response
|
||||
*/
|
||||
export function parseSiteSettingsFromPlugin(
|
||||
options: Record<string, unknown>,
|
||||
): SiteSettingsAnalysis {
|
||||
const settings: SiteSettingsAnalysis = {};
|
||||
|
||||
// Basic settings
|
||||
if (typeof options.blogname === "string") {
|
||||
settings.title = options.blogname;
|
||||
}
|
||||
if (typeof options.blogdescription === "string") {
|
||||
settings.tagline = options.blogdescription;
|
||||
}
|
||||
|
||||
// Logo and favicon
|
||||
if (typeof options.custom_logo_url === "string") {
|
||||
settings.logo = {
|
||||
url: options.custom_logo_url,
|
||||
id: typeof options.custom_logo === "number" ? options.custom_logo : undefined,
|
||||
};
|
||||
}
|
||||
if (typeof options.site_icon_url === "string") {
|
||||
settings.favicon = {
|
||||
url: options.site_icon_url,
|
||||
id: typeof options.site_icon === "number" ? options.site_icon : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
// Front page settings
|
||||
if (options.show_on_front === "page") {
|
||||
settings.frontPage = {
|
||||
type: "page",
|
||||
pageId: typeof options.page_on_front === "number" ? options.page_on_front : undefined,
|
||||
};
|
||||
} else {
|
||||
settings.frontPage = { type: "posts" };
|
||||
}
|
||||
|
||||
// SEO settings (Yoast)
|
||||
const seo: Record<string, unknown> = {};
|
||||
if (typeof options.wpseo === "object" && options.wpseo !== null) {
|
||||
seo.yoast = options.wpseo;
|
||||
}
|
||||
if (typeof options.wpseo_titles === "object" && options.wpseo_titles !== null) {
|
||||
seo.yoast_titles = options.wpseo_titles;
|
||||
}
|
||||
if (typeof options.wpseo_social === "object" && options.wpseo_social !== null) {
|
||||
seo.yoast_social = options.wpseo_social;
|
||||
}
|
||||
if (Object.keys(seo).length > 0) {
|
||||
settings.seo = seo;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
Reference in New Issue
Block a user