@builder.io/sdk-solid 0.0.8-23 → 0.0.8-24
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/package.json +1 -1
- package/src/blocks/columns/columns.jsx +41 -44
- package/src/blocks/columns/component-info.js +3 -2
- package/src/blocks/custom-code/custom-code.jsx +34 -37
- package/src/blocks/embed/component-info.js +3 -2
- package/src/blocks/embed/embed.jsx +28 -31
- package/src/blocks/form/form.jsx +172 -173
- package/src/blocks/image/component-info.js +3 -2
- package/src/blocks/image/image.jsx +26 -29
- package/src/blocks/img/img.jsx +1 -1
- package/src/blocks/symbol/symbol.jsx +10 -13
- package/src/blocks/util.js +7 -0
- package/src/blocks/video/video.jsx +19 -23
- package/src/components/render-block/block-styles.jsx +22 -27
- package/src/components/render-block/render-block.jsx +155 -159
- package/src/components/render-block/render-component.jsx +2 -2
- package/src/components/render-block/render-repeated-block.jsx +1 -1
- package/src/components/render-blocks.jsx +32 -33
- package/src/components/render-content/components/render-styles.jsx +38 -41
- package/src/components/render-content/render-content.jsx +167 -164
- package/src/components/render-inlined-styles.jsx +10 -13
- package/src/constants/builder-registered-components.js +3 -0
- package/src/functions/get-fetch.js +2 -2
- package/src/functions/get-processed-block.js +10 -6
- package/src/functions/get-processed-block.test.js +1 -1
- package/src/scripts/init-editing.js +4 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Show, onMount, on, createEffect } from "solid-js";
|
|
1
|
+
import { Show, onMount, on, createEffect, createSignal } from "solid-js";
|
|
2
2
|
import { Dynamic } from "solid-js/web";
|
|
3
|
-
import { createMutable } from "solid-js/store";
|
|
4
3
|
import { getDefaultRegisteredComponents } from "../../constants/builder-registered-components.js";
|
|
5
4
|
import { TARGET } from "../../constants/target.js";
|
|
6
5
|
import BuilderContext from "../../context/builder.context";
|
|
@@ -14,182 +13,186 @@ import { components, createRegisterComponentMessage } from "../../functions/regi
|
|
|
14
13
|
import { track } from "../../functions/track.js";
|
|
15
14
|
import RenderBlocks from "../render-blocks.jsx";
|
|
16
15
|
import RenderContentStyles from "./components/render-styles.jsx";
|
|
16
|
+
import { registerInsertMenu, setupBrowserForEditing } from "../../scripts/init-editing.js";
|
|
17
17
|
|
|
18
18
|
function RenderContent(props) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return mergedContent;
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
overrideContent: null,
|
|
32
|
-
update: 0,
|
|
33
|
-
|
|
34
|
-
get canTrackToUse() {
|
|
35
|
-
return props.canTrack || true;
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
overrideState: {},
|
|
39
|
-
|
|
40
|
-
get contentState() {
|
|
41
|
-
return { ...props.content?.data?.state,
|
|
19
|
+
const [forceReRenderCount, setForceReRenderCount] = createSignal(0);
|
|
20
|
+
const [overrideContent, setOverrideContent] = createSignal(null);
|
|
21
|
+
const [update, setUpdate] = createSignal(0);
|
|
22
|
+
const [overrideState, setOverrideState] = createSignal({});
|
|
23
|
+
|
|
24
|
+
function useContent() {
|
|
25
|
+
const mergedContent = { ...props.content,
|
|
26
|
+
...overrideContent(),
|
|
27
|
+
data: { ...props.content?.data,
|
|
42
28
|
...props.data,
|
|
43
|
-
...
|
|
44
|
-
}
|
|
45
|
-
}
|
|
29
|
+
...overrideContent()?.data
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return mergedContent;
|
|
33
|
+
}
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
35
|
+
function canTrackToUse() {
|
|
36
|
+
return props.canTrack || true;
|
|
37
|
+
}
|
|
50
38
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...components, ...(props.customComponents || [])];
|
|
58
|
-
const allComponents = allComponentsArray.reduce((acc, curr) => ({ ...acc,
|
|
59
|
-
[curr.name]: curr
|
|
60
|
-
}), {});
|
|
61
|
-
return allComponents;
|
|
62
|
-
},
|
|
39
|
+
function contentState() {
|
|
40
|
+
return { ...props.content?.data?.state,
|
|
41
|
+
...props.data,
|
|
42
|
+
...overrideState()
|
|
43
|
+
};
|
|
44
|
+
}
|
|
63
45
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} = event;
|
|
68
|
-
|
|
69
|
-
if (data) {
|
|
70
|
-
switch (data.type) {
|
|
71
|
-
case "builder.contentUpdate":
|
|
72
|
-
{
|
|
73
|
-
const messageContent = data.data;
|
|
74
|
-
const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
|
|
75
|
-
const contentData = messageContent.data;
|
|
76
|
-
|
|
77
|
-
if (key === props.model) {
|
|
78
|
-
state.overrideContent = contentData;
|
|
79
|
-
}
|
|
46
|
+
function contextContext() {
|
|
47
|
+
return props.context || {};
|
|
48
|
+
}
|
|
80
49
|
|
|
81
|
-
|
|
82
|
-
|
|
50
|
+
function allRegisteredComponents() {
|
|
51
|
+
const allComponentsArray = [...getDefaultRegisteredComponents(), // While this `components` object is deprecated, we must maintain support for it.
|
|
52
|
+
// Since users are able to override our default components, we need to make sure that we do not break such
|
|
53
|
+
// existing usage.
|
|
54
|
+
// This is why we spread `components` after the default Builder.io components, but before the `props.customComponents`,
|
|
55
|
+
// which is the new standard way of providing custom components, and must therefore take precedence.
|
|
56
|
+
...components, ...(props.customComponents || [])];
|
|
57
|
+
const allComponents = allComponentsArray.reduce((acc, curr) => ({ ...acc,
|
|
58
|
+
[curr.name]: curr
|
|
59
|
+
}), {});
|
|
60
|
+
return allComponents;
|
|
61
|
+
}
|
|
83
62
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
function processMessage(event) {
|
|
64
|
+
const {
|
|
65
|
+
data
|
|
66
|
+
} = event;
|
|
67
|
+
|
|
68
|
+
if (data) {
|
|
69
|
+
switch (data.type) {
|
|
70
|
+
case "builder.contentUpdate":
|
|
71
|
+
{
|
|
72
|
+
const messageContent = data.data;
|
|
73
|
+
const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
|
|
74
|
+
const contentData = messageContent.data;
|
|
75
|
+
|
|
76
|
+
if (key === props.model) {
|
|
77
|
+
setOverrideContent(contentData);
|
|
88
78
|
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
79
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const jsCode = state.useContent?.data?.jsCode;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
96
82
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
});
|
|
83
|
+
case "builder.patchUpdates":
|
|
84
|
+
{
|
|
85
|
+
// TODO
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
103
88
|
}
|
|
104
|
-
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
105
91
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
92
|
+
function evaluateJsCode() {
|
|
93
|
+
// run any dynamic JS code attached to content
|
|
94
|
+
const jsCode = useContent()?.data?.jsCode;
|
|
109
95
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
},
|
|
96
|
+
if (jsCode) {
|
|
97
|
+
evaluate({
|
|
98
|
+
code: jsCode,
|
|
99
|
+
context: contextContext(),
|
|
100
|
+
state: contentState()
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
120
104
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
context: state.contextContext,
|
|
125
|
-
state: state.contentState
|
|
126
|
-
}));
|
|
127
|
-
},
|
|
105
|
+
function httpReqsData() {
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
128
108
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
};
|
|
140
|
-
state.overrideState = newOverrideState;
|
|
141
|
-
};
|
|
109
|
+
function onClick(_event) {
|
|
110
|
+
if (useContent()) {
|
|
111
|
+
track({
|
|
112
|
+
type: "click",
|
|
113
|
+
canTrack: canTrackToUse(),
|
|
114
|
+
contentId: useContent().id,
|
|
115
|
+
orgId: props.apiKey
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
142
119
|
|
|
143
|
-
|
|
144
|
-
},
|
|
120
|
+
function evalExpression(expression) {
|
|
121
|
+
return expression.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
|
|
122
|
+
code: group,
|
|
123
|
+
context: contextContext(),
|
|
124
|
+
state: contentState()
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
145
127
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
128
|
+
function handleRequest({
|
|
129
|
+
url,
|
|
130
|
+
key
|
|
131
|
+
}) {
|
|
132
|
+
const fetchAndSetState = async () => {
|
|
133
|
+
const fetch = await getFetch();
|
|
134
|
+
const response = await fetch(url);
|
|
135
|
+
const json = await response.json();
|
|
136
|
+
const newOverrideState = { ...overrideState(),
|
|
137
|
+
[key]: json
|
|
138
|
+
};
|
|
139
|
+
setOverrideState(newOverrideState);
|
|
140
|
+
};
|
|
158
141
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
142
|
+
fetchAndSetState();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function runHttpRequests() {
|
|
146
|
+
const requests = useContent()?.data?.httpRequests ?? {};
|
|
147
|
+
Object.entries(requests).forEach(([key, url]) => {
|
|
148
|
+
if (url && (!httpReqsData()[key] || isEditing())) {
|
|
149
|
+
const evaluatedUrl = evalExpression(url);
|
|
150
|
+
handleRequest({
|
|
151
|
+
url: evaluatedUrl,
|
|
152
|
+
key
|
|
153
|
+
});
|
|
169
154
|
}
|
|
170
|
-
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
171
157
|
|
|
172
|
-
|
|
173
|
-
|
|
158
|
+
function emitStateUpdate() {
|
|
159
|
+
if (isEditing()) {
|
|
160
|
+
window.dispatchEvent(new CustomEvent("builder:component:stateChange", {
|
|
161
|
+
detail: {
|
|
162
|
+
state: contentState(),
|
|
163
|
+
ref: {
|
|
164
|
+
name: props.model
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}));
|
|
174
168
|
}
|
|
169
|
+
}
|
|
175
170
|
|
|
176
|
-
|
|
171
|
+
function shouldRenderContentStyles() {
|
|
172
|
+
return Boolean((useContent()?.data?.cssCode || useContent()?.data?.customFonts?.length) && TARGET !== "reactNative");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let elementRef;
|
|
177
176
|
onMount(() => {
|
|
178
177
|
if (isBrowser()) {
|
|
179
178
|
if (isEditing()) {
|
|
180
|
-
|
|
179
|
+
setForceReRenderCount(forceReRenderCount() + 1); // QWIK-REPLACE: _useMutableProps
|
|
180
|
+
|
|
181
|
+
registerInsertMenu();
|
|
182
|
+
setupBrowserForEditing();
|
|
183
|
+
Object.values(allRegisteredComponents()).forEach(registeredComponent => {
|
|
181
184
|
const message = createRegisterComponentMessage(registeredComponent);
|
|
182
185
|
window.parent?.postMessage(message, "*");
|
|
183
186
|
});
|
|
184
|
-
window.addEventListener("message",
|
|
185
|
-
window.addEventListener("builder:component:stateChangeListenerActivated",
|
|
187
|
+
window.addEventListener("message", processMessage);
|
|
188
|
+
window.addEventListener("builder:component:stateChangeListenerActivated", emitStateUpdate);
|
|
186
189
|
}
|
|
187
190
|
|
|
188
|
-
if (
|
|
191
|
+
if (useContent()) {
|
|
189
192
|
track({
|
|
190
193
|
type: "impression",
|
|
191
|
-
canTrack:
|
|
192
|
-
contentId:
|
|
194
|
+
canTrack: canTrackToUse(),
|
|
195
|
+
contentId: useContent().id,
|
|
193
196
|
orgId: props.apiKey
|
|
194
197
|
});
|
|
195
198
|
} // override normal content in preview mode
|
|
@@ -207,47 +210,47 @@ function RenderContent(props) {
|
|
|
207
210
|
apiKey: previewApiKey
|
|
208
211
|
}).then(content => {
|
|
209
212
|
if (content) {
|
|
210
|
-
|
|
213
|
+
setOverrideContent(content);
|
|
211
214
|
}
|
|
212
215
|
});
|
|
213
216
|
}
|
|
214
217
|
}
|
|
215
218
|
}
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
evaluateJsCode();
|
|
221
|
+
runHttpRequests();
|
|
222
|
+
emitStateUpdate();
|
|
220
223
|
}
|
|
221
224
|
});
|
|
222
225
|
|
|
223
226
|
function onUpdateFn_0() {
|
|
224
|
-
|
|
227
|
+
evaluateJsCode();
|
|
225
228
|
}
|
|
226
229
|
|
|
227
|
-
createEffect(on(() => [
|
|
230
|
+
createEffect(on(() => [useContent()?.data?.jsCode], onUpdateFn_0));
|
|
228
231
|
|
|
229
232
|
function onUpdateFn_1() {
|
|
230
|
-
|
|
233
|
+
runHttpRequests();
|
|
231
234
|
}
|
|
232
235
|
|
|
233
|
-
createEffect(on(() => [
|
|
236
|
+
createEffect(on(() => [useContent()?.data?.httpRequests], onUpdateFn_1));
|
|
234
237
|
|
|
235
238
|
function onUpdateFn_2() {
|
|
236
|
-
|
|
239
|
+
emitStateUpdate();
|
|
237
240
|
}
|
|
238
241
|
|
|
239
|
-
createEffect(on(() => [
|
|
242
|
+
createEffect(on(() => [contentState()], onUpdateFn_2));
|
|
240
243
|
return <Dynamic value={{
|
|
241
244
|
get content() {
|
|
242
|
-
return
|
|
245
|
+
return useContent();
|
|
243
246
|
},
|
|
244
247
|
|
|
245
248
|
get state() {
|
|
246
|
-
return
|
|
249
|
+
return contentState();
|
|
247
250
|
},
|
|
248
251
|
|
|
249
252
|
get context() {
|
|
250
|
-
return
|
|
253
|
+
return contextContext();
|
|
251
254
|
},
|
|
252
255
|
|
|
253
256
|
get apiKey() {
|
|
@@ -255,16 +258,16 @@ function RenderContent(props) {
|
|
|
255
258
|
},
|
|
256
259
|
|
|
257
260
|
get registeredComponents() {
|
|
258
|
-
return
|
|
261
|
+
return allRegisteredComponents();
|
|
259
262
|
}
|
|
260
263
|
|
|
261
264
|
}} component={BuilderContext.Provider}>
|
|
262
|
-
<Show when={
|
|
263
|
-
<div onClick={event =>
|
|
264
|
-
<Show when={
|
|
265
|
-
<RenderContentStyles cssCode={
|
|
265
|
+
<Show when={useContent()}>
|
|
266
|
+
<div ref={elementRef} onClick={event => onClick(event)} builder-content-id={useContent()?.id}>
|
|
267
|
+
<Show when={shouldRenderContentStyles()}>
|
|
268
|
+
<RenderContentStyles cssCode={useContent()?.data?.cssCode} customFonts={useContent()?.data?.customFonts}></RenderContentStyles>
|
|
266
269
|
</Show>
|
|
267
|
-
<RenderBlocks blocks={
|
|
270
|
+
<RenderBlocks blocks={useContent()?.data?.blocks} key={forceReRenderCount()}></RenderBlocks>
|
|
268
271
|
</div>
|
|
269
272
|
</Show>
|
|
270
273
|
</Dynamic>;
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { Show } from "solid-js";
|
|
2
2
|
import { Dynamic } from "solid-js/web";
|
|
3
|
-
import { createMutable } from "solid-js/store";
|
|
4
3
|
import { TARGET } from "../constants/target.js";
|
|
5
4
|
|
|
6
5
|
function RenderInlinedStyles(props) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
6
|
+
function injectedStyleScript() {
|
|
7
|
+
return `<${tagName()}>${props.styles}</${tagName()}>`;
|
|
8
|
+
}
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
function tagName() {
|
|
11
|
+
// NOTE: we have to obfusctate the name of the tag due to a limitation in the svelte-preprocessor plugin.
|
|
12
|
+
// https://github.com/sveltejs/vite-plugin-svelte/issues/315#issuecomment-1109000027
|
|
13
|
+
return "sty" + "le";
|
|
14
|
+
}
|
|
17
15
|
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
<div innerHTML={state.injectedStyleScript}></div>
|
|
16
|
+
return <Show fallback={<Dynamic component={tagName()}>{props.styles}</Dynamic>} when={TARGET === "svelte"}>
|
|
17
|
+
<div innerHTML={injectedStyleScript()}></div>
|
|
21
18
|
</Show>;
|
|
22
19
|
}
|
|
23
20
|
|
|
@@ -32,9 +32,12 @@ import { componentInfo as videoComponentInfo } from "../blocks/video/component-i
|
|
|
32
32
|
import { default as Video } from "../blocks/video/video.jsx";
|
|
33
33
|
import { componentInfo as embedComponentInfo } from "../blocks/embed/component-info";
|
|
34
34
|
import { default as embed } from "../blocks/embed/embed.jsx";
|
|
35
|
+
import { default as Img } from "../blocks/img/img.jsx";
|
|
36
|
+
import { componentInfo as imgComponentInfo } from "../blocks/img/component-info";
|
|
35
37
|
const getDefaultRegisteredComponents = () => [
|
|
36
38
|
__spreadValues({ component: Columns }, columnsComponentInfo),
|
|
37
39
|
__spreadValues({ component: Image }, imageComponentInfo),
|
|
40
|
+
__spreadValues({ component: Img }, imgComponentInfo),
|
|
38
41
|
__spreadValues({ component: Text }, textComponentInfo),
|
|
39
42
|
__spreadValues({ component: Video }, videoComponentInfo),
|
|
40
43
|
__spreadValues({ component: Symbol }, symbolComponentInfo),
|
|
@@ -24,9 +24,9 @@ function getFetch() {
|
|
|
24
24
|
const globalFetch = getGlobalThis().fetch;
|
|
25
25
|
if (typeof globalFetch === "undefined" && typeof global !== "undefined") {
|
|
26
26
|
const nodeFetch = import("node-fetch").then((d) => d.default);
|
|
27
|
-
return nodeFetch;
|
|
27
|
+
return nodeFetch.default || nodeFetch;
|
|
28
28
|
}
|
|
29
|
-
return globalFetch;
|
|
29
|
+
return globalFetch.default || globalFetch;
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
export {
|
|
@@ -39,13 +39,17 @@ const evaluateBindings = ({
|
|
|
39
39
|
}
|
|
40
40
|
return copied;
|
|
41
41
|
};
|
|
42
|
-
function getProcessedBlock(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
function getProcessedBlock({
|
|
43
|
+
block,
|
|
44
|
+
context,
|
|
45
|
+
shouldEvaluateBindings,
|
|
46
|
+
state
|
|
47
|
+
}) {
|
|
48
|
+
const transformedBlock = transformBlock(block);
|
|
49
|
+
if (shouldEvaluateBindings) {
|
|
50
|
+
return evaluateBindings({ block: transformedBlock, state, context });
|
|
47
51
|
} else {
|
|
48
|
-
return
|
|
52
|
+
return transformedBlock;
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
export {
|
|
@@ -21,7 +21,7 @@ test("Can process bindings", () => {
|
|
|
21
21
|
block,
|
|
22
22
|
context: {},
|
|
23
23
|
state: { test: "hello" },
|
|
24
|
-
|
|
24
|
+
shouldEvaluateBindings: true
|
|
25
25
|
});
|
|
26
26
|
expect(processed).not.toEqual(block);
|
|
27
27
|
expect((_a = processed.properties) == null ? void 0 : _a.foo).toEqual("baz");
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TARGET } from "../constants/target.js";
|
|
2
2
|
import { isBrowser } from "../functions/is-browser.js";
|
|
3
|
-
import { isEditing } from "../functions/is-editing.js";
|
|
4
3
|
import { register } from "../functions/register.js";
|
|
5
4
|
const registerInsertMenu = () => {
|
|
6
5
|
register("insertMenu", {
|
|
@@ -74,7 +73,7 @@ const setupBrowserForEditing = () => {
|
|
|
74
73
|
});
|
|
75
74
|
}
|
|
76
75
|
};
|
|
77
|
-
|
|
78
|
-
registerInsertMenu
|
|
79
|
-
setupBrowserForEditing
|
|
80
|
-
}
|
|
76
|
+
export {
|
|
77
|
+
registerInsertMenu,
|
|
78
|
+
setupBrowserForEditing
|
|
79
|
+
};
|