fulldev-ui 0.1.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.astro/types.d.ts +156 -0
- package/README.md +29 -0
- package/astro.config.mjs +7 -0
- package/package.json +45 -0
- package/src/blocks/todo.md +12 -0
- package/src/components/_Block.astro +20 -0
- package/src/components/_Blocks.astro +26 -0
- package/src/components/_Children.astro +38 -0
- package/src/components/_Plural.astro +27 -0
- package/src/components/_Tag.astro +53 -0
- package/src/components/base/Badge.astro +53 -0
- package/src/components/base/Button.astro +85 -0
- package/src/components/base/Buttons.astro +15 -0
- package/src/components/base/Checkbox.astro +39 -0
- package/src/components/base/Icon.astro +46 -0
- package/src/components/base/Image.astro +123 -0
- package/src/components/base/Images.astro +15 -0
- package/src/components/base/Input.astro +52 -0
- package/src/components/base/Logo.astro +33 -0
- package/src/components/base/Radio.astro +38 -0
- package/src/components/base/Rating.astro +45 -0
- package/src/components/base/Select.astro +65 -0
- package/src/components/base/SelectOption.astro +27 -0
- package/src/components/base/Switch.astro +82 -0
- package/src/components/base/Textarea.astro +31 -0
- package/src/components/base/Video.astro +32 -0
- package/src/components/base/todo.md +8 -0
- package/src/components/typography/Heading.astro +41 -0
- package/src/components/typography/Label.astro +36 -0
- package/src/components/typography/Link.astro +38 -0
- package/src/components/typography/Links.astro +15 -0
- package/src/components/typography/List.astro +42 -0
- package/src/components/typography/ListItem.astro +30 -0
- package/src/components/typography/Paragraph.astro +38 -0
- package/src/components/typography/Tagline.astro +39 -0
- package/src/components/typography/_Typography.astro +28 -0
- package/src/components/typography/todo.md +15 -0
- package/src/components/utility/DecorativeBox.astro +22 -0
- package/src/components/utility/Head.astro +81 -0
- package/src/components/wrapper/Body.astro +32 -0
- package/src/components/wrapper/Card.astro +144 -0
- package/src/components/wrapper/Cards.astro +15 -0
- package/src/components/wrapper/Deck.astro +133 -0
- package/src/components/wrapper/Footer.astro +14 -0
- package/src/components/wrapper/Form.astro +26 -0
- package/src/components/wrapper/Group.astro +26 -0
- package/src/components/wrapper/Header.astro +76 -0
- package/src/components/wrapper/Main.astro +25 -0
- package/src/components/wrapper/Nav.astro +32 -0
- package/src/components/wrapper/Prose.astro +108 -0
- package/src/components/wrapper/Section.astro +110 -0
- package/src/components/wrapper/Sections.astro +15 -0
- package/src/components/wrapper/Writeup.astro +23 -0
- package/src/components/wrapper/_Wrapper.astro +333 -0
- package/src/components/wrapper/todo.md +20 -0
- package/src/content/pages/index.md +2 -0
- package/src/css/border.css +23 -0
- package/src/css/colors.css +328 -0
- package/src/css/font.css +15 -0
- package/src/css/main.css +4 -0
- package/src/css/reset.css +388 -0
- package/src/css/sizes.css +273 -0
- package/src/env.d.ts +2 -0
- package/src/index.ts +63 -0
- package/src/integration/integration.ts +61 -0
- package/src/layouts/Layout.astro +39 -0
- package/src/layouts/todo.md +2 -0
- package/src/schemas/attributesSchema.ts +125 -0
- package/src/schemas/htmlAttributesSchema.ts +126 -0
- package/src/schemas/pageSchema.ts +185 -0
- package/src/schemas/staticPageSchema.ts +124 -0
- package/src/types/Childmorphic.ts +8 -0
- package/src/types/Pluralmorphic.ts +7 -0
- package/src/utils/getAllCollections.ts +10 -0
- package/src/utils/getCollectionCascade.ts +33 -0
- package/src/utils/getPathname.ts +18 -0
- package/src/utils/transform/transform.ts +25 -0
- package/src/utils/transform/transformCasing.ts +24 -0
- package/src/utils/transform/transformReferences.ts +54 -0
- package/src/utils/transform/transformSelfs.ts +20 -0
- package/src/utils/transform/transformUnderscores.ts +19 -0
- package/tsconfig.json +6 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// import type { AstroIntegration } from 'astro'
|
|
2
|
+
// import autoprefixer from 'autoprefixer'
|
|
3
|
+
// import postcssNesting from 'postcss-nesting'
|
|
4
|
+
// import postcssPresetEnv from 'postcss-preset-env'
|
|
5
|
+
// import { mergeDeep } from 'remeda'
|
|
6
|
+
// import virtual from 'vite-plugin-virtual'
|
|
7
|
+
|
|
8
|
+
// const defaultConfig = {
|
|
9
|
+
// color: {
|
|
10
|
+
// accent: 'indigo',
|
|
11
|
+
// base: 'slate',
|
|
12
|
+
// },
|
|
13
|
+
// size: {
|
|
14
|
+
// scale: 1,
|
|
15
|
+
// space: 1,
|
|
16
|
+
// radius: 1,
|
|
17
|
+
// text: 1,
|
|
18
|
+
// },
|
|
19
|
+
// theme: {
|
|
20
|
+
// border: '1px',
|
|
21
|
+
// },
|
|
22
|
+
// font: {
|
|
23
|
+
// heading.text: 'IMB Plex Sans:700',
|
|
24
|
+
// subheading.text: 'IMB Plex Sans:700',
|
|
25
|
+
// text: 'IMB Plex Sans:400',
|
|
26
|
+
// tagline: 'IMB Plex Sans:400',
|
|
27
|
+
// button: 'IMB Plex Sans:500',
|
|
28
|
+
// },
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// export default function fulluiIntegration(userConfig: any): AstroIntegration {
|
|
32
|
+
// const config: any = mergeDeep(defaultConfig || {}, userConfig || {})
|
|
33
|
+
|
|
34
|
+
// return {
|
|
35
|
+
// name: '/integration',
|
|
36
|
+
// hooks: {
|
|
37
|
+
// 'astro:config:setup': async ({
|
|
38
|
+
// // config: astroConfig,
|
|
39
|
+
// updateConfig,
|
|
40
|
+
// injectScript,
|
|
41
|
+
// }) => {
|
|
42
|
+
// updateConfig({
|
|
43
|
+
// vite: {
|
|
44
|
+
// plugins: [
|
|
45
|
+
// virtual({
|
|
46
|
+
// 'virtual:/config': `export default ${JSON.stringify(config)}`,
|
|
47
|
+
// }) as any,
|
|
48
|
+
// ],
|
|
49
|
+
// css: {
|
|
50
|
+
// postcss: {
|
|
51
|
+
// plugins: [postcssNesting, postcssPresetEnv, autoprefixer],
|
|
52
|
+
// },
|
|
53
|
+
// },
|
|
54
|
+
// },
|
|
55
|
+
// })
|
|
56
|
+
|
|
57
|
+
// // injectScript('page-ssr', 'import "fulldev-ui/css";')
|
|
58
|
+
// },
|
|
59
|
+
// },
|
|
60
|
+
// }
|
|
61
|
+
// }
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { ComponentProps } from 'astro/types'
|
|
3
|
+
import Tag from '../components/_Tag.astro'
|
|
4
|
+
import Head from '../components/utility/Head.astro'
|
|
5
|
+
import Body from '../components/wrapper/Body.astro'
|
|
6
|
+
|
|
7
|
+
interface Props extends ComponentProps<typeof Tag> {
|
|
8
|
+
title: ComponentProps<typeof Head>['title']
|
|
9
|
+
description: ComponentProps<typeof Head>['description']
|
|
10
|
+
image: ComponentProps<typeof Head>['image']
|
|
11
|
+
head?: ComponentProps<typeof Head>
|
|
12
|
+
body?: ComponentProps<typeof Body>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { title, description, image, theme, head, body, ...rest } = Astro.props
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<Tag
|
|
19
|
+
class:list={['full-layout']}
|
|
20
|
+
as="html"
|
|
21
|
+
if={true}
|
|
22
|
+
{theme}
|
|
23
|
+
{...rest}
|
|
24
|
+
>
|
|
25
|
+
<Head
|
|
26
|
+
{title}
|
|
27
|
+
{description}
|
|
28
|
+
{image}
|
|
29
|
+
{...head}
|
|
30
|
+
/>
|
|
31
|
+
<Body
|
|
32
|
+
if={true}
|
|
33
|
+
{theme}
|
|
34
|
+
{...body}
|
|
35
|
+
>
|
|
36
|
+
<slot name="before" />
|
|
37
|
+
<slot />
|
|
38
|
+
</Body>
|
|
39
|
+
</Tag>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { z } from 'astro:content'
|
|
2
|
+
|
|
3
|
+
export const attributesSchema = z.object({
|
|
4
|
+
abbr: z.any(),
|
|
5
|
+
accept: z.any(),
|
|
6
|
+
acceptCharset: z.any(),
|
|
7
|
+
accessKey: z.any(),
|
|
8
|
+
allowFullScreen: z.any(),
|
|
9
|
+
allowTransparency: z.any(),
|
|
10
|
+
alt: z.any(),
|
|
11
|
+
async: z.any(),
|
|
12
|
+
autoComplete: z.any(),
|
|
13
|
+
autoFocus: z.any(),
|
|
14
|
+
autoPlay: z.any(),
|
|
15
|
+
cellPadding: z.any(),
|
|
16
|
+
cellSpacing: z.any(),
|
|
17
|
+
challenge: z.any(),
|
|
18
|
+
charset: z.any(),
|
|
19
|
+
checked: z.any(),
|
|
20
|
+
cite: z.any(),
|
|
21
|
+
class: z.any(),
|
|
22
|
+
className: z.any(),
|
|
23
|
+
cols: z.any(),
|
|
24
|
+
colSpan: z.any(),
|
|
25
|
+
command: z.any(),
|
|
26
|
+
content: z.any(),
|
|
27
|
+
contentEditable: z.any(),
|
|
28
|
+
contextMenu: z.any(),
|
|
29
|
+
controls: z.any(),
|
|
30
|
+
coords: z.any(),
|
|
31
|
+
crossOrigin: z.any(),
|
|
32
|
+
data: z.any(),
|
|
33
|
+
dateTime: z.any(),
|
|
34
|
+
default: z.any(),
|
|
35
|
+
defer: z.any(),
|
|
36
|
+
dir: z.any(),
|
|
37
|
+
disabled: z.any(),
|
|
38
|
+
download: z.any(),
|
|
39
|
+
draggable: z.any(),
|
|
40
|
+
dropzone: z.any(),
|
|
41
|
+
encType: z.any(),
|
|
42
|
+
for: z.any(),
|
|
43
|
+
form: z.any(),
|
|
44
|
+
action: z.any(),
|
|
45
|
+
formEncType: z.any(),
|
|
46
|
+
method: z.any(),
|
|
47
|
+
formNoValidate: z.any(),
|
|
48
|
+
target: z.any(),
|
|
49
|
+
frameBorder: z.any(),
|
|
50
|
+
headers: z.any(),
|
|
51
|
+
height: z.any(),
|
|
52
|
+
hidden: z.any(),
|
|
53
|
+
high: z.any(),
|
|
54
|
+
href: z.any(),
|
|
55
|
+
hrefLang: z.any(),
|
|
56
|
+
htmlFor: z.any(),
|
|
57
|
+
httpEquiv: z.any(),
|
|
58
|
+
id: z.any(),
|
|
59
|
+
inputMode: z.any(),
|
|
60
|
+
isMap: z.any(),
|
|
61
|
+
itemId: z.any(),
|
|
62
|
+
itemProp: z.any(),
|
|
63
|
+
itemRef: z.any(),
|
|
64
|
+
itemScope: z.any(),
|
|
65
|
+
itemType: z.any(),
|
|
66
|
+
kind: z.any(),
|
|
67
|
+
label: z.any(),
|
|
68
|
+
lang: z.any(),
|
|
69
|
+
list: z.any(),
|
|
70
|
+
loop: z.any(),
|
|
71
|
+
manifest: z.any(),
|
|
72
|
+
max: z.any(),
|
|
73
|
+
maxLength: z.any(),
|
|
74
|
+
media: z.any(),
|
|
75
|
+
mediaGroup: z.any(),
|
|
76
|
+
min: z.any(),
|
|
77
|
+
minLength: z.any(),
|
|
78
|
+
multiple: z.any(),
|
|
79
|
+
muted: z.any(),
|
|
80
|
+
name: z.any(),
|
|
81
|
+
noValidate: z.any(),
|
|
82
|
+
open: z.any(),
|
|
83
|
+
optimum: z.any(),
|
|
84
|
+
pattern: z.any(),
|
|
85
|
+
ping: z.any(),
|
|
86
|
+
placeholder: z.any(),
|
|
87
|
+
poster: z.any(),
|
|
88
|
+
preload: z.any(),
|
|
89
|
+
rel: z.any(),
|
|
90
|
+
required: z.any(),
|
|
91
|
+
rows: z.any(),
|
|
92
|
+
sizes: z.any(),
|
|
93
|
+
|
|
94
|
+
// role: z.any(),
|
|
95
|
+
// radioGroup: z.any(),
|
|
96
|
+
// readOnly: z.any(),
|
|
97
|
+
// rowSpan: z.any(),
|
|
98
|
+
// sandbox: z.any(),
|
|
99
|
+
// scope: z.any(),
|
|
100
|
+
// scoped: z.any(),
|
|
101
|
+
// scrolling: z.any(),
|
|
102
|
+
// seamless: z.any(),
|
|
103
|
+
// selected: z.any(),
|
|
104
|
+
// shape: z.any(),
|
|
105
|
+
// size: z.any(),
|
|
106
|
+
// sortable: z.any(),
|
|
107
|
+
// span: z.any(),
|
|
108
|
+
// spellCheck: z.any(),
|
|
109
|
+
src: z.any(),
|
|
110
|
+
// srcDoc: z.any(),
|
|
111
|
+
srcset: z.any(),
|
|
112
|
+
// start: z.any(),
|
|
113
|
+
// step: z.any(),
|
|
114
|
+
style: z.any(),
|
|
115
|
+
tabIndex: z.any(),
|
|
116
|
+
title: z.any(),
|
|
117
|
+
// translate: z.any(),
|
|
118
|
+
type: z.any(),
|
|
119
|
+
// typeMustMatch: z.any(),
|
|
120
|
+
// useMap: z.any(),
|
|
121
|
+
value: z.any(),
|
|
122
|
+
width: z.any(),
|
|
123
|
+
// wmode: z.any(),
|
|
124
|
+
// wrap: z.any(),
|
|
125
|
+
})
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const arr = [
|
|
2
|
+
'abbr',
|
|
3
|
+
'accept',
|
|
4
|
+
'acceptCharset',
|
|
5
|
+
'accessKey',
|
|
6
|
+
'action',
|
|
7
|
+
'allowFullScreen',
|
|
8
|
+
'allowTransparency',
|
|
9
|
+
'alt',
|
|
10
|
+
'async',
|
|
11
|
+
'autoComplete',
|
|
12
|
+
'autoFocus',
|
|
13
|
+
'autoPlay',
|
|
14
|
+
'cellPadding',
|
|
15
|
+
'cellSpacing',
|
|
16
|
+
'challenge',
|
|
17
|
+
'charset',
|
|
18
|
+
'checked',
|
|
19
|
+
'cite',
|
|
20
|
+
'class',
|
|
21
|
+
'className',
|
|
22
|
+
'cols',
|
|
23
|
+
'colSpan',
|
|
24
|
+
'command',
|
|
25
|
+
'content',
|
|
26
|
+
'contentEditable',
|
|
27
|
+
'contextMenu',
|
|
28
|
+
'controls',
|
|
29
|
+
'coords',
|
|
30
|
+
'crossOrigin',
|
|
31
|
+
'data',
|
|
32
|
+
'dateTime',
|
|
33
|
+
'default',
|
|
34
|
+
'defer',
|
|
35
|
+
'dir',
|
|
36
|
+
'disabled',
|
|
37
|
+
'download',
|
|
38
|
+
'draggable',
|
|
39
|
+
'dropzone',
|
|
40
|
+
'encType',
|
|
41
|
+
'for',
|
|
42
|
+
'form',
|
|
43
|
+
'formAction',
|
|
44
|
+
'formEncType',
|
|
45
|
+
'formMethod',
|
|
46
|
+
'formNoValidate',
|
|
47
|
+
'formTarget',
|
|
48
|
+
'frameBorder',
|
|
49
|
+
'headers',
|
|
50
|
+
'height',
|
|
51
|
+
'hidden',
|
|
52
|
+
'high',
|
|
53
|
+
'href',
|
|
54
|
+
'hrefLang',
|
|
55
|
+
'htmlFor',
|
|
56
|
+
'httpEquiv',
|
|
57
|
+
'icon',
|
|
58
|
+
'id',
|
|
59
|
+
'inputMode',
|
|
60
|
+
'isMap',
|
|
61
|
+
'itemId',
|
|
62
|
+
'itemProp',
|
|
63
|
+
'itemRef',
|
|
64
|
+
'itemScope',
|
|
65
|
+
'itemType',
|
|
66
|
+
'kind',
|
|
67
|
+
'label',
|
|
68
|
+
'lang',
|
|
69
|
+
'list',
|
|
70
|
+
'loop',
|
|
71
|
+
'manifest',
|
|
72
|
+
'max',
|
|
73
|
+
'maxLength',
|
|
74
|
+
'media',
|
|
75
|
+
'mediaGroup',
|
|
76
|
+
'method',
|
|
77
|
+
'min',
|
|
78
|
+
'minLength',
|
|
79
|
+
'multiple',
|
|
80
|
+
'muted',
|
|
81
|
+
'name',
|
|
82
|
+
'noValidate',
|
|
83
|
+
'open',
|
|
84
|
+
'optimum',
|
|
85
|
+
'pattern',
|
|
86
|
+
'ping',
|
|
87
|
+
'placeholder',
|
|
88
|
+
'poster',
|
|
89
|
+
'preload',
|
|
90
|
+
'radioGroup',
|
|
91
|
+
'readOnly',
|
|
92
|
+
'rel',
|
|
93
|
+
'required',
|
|
94
|
+
'role',
|
|
95
|
+
'rows',
|
|
96
|
+
'rowSpan',
|
|
97
|
+
'sandbox',
|
|
98
|
+
'scope',
|
|
99
|
+
'scoped',
|
|
100
|
+
'scrolling',
|
|
101
|
+
'seamless',
|
|
102
|
+
'selected',
|
|
103
|
+
'shape',
|
|
104
|
+
'size',
|
|
105
|
+
'sizes',
|
|
106
|
+
'sortable',
|
|
107
|
+
'span',
|
|
108
|
+
'spellCheck',
|
|
109
|
+
'src',
|
|
110
|
+
'srcDoc',
|
|
111
|
+
'srcSet',
|
|
112
|
+
'start',
|
|
113
|
+
'step',
|
|
114
|
+
'style',
|
|
115
|
+
'tabIndex',
|
|
116
|
+
'target',
|
|
117
|
+
'title',
|
|
118
|
+
'translate',
|
|
119
|
+
'type',
|
|
120
|
+
'typeMustMatch',
|
|
121
|
+
'useMap',
|
|
122
|
+
'value',
|
|
123
|
+
'width',
|
|
124
|
+
'wmode',
|
|
125
|
+
'wrap',
|
|
126
|
+
]
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCollection,
|
|
3
|
+
getEntries,
|
|
4
|
+
getEntry,
|
|
5
|
+
z,
|
|
6
|
+
type CollectionEntry,
|
|
7
|
+
type CollectionKey,
|
|
8
|
+
} from 'astro:content'
|
|
9
|
+
import { flatten, unflatten } from 'flat'
|
|
10
|
+
import {
|
|
11
|
+
all,
|
|
12
|
+
camel,
|
|
13
|
+
construct,
|
|
14
|
+
get,
|
|
15
|
+
isString,
|
|
16
|
+
mapValues,
|
|
17
|
+
objectify,
|
|
18
|
+
} from 'radash'
|
|
19
|
+
import { mapKeys, merge } from 'remeda'
|
|
20
|
+
|
|
21
|
+
interface Options {
|
|
22
|
+
casing: boolean
|
|
23
|
+
layouts: boolean
|
|
24
|
+
references: boolean
|
|
25
|
+
selfs: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const defaults: Options = {
|
|
29
|
+
casing: true,
|
|
30
|
+
layouts: true,
|
|
31
|
+
references: true,
|
|
32
|
+
selfs: true,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let cascade: any = {}
|
|
36
|
+
|
|
37
|
+
const transformReferences = async (data: object) =>
|
|
38
|
+
await all(
|
|
39
|
+
mapValues(flatten(data) as any, async (value) => {
|
|
40
|
+
if (!isString(value)) return value
|
|
41
|
+
const parts = (value as string).split(' ')
|
|
42
|
+
const results = await all(
|
|
43
|
+
parts.map(async (valuePart) => {
|
|
44
|
+
if (!valuePart.startsWith('$')) return valuePart
|
|
45
|
+
if (valuePart.startsWith('$self')) return valuePart
|
|
46
|
+
|
|
47
|
+
const reference = valuePart.split('.')[0].replace('$', '')
|
|
48
|
+
const collection = reference.split('/')[0]
|
|
49
|
+
const slug = reference.split('/').slice(1).join('/')
|
|
50
|
+
const path = valuePart.split('.').slice(1).join('.')
|
|
51
|
+
|
|
52
|
+
if (collection && slug) {
|
|
53
|
+
let response = await getEntry(collection as CollectionKey, slug)
|
|
54
|
+
const parsed = await pageSchema().parseAsync(response?.data)
|
|
55
|
+
// let response: any = get(cascade, `${collection}/${slug}`)
|
|
56
|
+
const result = get(parsed, path)
|
|
57
|
+
response = undefined
|
|
58
|
+
return result
|
|
59
|
+
} else if (collection) {
|
|
60
|
+
const response = await getCollection(collection as CollectionKey)
|
|
61
|
+
// const response: any = get(cascade, collection)
|
|
62
|
+
const result = response?.map((entry: any) => get(entry?.data, path))
|
|
63
|
+
return result
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return valuePart
|
|
67
|
+
})
|
|
68
|
+
)
|
|
69
|
+
if (results.length == 1) return results[0]
|
|
70
|
+
return results.join(' ')
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
const transformLayouts = (data: object) => {
|
|
75
|
+
const flat: any = flatten(data)
|
|
76
|
+
let store: any = {}
|
|
77
|
+
let i: number = 0
|
|
78
|
+
|
|
79
|
+
const merged = mapKeys(flat, (key) => {
|
|
80
|
+
if (!isString(key)) return key
|
|
81
|
+
const parts = key.split('.')
|
|
82
|
+
const result = parts.map((part) => {
|
|
83
|
+
return part.replace(/^_+/, '')
|
|
84
|
+
})
|
|
85
|
+
const filtered = result.filter(Boolean)
|
|
86
|
+
const joined = filtered.join('.')
|
|
87
|
+
return joined
|
|
88
|
+
})
|
|
89
|
+
const nested = construct(merged)
|
|
90
|
+
return nested
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const transformSelfs = (data: object) => {
|
|
94
|
+
const flat = flatten(data) as any
|
|
95
|
+
const mapped = mapValues(flat, (value) => {
|
|
96
|
+
if (!isString(value)) return value
|
|
97
|
+
const parts = (value as string).split(' ')
|
|
98
|
+
const result = parts.map((part) => {
|
|
99
|
+
if (!part.startsWith('$self')) return part
|
|
100
|
+
const pathParts = part.split('.').slice(1)
|
|
101
|
+
const camelCased = pathParts.map((part) => camel(part))
|
|
102
|
+
const path = camelCased.join('.')
|
|
103
|
+
const result = get(data, path)
|
|
104
|
+
return result ? result : part
|
|
105
|
+
})
|
|
106
|
+
return result.join(' ')
|
|
107
|
+
})
|
|
108
|
+
return unflatten(mapped)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const transformCasing = (object: object) => {
|
|
112
|
+
const flat = flatten(object)
|
|
113
|
+
const mapped = mapKeys(flat, (key) => {
|
|
114
|
+
if (!isString(key)) return key
|
|
115
|
+
const parts = (key as string).split('.')
|
|
116
|
+
const result = parts.map((part) => camel(part))
|
|
117
|
+
return result.join('.')
|
|
118
|
+
})
|
|
119
|
+
return unflatten(mapped)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const buildCascade = async (data: any) => {
|
|
123
|
+
const flat: any = flatten(data)
|
|
124
|
+
const values = Object.values(flat)
|
|
125
|
+
const strings = values.filter(isString)
|
|
126
|
+
const parts = strings.map((value: any) => value.split(' ')).flat()
|
|
127
|
+
const fullpaths = parts.filter(
|
|
128
|
+
(value) => value.startsWith('$') && !value.startsWith('$self')
|
|
129
|
+
)
|
|
130
|
+
const filepaths = fullpaths.map((f) => f.replace('$', '').split('.')[0])
|
|
131
|
+
|
|
132
|
+
const collections = filepaths.filter((f) => !f.includes('/'))
|
|
133
|
+
const collectionsNew = collections.filter((c) => !cascade[c])
|
|
134
|
+
// console.log('collectionsNew', collectionsNew)
|
|
135
|
+
const collectionsPromises = collectionsNew.map((c) => getCollection(c))
|
|
136
|
+
const collectionsResponses = await Promise.all(collectionsPromises)
|
|
137
|
+
const collectionsCascade = objectify(
|
|
138
|
+
collectionsResponses,
|
|
139
|
+
(c: any) => c[0]?.collection
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
const entries = filepaths.filter((f) => f.includes('/'))
|
|
143
|
+
const entriesNew = entries.filter(
|
|
144
|
+
(e) => !cascade[e.split('/').slice(1).join('/')]
|
|
145
|
+
)
|
|
146
|
+
// console.log('entriesNew', entriesNew)
|
|
147
|
+
const entriesResponses = await getEntries(
|
|
148
|
+
entriesNew.map((e) => ({
|
|
149
|
+
collection: e.split('/')[0],
|
|
150
|
+
slug: e.split('/').slice(1).join('/'),
|
|
151
|
+
}))
|
|
152
|
+
)
|
|
153
|
+
const entriesCascade = objectify(
|
|
154
|
+
entriesResponses,
|
|
155
|
+
(e: any) => `${e?.collection}/${e?.slug || e?.id}`
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
cascade = { ...cascade, ...collectionsCascade, ...entriesCascade }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let doIStay = false
|
|
162
|
+
|
|
163
|
+
export const pageSchema = (options: Partial<Options> = {}) =>
|
|
164
|
+
z.any().transform(async (data: CollectionEntry<CollectionKey>['data']) => {
|
|
165
|
+
const { layouts, casing, references, selfs } = merge(defaults, options)
|
|
166
|
+
|
|
167
|
+
// console.log('doIStay', doIStay)
|
|
168
|
+
// console.log('cascade', Object.keys(cascade))
|
|
169
|
+
doIStay = true
|
|
170
|
+
// await buildCascade(data)
|
|
171
|
+
|
|
172
|
+
if (references) data = await transformReferences(data)
|
|
173
|
+
// console.log('references', data)
|
|
174
|
+
|
|
175
|
+
if (layouts) data = transformLayouts(data)
|
|
176
|
+
// console.log('layouts', data)
|
|
177
|
+
|
|
178
|
+
if (casing) data = transformCasing(data)
|
|
179
|
+
// console.log('casing', data)
|
|
180
|
+
|
|
181
|
+
if (selfs) data = transformSelfs(data)
|
|
182
|
+
// console.log('selfs', data)
|
|
183
|
+
|
|
184
|
+
return data
|
|
185
|
+
})
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCollection,
|
|
3
|
+
getEntry,
|
|
4
|
+
z,
|
|
5
|
+
type CollectionEntry,
|
|
6
|
+
type CollectionKey,
|
|
7
|
+
} from 'astro:content'
|
|
8
|
+
import { flatten, unflatten } from 'flat'
|
|
9
|
+
import { all, camel, construct, get, isString, mapValues } from 'radash'
|
|
10
|
+
import { mapKeys, merge } from 'remeda'
|
|
11
|
+
|
|
12
|
+
interface Options {
|
|
13
|
+
casing: boolean
|
|
14
|
+
layouts: boolean
|
|
15
|
+
references: boolean
|
|
16
|
+
selfs: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const defaults: Options = {
|
|
20
|
+
casing: true,
|
|
21
|
+
layouts: true,
|
|
22
|
+
references: true,
|
|
23
|
+
selfs: true,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const transformReferences = async (data: object) =>
|
|
27
|
+
await all(
|
|
28
|
+
mapValues(flatten(data) as any, async (value) => {
|
|
29
|
+
if (!isString(value)) return value
|
|
30
|
+
const parts = (value as string).split(' ')
|
|
31
|
+
const results = await all(
|
|
32
|
+
parts.map(async (valuePart) => {
|
|
33
|
+
if (!valuePart.startsWith('$')) return valuePart
|
|
34
|
+
if (valuePart.startsWith('$self')) return valuePart
|
|
35
|
+
|
|
36
|
+
const reference = valuePart.split('.')[0].replace('$', '')
|
|
37
|
+
const collection = reference.split('/')[0]
|
|
38
|
+
const slug = reference.split('/').slice(1).join('/')
|
|
39
|
+
const path = valuePart.split('.').slice(1).join('.')
|
|
40
|
+
|
|
41
|
+
if (collection && slug) {
|
|
42
|
+
let response = await getEntry(collection as CollectionKey, slug)
|
|
43
|
+
const result = get(response?.data, path)
|
|
44
|
+
return result
|
|
45
|
+
} else if (collection) {
|
|
46
|
+
const response = await getCollection(collection as CollectionKey)
|
|
47
|
+
const result = response?.map((entry: any) => get(entry?.data, path))
|
|
48
|
+
return result
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return valuePart
|
|
52
|
+
})
|
|
53
|
+
)
|
|
54
|
+
if (results.length == 1) return results[0]
|
|
55
|
+
return results.join(' ')
|
|
56
|
+
})
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
const transformLayouts = (data: object) => {
|
|
60
|
+
const flat: any = flatten(data)
|
|
61
|
+
let store: any = {}
|
|
62
|
+
let i: number = 0
|
|
63
|
+
|
|
64
|
+
const merged = mapKeys(flat, (key) => {
|
|
65
|
+
if (!isString(key)) return key
|
|
66
|
+
const parts = key.split('.')
|
|
67
|
+
const result = parts.map((part) => {
|
|
68
|
+
return part.replace(/^_+/, '')
|
|
69
|
+
})
|
|
70
|
+
const filtered = result.filter(Boolean)
|
|
71
|
+
const joined = filtered.join('.')
|
|
72
|
+
return joined
|
|
73
|
+
})
|
|
74
|
+
const nested = construct(merged)
|
|
75
|
+
return nested
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const transformSelfs = (data: object) => {
|
|
79
|
+
const flat = flatten(data) as any
|
|
80
|
+
const mapped = mapValues(flat, (value) => {
|
|
81
|
+
if (!isString(value)) return value
|
|
82
|
+
const parts = (value as string).split(' ')
|
|
83
|
+
const result = parts.map((part) => {
|
|
84
|
+
if (!part.startsWith('$self')) return part
|
|
85
|
+
const pathParts = part.split('.').slice(1)
|
|
86
|
+
const camelCased = pathParts.map((part) => camel(part))
|
|
87
|
+
const path = camelCased.join('.')
|
|
88
|
+
const result = get(data, path)
|
|
89
|
+
return result ? result : part
|
|
90
|
+
})
|
|
91
|
+
return result.join(' ')
|
|
92
|
+
})
|
|
93
|
+
return unflatten(mapped)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const transformCasing = (object: object) => {
|
|
97
|
+
const flat = flatten(object)
|
|
98
|
+
const mapped = mapKeys(flat, (key) => {
|
|
99
|
+
if (!isString(key)) return key
|
|
100
|
+
const parts = (key as string).split('.')
|
|
101
|
+
const result = parts.map((part) => camel(part))
|
|
102
|
+
return result.join('.')
|
|
103
|
+
})
|
|
104
|
+
return unflatten(mapped)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const pageSchema = (options: Partial<Options> = {}) =>
|
|
108
|
+
z.any().transform(async (data: CollectionEntry<CollectionKey>['data']) => {
|
|
109
|
+
const { layouts, casing, references, selfs } = merge(defaults, options)
|
|
110
|
+
|
|
111
|
+
if (references) data = await transformReferences(data)
|
|
112
|
+
// console.log('references', JSON.stringify(data, null, 2))
|
|
113
|
+
|
|
114
|
+
if (layouts) data = transformLayouts(data)
|
|
115
|
+
// console.log('layouts', data)
|
|
116
|
+
|
|
117
|
+
if (casing) data = transformCasing(data)
|
|
118
|
+
// console.log('casing', data)
|
|
119
|
+
|
|
120
|
+
if (selfs) data = transformSelfs(data)
|
|
121
|
+
// console.log('selfs', data)
|
|
122
|
+
|
|
123
|
+
return data
|
|
124
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CollectionKey } from 'astro:content'
|
|
2
|
+
import { getCollection } from 'astro:content'
|
|
3
|
+
|
|
4
|
+
export const getAllCollections = async (names: CollectionKey[]) => {
|
|
5
|
+
const promises = names.map((name) => getCollection(name))
|
|
6
|
+
const resolved = await Promise.all(promises)
|
|
7
|
+
const flattened = resolved.flat()
|
|
8
|
+
const filtered = flattened.filter(Boolean)
|
|
9
|
+
return filtered
|
|
10
|
+
}
|