UNPKG

@scriptables/manifest

Version:

Utilities to generate, parse, and update manifest headers in Scriptable scripts.

108 lines (101 loc) 3.88 kB
import {generateScriptableBanner} from './generateScriptableBanner'; import {normalizeManifest} from './normalizeManifest'; import {parseScriptableManifest} from './parseScriptableManifest'; import {SCRIPT_HEADER_NOTICES} from './scriptHeaderNotices'; import {ScriptableManifest} from './types'; interface ScriptableBannerResult { /** The merged banner content */ banner: string; /** The remaining script content without the banner */ content: string; } /** * Merges Scriptable script banners according to priority rules. This function: * 1. Merges manifest values from different sources (manifest object, old script, new script) * 2. Preserves static banner lines * 3. Creates new banner if none exists * * @param script - The script content to process * @param manifestOrOldScript - Either a manifest object or old script content to extract manifest from * @returns ScriptableBannerResult containing the merged banner and remaining content * * @example * // Case 1: Merge manifest object with existing banner * const script = `// Variables used by Scriptable. * // These must be at the very top of the file. Do not edit. * // icon-color: blue; icon-glyph: circle; * console.log('Hello world');`; * * const manifest = { * iconColor: 'red', * iconGlyph: 'square' * }; * * const {banner, content} = mergeScriptableBanner(script, manifest); * // banner will be: * // // Variables used by Scriptable. * // // These must be at the very top of the file. Do not edit. * // // icon-color: red; icon-glyph: square; * * @example * // Case 2: Merge banners from old and new scripts * const oldScript = `// Variables used by Scriptable. * // These must be at the very top of the file. Do not edit. * // icon-color: blue; icon-glyph: circle; * console.log('Old script');`; * * const newScript = `// Variables used by Scriptable. * // These must be at the very top of the file. Do not edit. * // icon-color: red; icon-glyph: square; * console.log('New script');`; * * const {banner, content} = mergeScriptableBanner(newScript, oldScript); * // banner will be: * // // Variables used by Scriptable. * // // These must be at the very top of the file. Do not edit. * // // icon-color: blue; icon-glyph: circle; * * @remarks * Merge Priority (highest to lowest): * 1. Manifest object values (if provided) * 2. Old script banner values (if oldScript provided) * 3. New script banner values * 4. Default values * * Supported manifest properties: * - iconColor: The color of the script icon * - iconGlyph: The glyph/symbol used for the script icon * - alwaysRunInApp: Whether the script should always run in the app (true/false) * - shareSheetInputs: Array of allowed input types for share sheet * * Banner Structure: * 1. Static notice lines (preserved as-is) * 2. Manifest properties (merged according to priority) */ export function mergeScriptableBanner( script: string, manifestOrOldScript?: Partial<ScriptableManifest> | string, ): ScriptableBannerResult { if (!script || !script.includes(SCRIPT_HEADER_NOTICES[0])) { return { banner: generateScriptableBanner(manifestOrOldScript as Partial<ScriptableManifest>), content: script || '', }; } const {manifest: currentManifest, content: scriptContent} = parseScriptableManifest(script); let finalManifest: Partial<ScriptableManifest> = currentManifest ?? {}; if (manifestOrOldScript) { if (typeof manifestOrOldScript === 'string') { const {manifest} = parseScriptableManifest(manifestOrOldScript); if (manifest && Object.keys(manifest).length) { finalManifest = {...finalManifest, ...manifest}; } } else { finalManifest = {...finalManifest, ...normalizeManifest(manifestOrOldScript)}; } } return { banner: generateScriptableBanner(finalManifest), content: scriptContent, }; }