import { nanoid } from '../core/transport.js' import { breakpoints, themes } from './presets/index.js' import { Rule } from './rule.js' import * as Set from './set.js' import { cloneDeep } from '../utils/object.js' import { toSlug } from '../utils/string.js' export function migrateStylesheets(s: any[], toVersion: number, doNotAddGlobalStyles = false) { let styles = cloneDeep(s) if (toVersion === 1) { const colors: any = [] for (let i = 0; i < styles.length; i++) { let style = styles[i] if (style.type === 'card') { style.type = 'block' style.details.collectionId = 'card' } else if (style.type === 'breakpoint') { styles[i] = null continue } else if (style.type === 'section') { style.type = 'block' style.details.collectionId = 'section' } else if (style.type === 'button') { style.type = 'inline' style.details.collectionId = 'button' } else if (style.type === 'text') { if (style.props.tag === 'h1') { style.details.collectionId = 'heading1' } if (style.props.tag === 'h2') { style.details.collectionId = 'heading2' } if (style.props.tag === 'h3') { style.details.collectionId = 'heading3' } if (style.props.tag === 'h4') { style.details.collectionId = 'heading4' } if (style.props.tag === 'h5') { style.details.collectionId = 'heading5' } if (style.props.tag === 'p') { style.details.collectionId = 'paragraph' } delete style.props.tag } else if (style.type === 'color') { style.props.colors?.map((c: any, index: number) => { Object.assign(style, { type: 'collection', details: { id: style.details.id, title: style.details.title }, props: { type: 'color' } }) colors.push( Rule({ type: 'color', details: { collectionId: style.details.id, description: '', exampleContent: null, id: style.details.id + '-' + c.name, title: c.name }, props: c.color }) ) }) } else if (style.type === 'decoration') { if (style.props.boxShadowColor) { const { alpha, name, id } = style.props.boxShadowColor style.props.boxShadowColor = { id: id + '-' + name, alpha } } if (style.props.borderColor) { const { alpha, name, id } = style.props.borderColor style.props.borderColor = { id: id + '-' + name, alpha } } style.details.collectionId = `default-${style.type}` } else if (style.type === 'fill') { if (style.props.backgroundColor) { const { alpha, name, id } = style.props.backgroundColor style.props.backgroundColor = { id: id + '-' + name, alpha } } if (style.props.backgroundGradient) { for (let k = 0; k < style.props.backgroundGradient.stops.length; k++) { const stop = style.props.backgroundGradient.stops[k] const { alpha, name, id } = stop.color style.props.backgroundGradient.stops[k].color = { id: id + '-' + name, alpha } } } style.details.collectionId = `default-${style.type}` } else if (style.type === 'palette') { if (style.props.textColor) { const { alpha, name, id } = style.props.textColor style.props.textColor = { id: id + '-' + name, alpha } } if (style.props.textHighlightColor) { const { alpha, name, id } = style.props.textHighlightColor style.props.textHighlightColor = { id: id + '-' + name, alpha } } if (style.props.linkColor) { const { alpha, name, id } = style.props.linkColor style.props.linkColor = { id: id + '-' + name, alpha } } if (style.props.linkHoverColor) { const { alpha, name, id } = style.props.linkHoverColor style.props.linkHoverColor = { id: id + '-' + name, alpha } } } if (style.type == 'fill' || style.type == 'decoration' || style.type == 'spacing' || style.type == 'typography') { style.details.collectionId = `default-${style.type}` } } if (!doNotAddGlobalStyles) { styles = [...styles, ...colors, ...breakpoints] } styles = styles.filter(Boolean) styles.map((style) => { if (style.type != 'color' && style.type != 'breakpoint') { if ( style.details.collectionId == 'card' || style.details.collectionId == 'button' || style.details.collectionId == 'section' ) { style.details.slug = style.details.collectionId + '--' + toSlug(style.details.title, false) } else { style.details.slug = toSlug(style.details.title, false) } } }) } if (toVersion === 2) { const palettes: any = [] styles = styles.map((s) => { if (s.type === 'inline' && !s.props?.paletteIds?.length) { const paletteId = `${s.details.id}-palette` palettes.push( Rule({ type: 'palette', details: { id: paletteId, title: 'Custom', elementId: s.details.id } }) ) return { ...s, props: { ...s.props, paletteIds: [paletteId] } } } return s }) styles = [...styles, ...palettes] } if (toVersion === 3) { styles = [...styles, ...themes] } // 6 jan 2023: if (toVersion === 4) { const theme = styles.find((s) => s.details.id == 'default-theme') styles.forEach((style, index) => { // kill olds hidden breakpoints if (style.type == 'breakpoint' && style.details.isHidden) { styles[index] = null } // text elements changed slug naming convention if (style.type == 'text') { style.details.slug = 'text--' + style.details.slug } // add default elements as combos to default theme if (style.details.isDefault) { const map = { text: ['typographyIds', 'paletteIds'], block: ['fillIds', 'decorationIds', 'layoutIds', 'gridIds', 'spacingIds', 'paletteIds'], inline: ['typographyIds', 'decorationIds', 'fillIds', 'graphicIds', 'paletteIds', 'spacingIds'] } const settings = map[style.type as keyof typeof map] as string[] if (settings) { const combo = { id: nanoid(10), refId: style.details.id, isDefault: true } as any settings.map((p) => { const type = p.replace('Ids', '') const ids = style.props[p] as string[] var filtered = !ids ? s.filter((r) => r.type == type) : ids.map((id) => s.find((r) => r.details.id == id)) const rule = (filtered[0]?.details.isInternal && filtered[1]) || filtered[0] combo[p.replace('Ids', 'Id')] = rule?.details.id || (p != 'paletteIds' ? 'blank-' + p.replace('Ids', '') : null) }) theme.props[style.type + 's'].push(combo) } } }) } if (toVersion === 5 || toVersion == 6) { const theme = styles.find((s) => s?.details.id == 'default-theme') if (theme) theme.details.slug = 'default' } if (toVersion === 6) { const xxlarge = styles.find((s) => s?.details.id == 'xxlarge') if (xxlarge) xxlarge.props.maxWidth = Infinity } // assign slugs to breakpoints if (toVersion === 7) { breakpoints.forEach((i) => { if (i.type == 'breakpoint') { const s = styles.find((s) => s.type == 'breakpoint' && s.details.id == i.details.id) if (s) { s.details.slug = i.details.slug s.props.query = i.props.query } } }) } // find first link color style and creae a link element out of it, assign to themes if (toVersion === 8) { if (!doNotAddGlobalStyles) { const palette = styles.find((s) => s.type == 'palette') styles.push( { type: 'inline', details: { id: 'default-link', title: 'Default link', description: 'Typical link style', collectionId: 'link' }, props: { paletteIds: ['link-palette'], decorationId: ['blank-decoration'], typographyId: ['blank-typography'], spacingId: ['blank-spacing'], fillId: ['blank-fill'] } }, { type: 'palette', details: { id: 'link-palette', title: 'Default link palette', elementId: 'default-link' }, props: { textColor: palette?.props.linkColor, linkDecoration: palette?.props.linkDecoration } } ) styles.forEach((s) => { if (s.type == 'theme') { s.props.inlines.push({ id: nanoid(10), isDefault: true, refId: 'default-link', paletteId: 'link-palette', decorationId: 'blank-decoration', typographyId: 'blank-typography', spacingId: 'blank-spacing', fillId: 'blank-fill' }) } }) } } if (toVersion === 9) { let ids: string[] = [] styles = styles.map((s) => { if (s.type !== 'theme') return s s.props.inlines = s.props.inlines.map((i: any) => { if (ids.includes(i.id)) return { ...i, id: nanoid(10) } ids.push(i.id) return i }) s.props.blocks = s.props.blocks.map((i: any) => { if (ids.includes(i.id)) return { ...i, id: nanoid(10) } ids.push(i.id) return i }) s.props.text = s.props.texts.map((i: any) => { if (ids.includes(i.id)) return { ...i, id: nanoid(10) } ids.push(i.id) return i }) return s }) } if (toVersion === 10) { let ids: string[] = [] styles = styles.map((s) => { if (s.type !== 'theme') return s s.props = { inlines: s.props.inlines, blocks: s.props.blocks, texts: s.props.texts.map((i: any) => { if (ids.includes(i.id)) return { ...i, id: nanoid(10) } ids.push(i.id) return i }) } return s }) } if (toVersion === 11) { styles = styles.map((s) => { if (s.type === 'breakpoint' && s.props.maxWidth === 576) { s.props.maxWidth = 575 s.props.query = '(max-width: 575px)' } return s }) } if (toVersion === 12) { // @ts-ignore styles = styles.map((s) => Rule.fix(s, styles)) } // Dimensions should allow null values if (toVersion === 13) { styles.forEach((style) => { if (style.type == 'dimensions') { for (var property in style.props) if (style.props[property]?.value === 0) style.props[property] = null } }) } if (false && toVersion === 17) { styles = Set.fix(styles).filter((s) => s.details.title) } // remove dangling elements not assigned to any collection, leftover from ancient styles if (toVersion === 20) { styles = styles.filter( (s) => !((s.type == 'text' || s.type == 'block' || s.type == 'inline') && !s.details.collectionId) ) } if (toVersion == 21) { styles = styles.map((s) => (s.details.type == 'theme' ? Rule.fix(s, styles) : s)) } if (toVersion == 22) { const xsmall = styles.find((s) => s.details.id == 'extra small') if (xsmall) xsmall.details.id = 'xsmall' } if (toVersion == 23) { styles.map((c) => { if (c.type == 'typography') { if (c.props.overrides['extra small']) { c.props.overrides['xsmall'] = c.props.overrides['extra small'] delete c.props.overrides['extra small'] } } }) } if (toVersion == 28) { styles.map((c) => { if (c.type == 'font') { c.details.title ||= c.props?.familyName || 'Unknown font' } }) } if (toVersion == 30) { styles.map((c) => { if (c.type == 'breakpoint' && c.props.query) { c.props.query = c.props.query.replace('.999', '.98') } }) } return styles.filter(Boolean) }