Skip to content

Commit

Permalink
replace psd-tools with psd-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderspevak committed Dec 8, 2022
1 parent 60afc5d commit 8a73a87
Show file tree
Hide file tree
Showing 94 changed files with 1,935 additions and 1,171 deletions.
16 changes: 16 additions & 0 deletions packages/octopus-psd/examples/node/convert-bulk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { readdir } from 'fs/promises'

import { convert } from './convert-debug.js'

const dirPath = './sample'
export async function convertBulk() {
const fileNames = await readdir(dirPath)
const filtered = fileNames.filter((name) => name.includes('psd'))

for (const fileName of filtered) {
const path = `${dirPath}/${fileName}`
await convert([path])
}
}

convertBulk()
2 changes: 1 addition & 1 deletion packages/octopus-psd/examples/node/convert-debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ async function convertDir(dirPath: string) {
}
}

async function convert(locations: string[]) {
export async function convert(locations: string[]) {
for (const location of locations) {
if (await isDirectory(location)) {
await convertDir(location)
Expand Down
5 changes: 4 additions & 1 deletion packages/octopus-psd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"clean": "rimraf ./node_modules ./lib ./dist ./workdir ./test/integration/report ./jsdoc",
"convert:debug": "yarn build && node ./lib/examples/node/convert-debug.js",
"convert:local": "yarn build && node ./lib/examples/node/convert-local.js",
"convert:bulk": "yarn clean:workdir && yarn build && node ./lib/examples/node/convert-bulk.js",
"prepack": "rimraf ./lib && yarn run build",
"test": "yarn test:unit && yarn test:integration",
"test:unit": "yarn build && yarn node --experimental-vm-modules $(yarn bin jest)",
Expand All @@ -26,12 +27,12 @@
"@opendesign/octopus-ts": "3.0.0-alpha.38",
"@types/chalk": "^2.2.0",
"@types/lodash": "^4.14.178",
"@types/pino": "^6.3.3",
"@types/rimraf": "^3.0.2",
"@types/uuid": "^8.3.1",
"chalk": "^4.1.2",
"dotenv": "16.0.0",
"image-size": "^1.0.1",
"jimp": "^0.16.2",
"lodash": "^4.17.21",
"paper": "0.12.15",
"pino": "^6.7.0",
Expand All @@ -41,6 +42,8 @@
"uuid": "^8.3.2"
},
"devDependencies": {
"@types/pino-pretty": "4.7.5",
"@types/pino-std-serializers": "2.4.1",
"@types/jest": "^27.4.0",
"@types/node": "*",
"handlebars": "^4.7.7",
Expand Down
Binary file added packages/octopus-psd/pattern-01.psd
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class OctopusComponent {
constructor(options: OctopusComponentOptions) {
this._sourceComponent = options.sourceComponent
this._designConverter = options.designConverter

this._layers = createOctopusLayers(this.sourceComponent.layers, this)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export class OctopusEffectBevelEmboss extends OctopusEffectBase {
protected _parentLayer: OctopusLayerBase
private _bevelEmboss: SourceEffectBevelEmboss

static BEVEL_EMBOSS_TYPE_MAP = {
OtrB: 'outerBevel',
InrB: 'innerBevel',
Embs: 'emboss',
PlEb: 'pillowEmboss',
strokeEmboss: 'strokeEmboss',
} as const

constructor(options: OctopusEffectBevelEmbossOptions) {
super(options)
this._parentLayer = options.parentLayer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ export class OctopusEffectFillGradient {
private _isStroke: boolean

static GRADIENT_TYPE_MAP = {
linear: 'LINEAR',
radial: 'RADIAL',
Lnr: 'LINEAR',
Rdl: 'RADIAL',
Angl: 'ANGULAR',
Dmnd: 'DIAMOND',
reflected: 'REFLECTED',
Rflc: 'REFLECTED',
} as const

constructor(options: OctopusFillGradientOptions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class OctopusEffectFill {
}

private get _imageName(): string {
return `${this._fill?.pattern?.ID}.png`
return `${this._fill?.pattern?.Idnt}.png`
}

private get _imagePath(): string | undefined {
Expand All @@ -66,7 +66,7 @@ export class OctopusEffectFill {
const image = this._image
const { width, height } = image ?? {}
if (width === undefined || height === undefined) {
logger.warn('Unknown image', { image, id: this._fill?.pattern?.ID })
logger.warn('Unknown image', { image, id: this._fill?.pattern?.Idnt })
return null
}
const matrix = createMatrix(width, 0, 0, height, ...this._offset)
Expand All @@ -77,7 +77,7 @@ export class OctopusEffectFill {

convert(): Octopus['Fill'] | null {
const fill = this._fill
if (!fill.enabled) return null
if (!fill?.enabled) return null
switch (this.fillType) {
case 'GRADIENT': {
const parentLayer = this._parentLayer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class OctopusEffectOverlayPattern extends OctopusEffectBase {
}

private get _imageName(): string {
return `${this._fill?.pattern?.ID}.png`
return `${this._fill?.pattern?.Idnt}.png`
}

private get _imagePath(): string | undefined {
Expand All @@ -63,7 +63,7 @@ export class OctopusEffectOverlayPattern extends OctopusEffectBase {
const image = this._image
const { width, height } = image ?? {}
if (width === undefined || height === undefined) {
logger.warn('Unknown image', { image, id: this._fill?.pattern?.ID })
logger.warn('Unknown image', { image, id: this._fill?.pattern?.Idnt })
return null
}
const matrix = createMatrix(width, 0, 0, height, ...this._offset)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { OctopusLayerShape } from './octopus-layer-shape.js'
import type { OctopusLayer } from '../../factories/create-octopus-layer'
import type { SourceLayer } from '../../factories/create-source-layer'
import type { Octopus } from '../../typings/octopus'
import type { RawLayerLayer, RawLayerShape, RawPath } from '../../typings/raw'
import type { RawLayerLayer, RawLayerShape } from '../../typings/raw'
import type { SourceBounds, SourceColor } from '../../typings/source'
import type { SourceLayerLayer } from '../source/source-layer-layer'
import type { SourceLayerShape } from '../source/source-layer-shape'
Expand Down Expand Up @@ -95,9 +95,23 @@ export class OctopusLayerMaskGroup {
if (!bitmapMask) return octopusLayer
const { width, height } = octopusLayer.parentComponent.dimensions
const bounds = { left: 0, right: width, top: 0, bottom: height }
const raw: RawLayerLayer = { type: 'layer', bitmapBounds: bounds, bounds, visible: false, imageName: bitmapMask }
const maskSourceLayer = createSourceLayer({ layer: raw, parent: sourceLayer?.parent }) as SourceLayerLayer

const raw: RawLayerLayer = {
addedType: 'layer',
width: bounds.right - bounds.left,
height: bounds.bottom - bounds.top,
top: bounds.top,
left: bounds.left,
isHidden: true,
parsedProperties: {},
//imageName: bitmapMask,
}
const maskSourceLayer = createSourceLayer({
layer: raw,
parent: sourceLayer?.parent,
}) as SourceLayerLayer
const maskAdapter = new OctopusLayerShapeLayerAdapter({ parent, sourceLayer: maskSourceLayer })

const mask = new OctopusLayerShape({ parent, sourceLayer, adapter: maskAdapter })
return new OctopusLayerMaskGroup({
parent,
Expand All @@ -115,10 +129,20 @@ export class OctopusLayerMaskGroup {
parent,
}: CreateWrapMaskOptions<T>): OctopusLayerMaskGroup | T {
const path = sourceLayer.path

if (!path) return octopusLayer
const raw: RawLayerShape = { type: 'shapeLayer', visible: false, path: path.raw as RawPath }
const maskSourceLayer = createSourceLayer({ layer: raw, parent: sourceLayer?.parent }) as SourceLayerShape
const raw: RawLayerShape = {
addedType: 'shapeLayer',
isHidden: true,
parsedProperties: { vmsk: path.vectorMaskSetting, vogk: path.vectorOriginationData },
}

const maskSourceLayer = createSourceLayer({
layer: raw,
parent: sourceLayer?.parent,
}) as SourceLayerShape
const maskAdapter = new OctopusLayerShapeShapeAdapter({ parent, sourceLayer: maskSourceLayer })

const mask = new OctopusLayerShape({ parent, sourceLayer, adapter: maskAdapter })
const id = `${octopusLayer.id}-ShapeMask`
return new OctopusLayerMaskGroup({ id, parent, mask, maskBasis: 'BODY', layers: [octopusLayer] })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export class OctopusLayerShapeShapePath {
private _getPathRectangle(pathComponents: SourcePathComponent[]): Octopus['PathRectangle'] {
const rect = pathComponents[0]
const { bottom, left, right, top } = rect.origin.bounds

const [layerTx, layerTy] = this._parentLayer.layerTranslation
const tx = left - layerTx
const ty = top - layerTy
Expand Down
40 changes: 33 additions & 7 deletions packages/octopus-psd/src/entities/octopus/octopus-manifest.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import path from 'path'

import { asString } from '@opendesign/octopus-common/dist/utils/as.js'
import { traverseAndFind } from '@opendesign/octopus-common/dist/utils/common.js'
import { asArray, asString } from '@opendesign/octopus-common/dist/utils/as.js'

import { getFontProperties } from '../../utils/text.js'

import type { OctopusPSDConverter } from '../..'
import type { Manifest } from '../../typings/manifest'
import type { EngineData, NodeChildWithProps, ParsedPsd } from '../../typings/raw'
import type { SourceBounds } from '../../typings/source'
import type { SourceComponent } from '../source/source-component'
import type { SourceDesign } from '../source/source-design'
Expand Down Expand Up @@ -106,22 +108,46 @@ export class OctopusManifest {
}
}

private _getComponentAssetsFonts(raw: Record<string, unknown>): string[] {
const entries = traverseAndFind(raw, (obj: unknown) => Object(obj)?.fontPostScriptName)
return [...new Set(entries)] as string[]
private _getFontNames(engineData: EngineData | undefined): string[] {
const { ResourceDict } = engineData ?? {}
const { FontSet } = ResourceDict ?? {}
const { RunArray } = engineData?.EngineDict?.StyleRun ?? {}
const fontSet = asArray(FontSet)
const runArray = asArray(RunArray)

return runArray.map(({ StyleSheet }) => {
return getFontProperties(fontSet, StyleSheet?.StyleSheetData).fontName
})
}

private _getComponentAssetsFonts(
raw: ParsedPsd | NodeChildWithProps,
fontsSet: Set<string> = new Set()
): Set<string> {
if ('textProperties' in raw) {
const fonts = this._getFontNames(raw.textProperties)
fonts.forEach((fontName) => fontsSet.add(fontName))
}

if ('children' in raw) {
raw.children?.forEach((child) => this._getComponentAssetsFonts(child, fontsSet))
}

return fontsSet
}

private _getComponentAssets(targetComponent: SourceComponent): Manifest['Assets'] | null {
const raw = targetComponent?.raw
if (!raw) return null

const images: Manifest['AssetImage'][] = this._sourceDesign.images.map((image) => {
const path = this.getExportedRelativeImageByName(image.name) ?? ''
const location: Manifest['ResourceLocation'] = { type: 'RELATIVE', path }
return { location, refId: image.name }
})

const fonts: Manifest['AssetFont'][] = this._getComponentAssetsFonts(raw).map((font) => ({ name: font }))
const fonts: Manifest['AssetFont'][] = Array.from(this._getComponentAssetsFonts(raw as ParsedPsd)).map((font) => ({
name: font,
}))

return {
...(images.length ? { images } : null),
Expand Down
62 changes: 46 additions & 16 deletions packages/octopus-psd/src/entities/source/source-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,48 @@ import { asArray, asFiniteNumber } from '@opendesign/octopus-common/dist/utils/a
import { push } from '@opendesign/octopus-common/dist/utils/common.js'

import { createSourceLayer } from '../../factories/create-source-layer.js'
import { getArtboardColor, getBoundsFor, isArtboard } from '../../utils/source.js'
import { getArtboardColor, getBoundsFor, getLayerBounds } from '../../utils/source.js'
import { SourceEntity } from './source-entity.js'

import type { SourceLayer } from '../../factories/create-source-layer'
import type { RawComponent, RawLayer } from '../../typings/raw'
import type { NodeChildWithProps, ParsedPsd, RawColor } from '../../typings/raw'
import type { SourceBounds, SourceColor } from '../../typings/source'
import type { SourceDesign } from './source-design.js'

export type SourceComponentOptions = {
raw: RawComponent & RawLayer
isPasteboard?: boolean
raw: ParsedPsd | NodeChildWithProps
parent: SourceDesign
}

export class SourceComponent extends SourceEntity {
protected _rawValue: RawComponent & RawLayer
protected _rawValue: NodeChildWithProps | ParsedPsd
private _layers: SourceLayer[]
private _isPasteboard: boolean
private _parent: SourceDesign

static DEFAULT_ID = 'pasteboard-1'
static DEFAULT_NAME = 'Pasteboard'

constructor({ raw, isPasteboard }: SourceComponentOptions) {
constructor({ isPasteboard, raw, parent }: SourceComponentOptions) {
super(raw)
this._layers = this._initLayers()
this._isPasteboard = isPasteboard ?? false
this._parent = parent
}

private _initLayers() {
const layers = asArray(this._rawValue?.layers).reduce((layers: SourceLayer[], layer: RawLayer) => {
const sourceLayer = createSourceLayer({ layer, parent: this })
const layers = asArray(this._rawValue?.children).reduce((layers: SourceLayer[], layer) => {
const sourceLayer = createSourceLayer({
layer: layer as unknown as NodeChildWithProps,
parent: this,
})
return sourceLayer ? push(layers, sourceLayer) : layers
}, [])
return layers
}

get raw(): RawComponent & RawLayer {
get raw(): NodeChildWithProps | ParsedPsd {
return this._rawValue
}

Expand All @@ -45,12 +52,19 @@ export class SourceComponent extends SourceEntity {
}

get bounds(): SourceBounds {
const artboardRect = this._rawValue.artboard?.artboardRect
return artboardRect ? getBoundsFor(artboardRect) : getBoundsFor(this._rawValue.bounds)
const artboardRect = this._rawValue.parsedProperties?.artb?.artboardRect

return artboardRect
? getBoundsFor(artboardRect)
: this._rawValue?.type === 'Psd'
? getBoundsFor({ Rght: this._rawValue?.width, Btom: this._rawValue?.height })
: getLayerBounds(this._rawValue)
}

get id(): string {
return this._rawValue.id !== undefined ? String(this._rawValue.id) : SourceComponent.DEFAULT_ID
return this._rawValue?.parsedProperties?.lyid !== undefined
? String(this._rawValue.parsedProperties?.lyid)
: SourceComponent.DEFAULT_ID
}

get name(): string {
Expand All @@ -62,18 +76,34 @@ export class SourceComponent extends SourceEntity {
}

get isArtboard(): boolean {
return isArtboard(this._rawValue)
return Boolean(this._rawValue?.parsedProperties?.artb)
}

get artboardColor(): SourceColor | null {
return getArtboardColor(this._rawValue)
return getArtboardColor(this.artboardBackgroundType, this.rawArtboardColor)
}

get artboardBackgroundType(): number | undefined {
return this._rawValue?.parsedProperties?.artb?.artboardBackgroundType
}

get resolution(): number | undefined {
return this._rawValue.resolution
get rawArtboardColor(): RawColor | undefined {
return this._rawValue?.parsedProperties?.artb?.Clr
}

get globalLightAngle(): number {
return asFiniteNumber(this._rawValue.globalLight?.angle, 0)
if ('globalLightAngle' in this._rawValue) {
return asFiniteNumber(this._rawValue.globalLightAngle, 0)
}

return 0
}

get documentWidth(): number {
return this._parent.documentWidth
}

get documentHeight(): number {
return this._parent.documentHeight
}
}
Loading

0 comments on commit 8a73a87

Please sign in to comment.