@stackbit/annotations
Version:
Stackbit annotations utils
93 lines (84 loc) • 3.07 kB
text/typescript
export const StackbitObjectIdAttrName = 'data-sb-object-id';
export const StackbitFieldPathAttrName = 'data-sb-field-path';
export type StackbitObjectId = { [StackbitObjectIdAttrName]?: string };
export type StackbitFieldPath = { [StackbitFieldPathAttrName]?: string };
export type StackbitAnnotations = StackbitObjectId & StackbitFieldPath;
export function getObjectId(props?: StackbitObjectId): string | undefined {
return props?.[StackbitObjectIdAttrName];
}
export function getFieldPath(props?: StackbitFieldPath): string | undefined {
return props?.[StackbitFieldPathAttrName];
}
/**
* Takes a string and returns an object with that string wrapped into the
* `data-sb-object-id` attribute.
*
* @example
* toObjectId('xyz')
* => { 'data-sb-object-id': 'xyz' }
*
* @param objectId
*/
export function toObjectId(objectId?: string): StackbitObjectId {
if (process.env.NODE_ENV === 'production') {
return {};
}
if (!objectId) {
return {};
}
return { [StackbitObjectIdAttrName]: objectId };
}
export type FieldPathDescriptor = ({ fieldPath: string } | { fp: string }) & ({ objectId?: string } | { oid?: string }) & { xpath?: string };
/**
* Takes field-path and returns an object with all field-paths concatenated into
* the `data-sb-field-path` attribute. Each field-path can be a string or a
* FieldPathDescriptor.
*
* @example
* toFieldPath('.button', { objectId: 'xyz', fieldPath: 'link', xpath: '@href' })
* => { 'data-sb-field-path': '.button xyz:link#@href' }
*
* toFieldPath({ oid: 'abc', fp: 'image', xpath: 'img[1]/@src' })
* => { 'data-sb-field-path': 'abc:image#img[1]/@src' }
*
* @param fieldPaths
*/
export function toFieldPath(...fieldPaths: (undefined | null | string | FieldPathDescriptor)[]): StackbitFieldPath {
if (process.env.NODE_ENV === 'production') {
return {};
}
const fieldPath = fieldPaths
.map((fieldPath) => {
if (!fieldPath) {
return null;
}
if (typeof fieldPath === 'string') {
return fieldPath;
}
const fp = 'fieldPath' in fieldPath ? fieldPath.fieldPath : fieldPath.fp;
const oid = 'objectId' in fieldPath ? fieldPath.objectId : 'oid' in fieldPath ? fieldPath.oid : '';
const xpath = 'xpath' in fieldPath ? fieldPath.xpath : '';
return (oid ? `${oid}:` : '') + fp + (xpath ? `#${xpath}` : '');
})
.filter(Boolean)
.join(' ')
.trim();
return fieldPath ? { [StackbitFieldPathAttrName]: fieldPath } : {};
}
/**
* Takes an object and returns a new object with only the properties that start
* with `data-`
*
* @param props
*/
export function pickDataAttrs(props?: Record<string, any>): Record<string, any> {
if (!props) {
return {};
}
return Object.entries(props).reduce((dataAttrs: Record<string, any>, [key, value]) => {
if (key.startsWith('data-')) {
dataAttrs[key] = value;
}
return dataAttrs;
}, {});
}