mirror of
https://github.com/penpot/penpot-plugins.git
synced 2025-01-21 06:02:34 -05:00
feat: test new state parser
This commit is contained in:
parent
92a26457e0
commit
ecb2295b93
3 changed files with 205 additions and 1 deletions
|
@ -1,2 +1,3 @@
|
|||
export { parse, getSelectedUuids } from './lib/utils';
|
||||
export * from './lib/models';
|
||||
export { getPartialState } from './lib/utils/parse-state';
|
||||
|
|
199
libs/plugins-data-parser/src/lib/utils/parse-state.ts
Normal file
199
libs/plugins-data-parser/src/lib/utils/parse-state.ts
Normal file
|
@ -0,0 +1,199 @@
|
|||
import { toCamelCase } from './object.util';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type UknowCljs = any;
|
||||
|
||||
declare global {
|
||||
const cljs: UknowCljs;
|
||||
const app: UknowCljs;
|
||||
}
|
||||
|
||||
const PATH_SEPARATOR = '/' as const;
|
||||
|
||||
function getPath(path: string): UknowCljs[] {
|
||||
if (path === 'root') {
|
||||
return [];
|
||||
}
|
||||
return path
|
||||
.slice(5)
|
||||
.split(PATH_SEPARATOR)
|
||||
.map((it) => {
|
||||
if (it.startsWith('#')) {
|
||||
return cljs.core.uuid(it.slice(1));
|
||||
} else if (it.startsWith(':')) {
|
||||
return cljs.core.keyword(it.slice(1));
|
||||
} else if (it.startsWith('!')) {
|
||||
return parseInt(it.slice(1), 10);
|
||||
} else {
|
||||
return it;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const expandableTable = {
|
||||
'app:datetime': false,
|
||||
'cljs:uuid': false,
|
||||
'cljs:keyword': false,
|
||||
'cljs:symbol': false,
|
||||
'js:date': false,
|
||||
'js:boolean': false,
|
||||
'js:function': false,
|
||||
'js:number': false,
|
||||
'js:string': false,
|
||||
'js:undefined': false,
|
||||
'js:null': false,
|
||||
'unkwnown:unknown': false,
|
||||
'cljs:vector': true,
|
||||
'cljs:list': true,
|
||||
'cljs:map': true,
|
||||
'cljs:set': true,
|
||||
'js:array': true,
|
||||
'js:object': true,
|
||||
} as const;
|
||||
|
||||
function isCljsArray(key: string) {
|
||||
const valid = ['cljs:vector', 'cljs:list', 'cljs:set'];
|
||||
|
||||
return valid.includes(key);
|
||||
}
|
||||
|
||||
const valueTable = {
|
||||
'app:datetime': (value: unknown) => cljs.core.str(value),
|
||||
'cljs:uuid': (value: unknown) => cljs.core.name(value),
|
||||
'cljs:keyword': (value: unknown) => cljs.core.name(value),
|
||||
'js:date': (value: unknown) => (value as Date).toISOString(),
|
||||
};
|
||||
|
||||
function isTypeExpandable(type: keyof typeof expandableTable) {
|
||||
return expandableTable[type];
|
||||
}
|
||||
|
||||
function getType(value: unknown) {
|
||||
const typeTable = {
|
||||
'app:datetime': app.util.time.datetime_QMARK_,
|
||||
'cljs:uuid': cljs.core.uuid_QMARK_,
|
||||
'cljs:keyword': cljs.core.keyword_QMARK_,
|
||||
'cljs:vector': cljs.core.vector_QMARK_,
|
||||
'cljs:list': cljs.core.list_QMARK_,
|
||||
'cljs:map': cljs.core.map_QMARK_,
|
||||
'cljs:set': cljs.core.set_QMARK_,
|
||||
'cljs:symbol': cljs.core.symbol_QMARK_,
|
||||
'js:date': (value: unknown) => value instanceof Date,
|
||||
'js:array': (value: unknown) => Array.isArray(value),
|
||||
'js:boolean': (value: unknown) => typeof value === 'boolean',
|
||||
'js:function': (value: unknown) => typeof value === 'function',
|
||||
'js:number': (value: unknown) => typeof value === 'number',
|
||||
'js:string': (value: unknown) => typeof value === 'string',
|
||||
'js:undefined': (value: unknown) => typeof value === 'undefined',
|
||||
'js:null': (value: unknown) => value === null,
|
||||
'js:object': (value: unknown) =>
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
value.toString() === '[object Object]',
|
||||
};
|
||||
|
||||
for (const [type, fn] of Object.entries(typeTable)) {
|
||||
if (fn(value)) return type as keyof typeof typeTable;
|
||||
}
|
||||
|
||||
return 'unknown:unknown' as keyof typeof typeTable;
|
||||
}
|
||||
|
||||
function getKeyName(key: string | number) {
|
||||
if (cljs.core.uuid_QMARK_(key)) {
|
||||
return '#' + cljs.core.name(key);
|
||||
} else if (cljs.core.keyword_QMARK_(key)) {
|
||||
return ':' + cljs.core.name(key);
|
||||
} else if (typeof key === 'string') {
|
||||
return key;
|
||||
} else if (typeof key === 'number') {
|
||||
return `!${key}`;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
function getValue(value: unknown, type: string): unknown {
|
||||
return type in valueTable
|
||||
? valueTable[type as keyof typeof valueTable](value)
|
||||
: value;
|
||||
}
|
||||
|
||||
export function getPartialState(path: string, state: UknowCljs) {
|
||||
// const state = cljs.core.deref(app.main.store.state);
|
||||
const statePath = getPath(path);
|
||||
const data = cljs.core.get_in(state, statePath);
|
||||
const type = getType(data);
|
||||
const isArray = isCljsArray(type);
|
||||
const isExpandable = isTypeExpandable(type);
|
||||
|
||||
const map: Record<string, unknown> = {};
|
||||
const list: unknown[] = [];
|
||||
|
||||
function addEntry(
|
||||
childPath: string,
|
||||
propName: string | number,
|
||||
repValue: unknown,
|
||||
isExpandable: boolean
|
||||
) {
|
||||
if (isArray) {
|
||||
list.push(isExpandable ? getPartialState(childPath, state) : repValue);
|
||||
} else {
|
||||
if (isExpandable) {
|
||||
Object.defineProperty(map, propName, {
|
||||
get() {
|
||||
return getPartialState(childPath, state);
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
} else {
|
||||
map[propName] = repValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isExpandable) {
|
||||
if (type.startsWith('cljs:')) {
|
||||
const cljsData = cljs.core.clj__GT_js(cljs.core.to_array(data));
|
||||
|
||||
cljsData.forEach((entry: unknown, index: number) => {
|
||||
if (cljs.core.map_entry_QMARK_(entry)) {
|
||||
const key = cljs.core.first(entry);
|
||||
const name = getKeyName(key);
|
||||
const value = cljs.core.nth(entry, 1);
|
||||
const valueType = getType(value);
|
||||
const repValue = getValue(value, valueType);
|
||||
const isExpandable = isTypeExpandable(valueType);
|
||||
const childPath = path + PATH_SEPARATOR + name;
|
||||
const propName = name.startsWith(':')
|
||||
? toCamelCase(name.slice(1))
|
||||
: name;
|
||||
|
||||
addEntry(childPath, propName, repValue, isExpandable);
|
||||
|
||||
return;
|
||||
} else {
|
||||
const valueType = getType(entry);
|
||||
const repValue = getValue(entry, valueType);
|
||||
const isExpandable = isTypeExpandable(valueType);
|
||||
const childPath = path + PATH_SEPARATOR + getKeyName(index);
|
||||
|
||||
addEntry(childPath, index, repValue, isExpandable);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else if (type.startsWith('js:')) {
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
map[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
return isArray ? list : map;
|
||||
}
|
||||
|
||||
const repValue = getValue(data, type);
|
||||
|
||||
return repValue;
|
||||
}
|
|
@ -3,7 +3,7 @@ import './lib/plugin-modal';
|
|||
|
||||
import { ɵloadPlugin } from './lib/load-plugin';
|
||||
import { setFileState, setPageState, setSelection, setTheme } from './lib/api';
|
||||
import { getSelectedUuids } from 'plugins-parser';
|
||||
import { getPartialState, getSelectedUuids } from 'plugins-parser';
|
||||
|
||||
repairIntrinsics({
|
||||
evalTaming: 'unsafeEval',
|
||||
|
@ -18,6 +18,10 @@ export function initialize(api: any) {
|
|||
console.log(api);
|
||||
|
||||
/* eslint-disable */
|
||||
(globalThis as any).getPartialState = (path: string) => {
|
||||
return getPartialState(path, api.getState());
|
||||
};
|
||||
|
||||
api.addListener('plugin-page', 'page', (page: any) => {
|
||||
console.log('Page Changed:', page);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue