-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,116 @@ | ||
import { DecapCmsField } from 'vite-plugin-decap-cms' | ||
import { createField, DecapCmsField, fieldToSnakeCase, Options } from 'vite-plugin-decap-cms' | ||
|
||
type Block = NonNullable<NonNullable<Options['script']>['markdownEditorComponents']>[number] | ||
|
||
interface ComponentBlockOptions { | ||
id: string | ||
label: string | ||
props: DecapCmsField[] | ||
templateField?: { | ||
label: string | ||
labelSingular: string | ||
nameLabel?: string | ||
contentLabel?: string | ||
names?: string[] | ||
} | ||
} | ||
|
||
// TODO: fix enters while transitioning | ||
function createComponentBlock (options: ComponentBlockOptions): Block { | ||
const { id, label, props, templateField } = options | ||
|
||
interface ComponentData { | ||
templates: { | ||
name: string | null; | ||
content: string; | ||
}[] | ||
props: Record<string, unknown> | ||
} | ||
|
||
return { | ||
id, | ||
label, | ||
pattern: new RegExp(`^<${id}(.*)>((.|\\n)*?)<\\/${id}>$`, 'm'), | ||
fields: [ | ||
createField('object', { | ||
name: 'props', | ||
label: 'Properties', | ||
required: false, | ||
collapsed: true, | ||
fields: props.map(fieldToSnakeCase), | ||
}), | ||
templateField != undefined ? createField('list', { | ||
name: 'templates', | ||
label: templateField.label, | ||
label_singular: templateField.labelSingular, | ||
allow_add: true, | ||
required: false, | ||
min: 1, | ||
fields: [ | ||
createField(templateField.names ? 'select' : 'string', { | ||
name: 'name', | ||
required: false, | ||
label: templateField.nameLabel ?? 'Name', | ||
// @ts-expect-error | ||
Check failure on line 54 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
Check failure on line 54 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v20
|
||
options: templateField.names, | ||
}), | ||
createField('markdown', { | ||
name: 'content', | ||
required: true, | ||
label: templateField.contentLabel ?? 'Content', | ||
}), | ||
].filter((n): n is NonNullable<typeof n> => n != undefined), | ||
}) : undefined, | ||
].filter(n => n) as Block['fields'], | ||
fromBlock: function (match): ComponentData { | ||
console.log(match) | ||
const props = match.at(1), slots = match.at(2) | ||
|
||
return { | ||
props: props != undefined | ||
? props.split(/(?= :)(?<=")/) | ||
.map(str => str.trim().replace(':', '').split('=', 2)) | ||
.reduce((obj, value) => ({ ...obj, [value[0]]: value[1] }), {}) | ||
: {}, | ||
templates: slots != undefined | ||
? slots.split('</template>').filter(str => str.length).map((slot) => { | ||
//@ts-ignore | ||
Check failure on line 77 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
Check warning on line 77 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
Check failure on line 77 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v20
|
||
const results = /^<template #(.*)>(.*)/ms.exec(slot) ?? [] | ||
console.log([slots], slot, results) | ||
const name = results.at(1) | ||
|
||
return { | ||
name: name ?? null, | ||
content: results.at(2) ?? slot, | ||
} | ||
}) : [], | ||
} | ||
}, | ||
toBlock: function (data: ComponentData) { | ||
const templates = data.templates.map(({ name, content }) => { | ||
return `<template${name ? ` #${name}` : ''}>\n${content}\n</template>` | ||
}) | ||
|
||
Check warning on line 93 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
|
||
const props = Object.entries(data.props) | ||
.reduce((str, prop) => str + ` :${prop[0]}="${prop[1]}"`, ' ') | ||
|
||
Check warning on line 96 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
|
||
return `<${id}${props}>\n${templates}\n</${id}>` | ||
}, | ||
toPreview: function (data: ComponentData) { | ||
Check warning on line 99 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
Check failure on line 99 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
Check warning on line 99 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v20
|
||
return '' | ||
}, | ||
} | ||
} | ||
|
||
type BlockFields = { summary?: string, contents: string, type: string } | ||
|
||
export const customContainerBlock = { | ||
const customContainerBlock: Block = { | ||
id: 'custom-block', | ||
label: 'Custom block', | ||
label: 'Custom comtainer', | ||
fields: [ | ||
{ | ||
name: 'type', | ||
label: 'Type of block', | ||
label: 'Type of comtainer', | ||
widget: 'select', | ||
required: true, | ||
options: [ | ||
|
@@ -36,7 +138,7 @@ export const customContainerBlock = { | |
] satisfies DecapCmsField[], | ||
// @ts-expect-error Needs flag to work | ||
pattern: /^:::(\w+)(.*?)\n(.*?)\n^:::$/ms, | ||
fromBlock: function (match: RegExpMatchArray): BlockFields { | ||
fromBlock: function (match): BlockFields { | ||
Check warning on line 141 in docs/.vitepress/config/cms/blocks.ts GitHub Actions / Lint & test v18
|
||
return { | ||
type: match[1], | ||
summary: match[2], | ||
|
@@ -50,3 +152,61 @@ export const customContainerBlock = { | |
return `:::${data.type} ${data.summary}\n${data.contents}\n:::` | ||
}, | ||
} | ||
|
||
export default [ | ||
customContainerBlock, | ||
createComponentBlock({ | ||
id: 'steps', | ||
label: 'Steps component', | ||
templateField: { | ||
label: 'Steps', | ||
labelSingular: 'step', | ||
}, | ||
props: [ | ||
createField('string', { | ||
name: 'color', | ||
label: 'Color', | ||
required: false, | ||
}), | ||
], | ||
}), | ||
createComponentBlock({ | ||
id: 'tabs', | ||
label: 'Tabs component', | ||
templateField: { | ||
label: 'Tabs', | ||
labelSingular: 'tab', | ||
nameLabel: 'Id', | ||
}, | ||
props: [ | ||
createField('list', { | ||
name: 'tabs', | ||
label: 'Tab names', | ||
label_singular: 'name', | ||
allow_add: true, | ||
required: true, | ||
}), | ||
createField('string', { | ||
name: 'startTab', | ||
label: 'Start tab name', | ||
required: false, | ||
}), | ||
createField('string', { | ||
name: 'searchParam', | ||
label: 'Search parameter', | ||
required: false, | ||
}), | ||
] | ||
}), | ||
createComponentBlock({ | ||
id: 'ActionBlock', | ||
label: 'Action block component', | ||
templateField: { | ||
label: 'Content', | ||
labelSingular: 'content', | ||
names: ['left', 'right'], | ||
nameLabel: 'Position', | ||
}, | ||
props: [], | ||
}), | ||
] |