Add some simple instructions.
Showing
21 changed files
with
642 additions
and
0 deletions
README
0 → 100644
astro.config.mjs
0 → 100644
bin/run
0 → 100755
1 | #!/bin/sh | ||
2 | |||
3 | set -e | ||
4 | |||
5 | TOP_DIR="$(cd "$(dirname "$0")/.."; pwd -P)" | ||
6 | |||
7 | ti_arg="" | ||
8 | if [ -t 0 ]; then | ||
9 | ti_arg="-ti" | ||
10 | fi | ||
11 | docker run --rm $ti_arg \ | ||
12 | -e UID_REMAP=$(id -u) -e GID_REMAP=$(id -g) \ | ||
13 | -v "$TOP_DIR/container-entrypoint.sh:/container-entrypoint.sh" --entrypoint /container-entrypoint.sh \ | ||
14 | -w /srv/app \ | ||
15 | -v "$TOP_DIR:/srv/app" \ | ||
16 | $DOCKER_ARGS \ | ||
17 | node "$@" | ||
18 |
container-entrypoint.sh
0 → 100755
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | if [[ 0 -eq $(id -u) ]]; then | ||
5 | [[ $UID_REMAP ]] && usermod -u $UID_REMAP node | ||
6 | [[ $GID_REMAP ]] && groupmod -g $GID_REMAP node | ||
7 | fi | ||
8 | if [[ $# -eq 0 ]]; then | ||
9 | set -- bash | ||
10 | fi | ||
11 | |||
12 | cmd="$1" | ||
13 | shift | ||
14 | start-stop-daemon -c node -d $PWD -u node --start --exec "$(which "$cmd")" -- "$@" |
lib/api.ts
0 → 100644
1 | import { configureStore } from '@reduxjs/toolkit' | ||
2 | import { createSlice } from '@reduxjs/toolkit' | ||
3 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' | ||
4 | |||
5 | import { parseHtml } from './html.js' | ||
6 | |||
7 | export const configSlice = createSlice({ | ||
8 | name: 'config', | ||
9 | initialState: { | ||
10 | sites: {}, | ||
11 | }, | ||
12 | reducers: { | ||
13 | setSiteConfig(state, { payload: { name, baseUrl } }) { | ||
14 | if (!state.sites[ name ]) state.sites[ name ] = {} | ||
15 | Object.assign(state.sites[ name ], { baseUrl }) | ||
16 | } | ||
17 | }, | ||
18 | selectors: { | ||
19 | getSiteBaseUrl: (state, name) => state.sites?.[ name ]?.baseUrl, | ||
20 | }, | ||
21 | }) | ||
22 | |||
23 | |||
24 | const baseQuery = fetchBaseQuery() | ||
25 | |||
26 | const siteBaseQuery = async (args, api, options) => { | ||
27 | const { site, url } = args | ||
28 | const baseUrl = getSiteBaseUrl(site) | ||
29 | return baseQuery({ ...args, url: `${baseUrl}/${url}` }, api, options) | ||
30 | } | ||
31 | |||
32 | export const sitePageSlice = createApi({ | ||
33 | reducerPath: 'moqui', | ||
34 | tagTypes: ['Page'], | ||
35 | keepUnusedDataFor: 60, | ||
36 | refetchOnReconnect: true, | ||
37 | refetchOnMountOrArgChange: true, | ||
38 | baseQuery: siteBaseQuery, | ||
39 | endpoints: builder => ({ | ||
40 | getPage: builder.query({ | ||
41 | query: (args) => { | ||
42 | const { site, page } = args | ||
43 | return { | ||
44 | site, | ||
45 | url: page, | ||
46 | method: 'GET', | ||
47 | responseHandler: 'text', | ||
48 | } | ||
49 | }, | ||
50 | providesTags: (result, err, args) => { | ||
51 | const { site, page } = args | ||
52 | return [ { type: 'Page', id: { site, page } } ] | ||
53 | }, | ||
54 | }), | ||
55 | }), | ||
56 | }) | ||
57 | |||
58 | export const store = configureStore({ | ||
59 | reducer: { | ||
60 | [ configSlice.reducerPath ]: configSlice.reducer, | ||
61 | [ sitePageSlice.reducerPath ]: sitePageSlice.reducer, | ||
62 | }, | ||
63 | middleware: getDefaultMiddleware => getDefaultMiddleware().concat([ | ||
64 | sitePageSlice.middleware, | ||
65 | ]), | ||
66 | }) | ||
67 | |||
68 | export const getSitePage = async (site, page) => { | ||
69 | const result = await store.dispatch(sitePageSlice.endpoints.getPage.initiate({ site, page })) | ||
70 | if (result.data) result.doc = parseHtml(result.data) | ||
71 | return result | ||
72 | } | ||
73 | |||
74 | export const setSiteConfig = (siteDef) => { | ||
75 | return store.dispatch(configSlice.actions.setSiteConfig(siteDef)) | ||
76 | } | ||
77 | |||
78 | export const getSiteBaseUrl = (name) => { | ||
79 | return configSlice.selectors.getSiteBaseUrl(store.getState(), name) | ||
80 | } | ||
81 | |||
82 | setSiteConfig({ name: 'msd', baseUrl: 'https://myspecialtydoc-d1d234.webflow.io' }) | ||
83 |
lib/astro.ts
0 → 100644
lib/cache.ts
0 → 100644
lib/children.astro
0 → 100644
1 | --- | ||
2 | import Render, { slotPassThrough } from './render.astro' | ||
3 | |||
4 | const { props: { debug, parent, children, replacers, slotHandler } } = Astro | ||
5 | |||
6 | const slotCallback = slotPassThrough(Astro) | ||
7 | |||
8 | //console.log('Children:render', { parent, children, replacers }) | ||
9 | --- | ||
10 | { | ||
11 | Array.isArray(children) ? | ||
12 | children.map((child, index) => <Render debug={debug} parent={parent} node={child} index={index} replacers={replacers} slotHandler={slotHandler}/>) | ||
13 | : !children ? '' | ||
14 | : <Render debug={debug} parent={parent} node={children} index={0} replacers={replacers} slotHandler={slotHandler}/> | ||
15 | } |
lib/custom.astro
0 → 100644
1 | --- | ||
2 | |||
3 | import { slotPassThrough } from './render.astro' | ||
4 | import Children from './children.astro' | ||
5 | |||
6 | const { props: { wrap = false, wrapAttributes = {}, node, replacers, slotHandler } } = Astro | ||
7 | const { name: Name, attributes, children } = node | ||
8 | |||
9 | const CustomName = `custom-${Name}` | ||
10 | const slotCallback = slotPassThrough(Astro) | ||
11 | |||
12 | //console.log('Got custom match', node) | ||
13 | --- | ||
14 | { | ||
15 | wrap ? ( | ||
16 | <CustomName {...wrapAttributes}> | ||
17 | { | ||
18 | node.isSelfClosingTag ? <Name {...attributes}/> | ||
19 | : <Name {...attributes}> | ||
20 | <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/> | ||
21 | </Name> | ||
22 | } | ||
23 | </CustomName> | ||
24 | ) : ( | ||
25 | node.isSelfClosingTag ? <CustomName {...attributes}/> | ||
26 | : <CustomName {...attributes}> | ||
27 | <Children parent={node} children={children} replacers={replacers} slotHandler={slotHandler}/> | ||
28 | </CustomName> | ||
29 | ) | ||
30 | } | ||
31 |
lib/html.ts
0 → 100644
1 | import nodeUtil from 'util' | ||
2 | import NodeCache from 'node-cache' | ||
3 | |||
4 | import { | ||
5 | parse as umParse, | ||
6 | render as umRender, | ||
7 | transform as umTransform, | ||
8 | __unsafeHTML, | ||
9 | ELEMENT_NODE, | ||
10 | TEXT_NODE, | ||
11 | walkSync, | ||
12 | } from 'ultrahtml' | ||
13 | |||
14 | import { | ||
15 | parse as elParse, | ||
16 | specificity as getSpecificity, | ||
17 | specificityToNumber, | ||
18 | } from 'parsel-js' | ||
19 | |||
20 | import { parsedHtmlCache, selectorCache, findNodeCache } from './cache.js' | ||
21 | |||
22 | // TODO: implement a parent/child/element cache | ||
23 | const filterChildElements = (parent) => parent?.children?.filter(n => n.type === ELEMENT_NODE) || [] | ||
24 | const nthChildPos = (node, parent) => filterChildElements(parent).findIndex((child) => child === node); | ||
25 | |||
26 | const makeNthChildPosMatcher = (ast) => { | ||
27 | const { argument } = ast | ||
28 | const n = Number(argument) | ||
29 | if (!Number.isNaN(n)) { | ||
30 | return (context, node, parent, i) => { | ||
31 | return i === n | ||
32 | } | ||
33 | } | ||
34 | switch (argument) { | ||
35 | case 'odd': | ||
36 | return (context, node, parent, i) => Math.abs(i % 2) === 1 | ||
37 | case 'even': | ||
38 | return (context, node, parent, i) => i % 2 === 0 | ||
39 | default: { | ||
40 | if (!argument) throw new Error(`Unsupported empty nth-child selector!`) | ||
41 | let [_, A = '1', B = '0'] = /^\s*(?:(-?(?:\d+)?)n)?\s*\+?\s*(\d+)?\s*$/gm.exec(argument) ?? [] | ||
42 | if (A.length === 0) A = '1' | ||
43 | const a = Number.parseInt(A === '-' ? '-1' : A) | ||
44 | const b = Number.parseInt(B) | ||
45 | const nth = (index) => (a * n) + b | ||
46 | return (context, node, parent, i) => { | ||
47 | const elements = filterChildElements(parent) | ||
48 | for (let index = 0; index < elements.length; index++) { | ||
49 | const n = nth(index) | ||
50 | if (n > elements.length) return false | ||
51 | if (n === i) return true | ||
52 | } | ||
53 | return false | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | const getAttrValueMatch = (value, operator = '=', caseSenstive) => { | ||
60 | if (value === undefined) return (attrValue) => attrValue !== undefined | ||
61 | const isCaseInsenstive = caseSensitive === 'i' | ||
62 | if (isCaseInsensitive) value = value.toLowerCase() | ||
63 | const adjustMatcher = (matcher) => isCaseInsensitive ? (attrValue) => matcher(attrValue.toLowerCase()) : matcher | ||
64 | switch (operator) { | ||
65 | case '=': return (attrValue) => value === attrValue | ||
66 | case '~=': { | ||
67 | const keys = value.split(/\s+/g).reduce((keys, item) => { | ||
68 | keys[ item ] = true | ||
69 | return keys | ||
70 | }, {}) | ||
71 | return adjustMatcher((attrValue) => keys[ attrValue ]) | ||
72 | } | ||
73 | case '|=': return adjustMatcher((attrValue) => value.startsWith(attrValue + '-')) | ||
74 | case '*=': return adjustMatcher((attrValue) => value.indexOf(attrValue) > -1) | ||
75 | case '$=': return adjustMatcher((attrValue) => value.endsWith(attrValue)) | ||
76 | case '^=': return adjustMatcher((attrValue) => value.startsWith(attrValue)) | ||
77 | } | ||
78 | return (attrValue) => false | ||
79 | } | ||
80 | |||
81 | const compileMatcher = (ast, selector) => { | ||
82 | let counter = 0 | ||
83 | |||
84 | const neededContext = [] | ||
85 | const makeMatcher = (ast) => { | ||
86 | //console.log('makeMatcher', ast) | ||
87 | switch (ast.type) { | ||
88 | case 'list': { | ||
89 | const matchers = ast.list.map(s => makeMatcher(s)) | ||
90 | return (context, node, parent, i, debug) => { | ||
91 | for (const matcher of matchers) { | ||
92 | if (!matcher(context, node, parent, i)) return false | ||
93 | } | ||
94 | return true | ||
95 | } | ||
96 | } | ||
97 | case 'compound': { | ||
98 | const matchers = ast.list.map(s => makeMatcher(s)) | ||
99 | return (context, node, parent, i, debug) => { | ||
100 | for (const matcher of matchers) { | ||
101 | if (!matcher(context, node, parent, i)) return false | ||
102 | } | ||
103 | return true | ||
104 | } | ||
105 | } | ||
106 | case 'complex': { | ||
107 | const { left, right, combinator, pos } = ast | ||
108 | const leftMatcher = makeMatcher(left) | ||
109 | const rightMatcher = makeMatcher(right) | ||
110 | const setCounter = counter++ | ||
111 | neededContext[ setCounter ] = () => new WeakSet() | ||
112 | return (context, node, parent, i, debug) => { | ||
113 | const seen = context[ setCounter ] | ||
114 | if (leftMatcher(context, node, parent, i, debug)) { | ||
115 | if (debug) console.log('matched on left', { left, right, combinator, pos, parent }) | ||
116 | // TODO: Check seen.has(), and maybe skip calling leftMatcher? | ||
117 | seen.add(node) | ||
118 | } else if (parent && seen.has(parent) && combinator === ' ') { | ||
119 | seen.add(node) | ||
120 | } | ||
121 | if (!rightMatcher(context, node, parent, i, debug)) return false | ||
122 | seen.add(node) | ||
123 | if (debug) console.log('matched on right', { left, right, combinator, pos, node, parent }) | ||
124 | switch (combinator) { | ||
125 | case ' ': | ||
126 | let parentPtr = parent | ||
127 | while (parentPtr) { | ||
128 | if (seen.has(parentPtr)) return true | ||
129 | parentPtr = parentPtr.parent | ||
130 | } | ||
131 | return false | ||
132 | case '>': | ||
133 | if (debug) console.log('seen parent', seen.has(parent)) | ||
134 | return parent ? seen.has(parent) : false | ||
135 | case '+': { | ||
136 | if (!parent) return false | ||
137 | let prevSiblings = parent.children.slice(0, i).filter((el) => el.type === ELEMENT_NODE) | ||
138 | if (prevSiblings.length === 0) return false | ||
139 | const prev = prevSiblings[prevSiblings.length - 1] | ||
140 | if (!prev) return false | ||
141 | if (seen.has(prev)) return true | ||
142 | return false | ||
143 | } | ||
144 | case '~': { | ||
145 | if (!parent) return false | ||
146 | let prevSiblings = parent.children.slice(0, i).filter((el) => el.type === ELEMENT_NODE) | ||
147 | if (prevSiblings.length === 0) return false | ||
148 | for (const prev of prevSiblings) { | ||
149 | if (seen.has(prev)) return true | ||
150 | } | ||
151 | return false | ||
152 | } | ||
153 | default: | ||
154 | return false | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | case 'type': { | ||
159 | const { name, content } = ast | ||
160 | if (content === '*') return (context, node, parent, i) => true | ||
161 | return (context, node, parent, i, debug) => node.name === name | ||
162 | } | ||
163 | case 'class': { | ||
164 | const { name } = ast | ||
165 | return (context, node, parent, i, debug) => node.attributes?.['class']?.split(/\s+/g).includes(name) | ||
166 | } | ||
167 | case 'id': { | ||
168 | const { name } = ast | ||
169 | return (context, node, parent, i, debug) => node.attributes?.id === name | ||
170 | } | ||
171 | case 'pseudo-class': | ||
172 | switch (ast.name) { | ||
173 | case 'global': | ||
174 | return makeMatcher(elParse(ast.argument)) | ||
175 | case 'not': { | ||
176 | const matcher = makeMatcher(ast.subtree) | ||
177 | return (...args) => !matcher(...args) | ||
178 | } | ||
179 | case 'is': | ||
180 | return makeMatcher(ast.subtree) | ||
181 | case 'where': | ||
182 | return makeMatcher(ast.subtree) | ||
183 | case 'root': | ||
184 | return (context, node, parent, i) => !node.parent | ||
185 | case 'empty': | ||
186 | return (context, node, parent, i, debug) => { | ||
187 | if (node.type !== ELEMENT_NODE) return false | ||
188 | const { children } = node | ||
189 | if (children.length === 0) return false | ||
190 | return children.every(child => child.type === TEXT_NODE && child.value.trim() === '') | ||
191 | } | ||
192 | case 'first-child': | ||
193 | return (context, node, parent, i, debug) => { | ||
194 | return parent?.children.findFirst(child => child.type === ELEMENT_NODE) === node | ||
195 | } | ||
196 | case 'last-child': | ||
197 | return (context, node, parent, i, debug) => { | ||
198 | return parent?.children.findLast(child => child.type === ELEMENT_NODE) === node | ||
199 | } | ||
200 | case 'only-child': | ||
201 | return (context, node, parent, i, debug) => { | ||
202 | // TODO: This can break-early after it finds the second element | ||
203 | return filterChildElements(parent).length === 1 | ||
204 | } | ||
205 | case 'nth-child': { | ||
206 | const nthChildMatcher = makeNthChildPosMatcher(ast) | ||
207 | return (context, node, parent, i, debug) => { | ||
208 | const pos = nthChildPos(node, parent) + 1 | ||
209 | return nthChildMatcher(context, node, parent, pos) | ||
210 | } | ||
211 | } | ||
212 | default: | ||
213 | throw new Error(`Unknown pseudo-class: ${ast.name}`) | ||
214 | } | ||
215 | case 'attribute': | ||
216 | const { caseSensitive, name, value, operator } = ast | ||
217 | const attrValueMatch = getAttrValueMatch(value, operator, caseSenstive) | ||
218 | return (context, node, parent, i, debug) => { | ||
219 | const { attributes: { [ name ]: attrValue } = {} } = node | ||
220 | return attrValueMatch(attrValue) | ||
221 | } | ||
222 | case 'universal': | ||
223 | return (context, node, parent, i, debug) => true | ||
224 | default: | ||
225 | throw new Error(`Unhandled ast: ${ast.type}`) | ||
226 | } | ||
227 | } | ||
228 | const matcher = makeMatcher(ast) | ||
229 | return () => { | ||
230 | const context = neededContext.map(item => item()) | ||
231 | const nodeMatcher = (node, parent, i, debug) => { | ||
232 | //if (debug) console.log('starting to match', {node, context}) | ||
233 | return matcher(context, node, parent, i, debug) | ||
234 | } | ||
235 | nodeMatcher.toString = () => { | ||
236 | return '[matcher:' + selector + ']' | ||
237 | } | ||
238 | return nodeMatcher | ||
239 | } | ||
240 | } | ||
241 | |||
242 | export const createMatcher = (selector) => { | ||
243 | const matcherCreater = selectorCache.get(selector) | ||
244 | if (false && matcher) return matcherCreater() | ||
245 | const ast = elParse(selector) | ||
246 | //console.log('createMatcher', nodeUtil.inspect({ selector, ast }, { depth: null, colors: true })) | ||
247 | const newMatcherCreater = compileMatcher(ast, selector) | ||
248 | selectorCache.set(selector, newMatcherCreater) | ||
249 | return newMatcherCreater() | ||
250 | } | ||
251 | |||
252 | export const parseHtml = (html) => { | ||
253 | const cached = parsedHtmlCache.get(html) | ||
254 | if (cached) return cached | ||
255 | const doc = umParse(html) | ||
256 | parsedHtmlCache.set(html, doc) | ||
257 | return doc | ||
258 | } | ||
259 | |||
260 | export const findNode = (doc, selector) => { | ||
261 | if (!selector) return doc | ||
262 | let docCache = findNodeCache.get(doc) | ||
263 | if (!docCache) { | ||
264 | docCache = new NodeCache({ stdTTL: 10*60, useClones: false }) | ||
265 | findNodeCache.set(doc, docCache) | ||
266 | } | ||
267 | const found = docCache.get(selector) | ||
268 | if (found !== undefined) return found[0] | ||
269 | //console.log('cache miss', {selector}) | ||
270 | const matcher = createMatcher(selector) | ||
271 | try { | ||
272 | walkSync(doc, (node, parent, index) => { | ||
273 | if (matcher(node, parent, index)) throw node | ||
274 | }) | ||
275 | } catch (e) { | ||
276 | if (e instanceof Error) throw e | ||
277 | docCache.set(selector, [ e ]) | ||
278 | return e | ||
279 | } | ||
280 | } |
lib/render.astro
0 → 100644
1 | --- | ||
2 | import { ELEMENT_NODE, TEXT_NODE } from 'ultrahtml' | ||
3 | import Children from './children.astro' | ||
4 | |||
5 | export const slotPassThrough = (Astro) => (slotName, node) => { | ||
6 | console.log('calling slot', { slotName, node, Astro }) | ||
7 | return Astro.slots.render('default', [ slotName, node ]) | ||
8 | } | ||
9 | |||
10 | const { props: { debug = false, parent = null, node, index = 0, replacers, slotHandler } } = Astro | ||
11 | const { name: Name, attributes } = node | ||
12 | |||
13 | if (debug) { | ||
14 | console.log('trying to match against', {node}) | ||
15 | } | ||
16 | let slotName | ||
17 | for (const [ matcher, handler ] of replacers) { | ||
18 | if (debug) console.log('attempting matcher', matcher.toString()) | ||
19 | if (matcher(node, parent, index, false)) { | ||
20 | if (debug) console.log('matched') | ||
21 | slotName = handler | ||
22 | } | ||
23 | } | ||
24 | |||
25 | //const slotCallback = slotPassThrough(Astro) | ||
26 | --- | ||
27 | { | ||
28 | slotName ? slotHandler(slotName, node) | ||
29 | : node.type === TEXT_NODE ? <Fragment set:html={node.value}/> | ||
30 | : node.type === ELEMENT_NODE ? ( | ||
31 | node.isSelfClosingTag ? <Name {...attributes}/> | ||
32 | : <Name {...attributes}> | ||
33 | <Children parent={node} children={node.children} replacers={replacers} slotHandler={slotHandler}/> | ||
34 | </Name> | ||
35 | ) : ( | ||
36 | <Children parent={node} children={node.children} replacers={replacers} slotHandler={slotHandler}/> | ||
37 | ) | ||
38 | } |
lib/replace.astro
0 → 100644
1 | --- | ||
2 | import html from '@resources/provider-portal.html?raw' | ||
3 | import { walkSync } from 'ultrahtml' | ||
4 | import { parseHtml, createMatcher, findNode } from './html.js' | ||
5 | import Render from './render.astro' | ||
6 | |||
7 | const { props } = Astro | ||
8 | const { html, mapClassname = true, xpath, replacements = {} } = props | ||
9 | const doc = props.node ? props.node : parseHtml(props.html) | ||
10 | |||
11 | const node = xpath ? findNode(doc, xpath) : doc | ||
12 | const replacers = Object.entries(replacements).map(([ selector, handler ]) => [ createMatcher(selector), handler ]) | ||
13 | const fixAttributes = ({ attributes }) => { | ||
14 | if (!mapClassname) return attributes | ||
15 | const { class: className, ...rest } = attributes | ||
16 | return { ...rest, className } | ||
17 | } | ||
18 | |||
19 | const slotHandler = (slotName, node) => { | ||
20 | const attributes = fixAttributes(node) | ||
21 | return Astro.slots.render(slotName, [ { ...node, attributes }, { slotHandler, replacers } ] ) | ||
22 | } | ||
23 | --- | ||
24 | <Render node={node} replacers={replacers} slotHandler={slotHandler}/> |
package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
package.json
0 → 100644
1 | { | ||
2 | "name": "astro-wt", | ||
3 | "type": "module", | ||
4 | "exports": { | ||
5 | "./astro": "./src/astro.mjs", | ||
6 | "./client": "./src/client.mjs", | ||
7 | "./slices": "./src/slices.mjs", | ||
8 | "./react": "./src/react.jsx", | ||
9 | "./session": "./src/session.mjs", | ||
10 | "./ReduxIsland": "./src/ReduxIsland.astro" | ||
11 | }, | ||
12 | "scripts": { | ||
13 | "dev": "astro dev" | ||
14 | }, | ||
15 | "dependencies": { | ||
16 | "@reduxjs/toolkit": "^2.2.5", | ||
17 | "node-cache": "^5.1.2", | ||
18 | "parsel-js": "^1.1.2", | ||
19 | "ultrahtml": "^1.5.3" | ||
20 | }, | ||
21 | "devDependencies": { | ||
22 | "@astrojs/node": "^8.2.5", | ||
23 | "@astrojs/react": "^3.3.4", | ||
24 | "astro": "^4.8.7", | ||
25 | "react": "^18.3.1" | ||
26 | } | ||
27 | } |
src/components/EventDetails.jsx
0 → 100644
src/config.ts
0 → 100644
src/env.d.ts
0 → 100644
1 | /// <reference types="astro/client" /> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/layouts/base.astro
0 → 100644
1 | --- | ||
2 | import { getSitePage } from '@lib/api.ts' | ||
3 | import { Replace } from '@lib/astro.ts' | ||
4 | import '@config.ts' | ||
5 | |||
6 | const { data: layoutHtml } = await getSitePage('msd', '/') | ||
7 | const layoutReplacements = { | ||
8 | ['.hero-section']: 'content', | ||
9 | ['.content-section']: 'DELETE', | ||
10 | ['.content-section-4']: 'DELETE', | ||
11 | //['.navbar.w-nav:nth-child(n + 1)']: 'DELETE', | ||
12 | // The following 2 are not implemented yet | ||
13 | //[':nth-child(n + 1 of .navbar.w-nav)']: 'DELETE', | ||
14 | //['.navbar.w-nav:nth-of-type(n + 1)']: 'DELETE', | ||
15 | } | ||
16 | --- | ||
17 | <Replace debug={true} html={layoutHtml} replacements={layoutReplacements}> | ||
18 | <define slot="DELETE">{(node) => ''}</define> | ||
19 | <define slot='content'>{(node) => <slot/>}</define> | ||
20 | </Replace> |
src/pages/index.astro
0 → 100644
1 | --- | ||
2 | import { getSitePage } from '@lib/api.ts' | ||
3 | import { Replace } from '@lib/astro.ts' | ||
4 | import BaseLayout from '@layouts/base.astro' | ||
5 | import { Demographics } from '@components/EventDetails.jsx' | ||
6 | |||
7 | const { data: layoutHtml } = await getSitePage('msd', '/') | ||
8 | const { data: pageHtml } = await getSitePage('msd', '/provider-portal') | ||
9 | const pageReplacements = { | ||
10 | ['#w-node-_3615b991-cc00-f776-58c2-a728a0fba1a9-70cc1f5d']: 'Demographics', | ||
11 | ['#w-node-eaef93e0-275c-ff2c-39b3-0cc9b81495f3-70cc1f5d .div-block-11']: 'DELETE', | ||
12 | ['#w-node-eaef93e0-275c-ff2c-39b3-0cc9b81495f3-70cc1f5d > .div-block-8 img']: 'custom', | ||
13 | ['#w-node-eaef93e0-275c-ff2c-39b3-0cc9b81495f3-70cc1f5d > .div-block-8']: 'Comms', | ||
14 | ['#w-node-a9641a71-b768-107f-2209-4491bf21ed0a-70cc1f5d > .textblock']: 'ChiefComplaint', | ||
15 | ['#w-node-bbdf8d21-dc38-5a20-e2b8-38fbe2e0f88a-70cc1f5d > .textblock']: 'HealthHistory', | ||
16 | ['#w-node-_4b7383d7-9725-37cd-1d15-d6292436eb85-70cc1f5d .textblock']: 'Subjective', | ||
17 | // ['#w-node-a97d0be9-a1a9-af1d-a30b-f54664c79b09-70cc1f5d > .textblock']: 'ObjectiveLevels', | ||
18 | ['#w-node-_8c10d845-8d0d-25e6-d1da-42fc4c0faa17-70cc1f5d > .textblock']: 'Objective', | ||
19 | ['#w-node-_77cf40d0-cb39-d173-d0ed-0a30bcbbda03-70cc1f5d ~ .div-block-15 > .textblock']: 'Assessment', | ||
20 | ['#w-node-f55c4197-553d-142d-be0f-1364e3d5ce27-70cc1f5d .textblock']: 'Assessment', | ||
21 | ['#w-node-_993bee43-3117-30d9-0b03-cb9d32541bb9-70cc1f5d > .textblock']: 'Formulary', | ||
22 | ['#w-node-_1817664f-14e2-687e-1460-429ef0a62ab3-70cc1f5d .textblock']: 'Plan', | ||
23 | } | ||
24 | --- | ||
25 | <BaseLayout> | ||
26 | <Replace html={pageHtml} xpath='.container-2.w-container' replacements={pageReplacements}> | ||
27 | <define slot='DELETE'>{(node, context) => ''}</define> | ||
28 | <define slot='Demographics'>{(node, context) => <Demographics/>}</define> | ||
29 | </Replace> | ||
30 | </BaseLayout> |
-
Please register or sign in to post a comment