@@ -2181,7 +2194,6 @@ exports[`Alpine.js > jsx > Javascript Test > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -2240,11 +2252,6 @@ exports[`Alpine.js > jsx > Javascript Test > renderBlock 1`] = `
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -2257,30 +2264,16 @@ exports[`Alpine.js > jsx > Javascript Test > renderBlock 1`] = `
},
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return this.componentInfo?.canHaveChildren ? this.useBlock.children : [];
return this.useBlock.children ?? [];
},
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
},
get repeatItemData() {
- /**
- * we don't use \`this.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -2345,7 +2338,6 @@ exports[`Alpine.js > jsx > Javascript Test > renderBlock 1`] = `
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -3232,9 +3224,7 @@ exports[`Alpine.js > jsx > Typescript Test > CustomCode 1`] = `
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3296,9 +3286,7 @@ exports[`Alpine.js > jsx > Typescript Test > Embed 1`] = `
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3431,8 +3419,7 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -3458,7 +3445,6 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
value = num;
}
} else if (el.type === 'file') {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3484,14 +3470,11 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
if (value instanceof File || Array.isArray(value) && value[0] instanceof File || value instanceof FileList) {
contentType = 'multipart/form-data';
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== 'application/json') {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({
value,
@@ -3503,9 +3486,7 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
}
if (contentType && contentType !== 'multipart/form-data') {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes('zapier.com'))) {
+ if (!(sendWithJs && props.action?.includes('zapier.com'))) {
headers['content-type'] = contentType;
}
}
@@ -3526,9 +3507,7 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
this.formState = 'sending';
const formUrl = \`\${builder.env === 'dev' ? 'http://localhost:5000' : 'https://builder.io'}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(props.sendSubmissionsToEmail || '')}&name=\${encodeURIComponent(props.name || '')}\`;
- fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action!
- /* TODO: throw error if no action URL */
- , {
+ fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action!, {
body,
headers,
method: props.method || 'post'
@@ -3543,13 +3522,10 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== 'string') {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -3574,15 +3550,11 @@ exports[`Alpine.js > jsx > Typescript Test > Form 1`] = `
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
-
if (props.resetFormOnSubmit !== false) {
this.$refs.formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
-
if (props.successUrl) {
if (this.$refs.formRef) {
@@ -3667,7 +3639,6 @@ exports[`Alpine.js > jsx > Typescript Test > Image 1`] = `
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && this.isBrowser();
},
@@ -4318,6 +4289,41 @@ exports[`Alpine.js > jsx > Typescript Test > classState 1`] = `
"
`;
+exports[`Alpine.js > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"
+
+
+
+ Hello
+
+
+ ! I can run in React, Vue, Solid, or Liquid!
+
@@ -4867,7 +4873,6 @@ exports[`Alpine.js > jsx > Typescript Test > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -4926,11 +4931,6 @@ exports[`Alpine.js > jsx > Typescript Test > renderBlock 1`] = `
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -4943,30 +4943,16 @@ exports[`Alpine.js > jsx > Typescript Test > renderBlock 1`] = `
},
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return this.componentInfo?.canHaveChildren ? this.useBlock.children : [];
return this.useBlock.children ?? [];
},
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
},
get repeatItemData() {
- /**
- * we don't use \`this.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -5034,7 +5020,6 @@ exports[`Alpine.js > jsx > Typescript Test > renderBlock 1`] = `
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
index e0a9d3bb58..051936e84a 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
@@ -843,9 +843,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -923,9 +921,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1101,8 +1097,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1129,7 +1124,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1157,14 +1151,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1173,10 +1164,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -1201,15 +1189,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -1221,13 +1205,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -1252,13 +1233,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -1366,7 +1345,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -2433,6 +2411,8 @@ export class MyBasicComponentModule {}
"
`;
+exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -3453,7 +3433,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -3506,11 +3485,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -3522,28 +3496,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -3604,7 +3564,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -5177,9 +5136,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5262,9 +5219,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5468,8 +5423,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -5499,7 +5453,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -5527,14 +5480,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -5543,10 +5493,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -5571,15 +5518,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -5591,13 +5534,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -5622,13 +5562,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -5755,7 +5693,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -6963,6 +6900,8 @@ export class MyBasicComponentModule {}
"
`;
+exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -8084,7 +8023,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -8137,11 +8075,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -8153,28 +8086,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -8235,7 +8154,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
index 9b45fd388a..ab6b7f976d 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap
@@ -861,9 +861,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -942,9 +940,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1121,8 +1117,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1149,7 +1144,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1177,14 +1171,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1193,10 +1184,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -1221,15 +1209,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -1241,13 +1225,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -1272,13 +1253,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -1387,7 +1366,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -2482,6 +2460,8 @@ export class MyBasicComponentModule {}
"
`;
+exports[`Angular with Import Mapper Tests > jsx > Javascript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular with Import Mapper Tests > jsx > Javascript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -3530,7 +3510,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -3583,11 +3562,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -3599,28 +3573,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -3681,7 +3641,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -5293,9 +5252,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5379,9 +5336,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5586,8 +5541,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -5617,7 +5571,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -5645,14 +5598,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -5661,10 +5611,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -5689,15 +5636,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -5709,13 +5652,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -5740,13 +5680,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -5874,7 +5812,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -7110,6 +7047,8 @@ export class MyBasicComponentModule {}
"
`;
+exports[`Angular with Import Mapper Tests > jsx > Typescript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular with Import Mapper Tests > jsx > Typescript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -8261,7 +8200,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -8314,11 +8252,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -8330,28 +8263,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -8412,7 +8331,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
index 94d0878829..05b5788c6d 100644
--- a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap
@@ -1531,9 +1531,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1611,9 +1609,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1684,9 +1680,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1764,9 +1758,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1935,8 +1927,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1963,7 +1954,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1991,14 +1981,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -2007,10 +1994,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -2035,15 +2019,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -2055,13 +2035,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -2086,13 +2063,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -2267,8 +2242,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -2295,7 +2269,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -2323,14 +2296,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -2339,10 +2309,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -2367,15 +2334,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -2387,13 +2350,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -2418,13 +2378,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -2525,7 +2483,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -2632,7 +2589,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -4519,6 +4475,10 @@ export class MyBasicComponent {
"
`;
+exports[`Angular > jsx > Javascript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
+exports[`Angular > jsx > Javascript Test > commentsWithQuotes 2`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular > jsx > Javascript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -6273,7 +6233,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -6326,11 +6285,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -6342,28 +6296,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -6424,7 +6364,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -6530,7 +6469,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -6583,11 +6521,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -6599,28 +6532,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -6681,7 +6600,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -9489,9 +9407,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -9574,9 +9490,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -9652,9 +9566,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -9737,9 +9649,7 @@ export class CustomCode {
scriptsInserted = [];
scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem.nativeElement && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.nativeElement.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -9936,8 +9846,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -9967,7 +9876,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -9995,14 +9903,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -10011,10 +9916,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -10039,15 +9941,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -10059,13 +9957,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -10090,13 +9985,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -10299,8 +10192,7 @@ export class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -10330,7 +10222,6 @@ export class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -10358,14 +10249,11 @@ export class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -10374,10 +10262,7 @@ export class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -10402,15 +10287,11 @@ export class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -10422,13 +10303,10 @@ export class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -10453,13 +10331,11 @@ export class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.formRef.nativeElement.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.formRef.nativeElement) {
@@ -10579,7 +10455,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -10705,7 +10580,6 @@ export class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -12874,6 +12748,10 @@ export class MyBasicComponent {
"
`;
+exports[`Angular > jsx > Typescript Test > commentsWithQuotes 1`] = `"JSON5: invalid character '&' at 2:10"`;
+
+exports[`Angular > jsx > Typescript Test > commentsWithQuotes 2`] = `"JSON5: invalid character '&' at 2:10"`;
+
exports[`Angular > jsx > Typescript Test > componentWithContext 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
@@ -14816,7 +14694,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -14869,11 +14746,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -14885,28 +14757,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -14967,7 +14825,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -15086,7 +14943,6 @@ export class RenderBlock {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -15139,11 +14995,6 @@ export class RenderBlock {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the this.component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -15155,28 +15006,14 @@ export class RenderBlock {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -15237,7 +15074,6 @@ export class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the this.component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/builder.test.ts.snap b/packages/core/src/__tests__/__snapshots__/builder.test.ts.snap
index ad7bb52abe..2cb7b4c41a 100644
--- a/packages/core/src/__tests__/__snapshots__/builder.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/builder.test.ts.snap
@@ -218,9 +218,7 @@ Object.assign(state, {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -268,9 +266,7 @@ useState({
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -326,9 +322,7 @@ export default function MyComponent(props) {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -415,9 +409,7 @@ Object.assign(state, {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -465,9 +457,7 @@ useState({
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -523,9 +513,7 @@ export default function MyComponent(props) {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -685,7 +673,6 @@ Object.assign(state, {
state.imageLoaded = true;
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
},
isBrowser: function isBrowser() {
@@ -728,7 +715,6 @@ useState({
state.imageLoaded = true;
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
},
isBrowser: function isBrowser() {
@@ -779,7 +765,6 @@ export default function MyComponent(props) {
state.imageLoaded = true;
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
},
isBrowser: function isBrowser() {
diff --git a/packages/core/src/__tests__/__snapshots__/context.test.ts.snap b/packages/core/src/__tests__/__snapshots__/context.test.ts.snap
index 4172498f5d..0c833a991e 100644
--- a/packages/core/src/__tests__/__snapshots__/context.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/context.test.ts.snap
@@ -430,7 +430,6 @@ exports[`Context > Use and set context in complex components 1`] = `
const ref = components[state.useBlock.component?.name];
if (componentName && !ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -516,7 +515,6 @@ function RenderBlock(props) {
const ref = components[useBlock().component?.name];
if (componentName && !ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
diff --git a/packages/core/src/__tests__/__snapshots__/html.test.ts.snap b/packages/core/src/__tests__/__snapshots__/html.test.ts.snap
index e9fbbe13bf..80c79eec09 100644
--- a/packages/core/src/__tests__/__snapshots__/html.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/html.test.ts.snap
@@ -1678,9 +1678,7 @@ exports[`Html > jsx > Javascript Test > CustomCode 1`] = `
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1769,9 +1767,7 @@ exports[`Html > jsx > Javascript Test > Embed 1`] = `
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1882,7 +1878,6 @@ exports[`Html > jsx > Javascript Test > Image 1`] = `
update();
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
},
isBrowser: function isBrowser() {
@@ -3788,6 +3783,99 @@ exports[`Html > jsx > Javascript Test > classState 1`] = `
"
`;
+exports[`Html > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello
+
+
+ ! I can run in React, Vue, Solid, or Liquid!
+
+
+
+"
+`;
+
exports[`Html > jsx > Javascript Test > componentWithContext 1`] = `
"
@@ -4881,7 +4969,6 @@ exports[`Html > jsx > Javascript Test > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -4934,11 +5021,6 @@ exports[`Html > jsx > Javascript Test > renderBlock 1`] = `
componentRef: state.component?.component,
componentOptions: {
...getBlockComponentOptions(state.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(state.shouldWrap
? {}
: {
@@ -4951,28 +5033,14 @@ exports[`Html > jsx > Javascript Test > renderBlock 1`] = `
};
},
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return state.useBlock.children ?? [];
},
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!state.component?.component && !state.repeatItemData;
return shouldRenderChildrenOutsideRef ? state.useChildren : [];
},
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -5034,7 +5102,6 @@ exports[`Html > jsx > Javascript Test > renderBlock 1`] = `
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -7944,9 +8011,7 @@ exports[`Html > jsx > Typescript Test > CustomCode 1`] = `
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -8035,9 +8100,7 @@ exports[`Html > jsx > Typescript Test > Embed 1`] = `
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -8148,7 +8211,6 @@ exports[`Html > jsx > Typescript Test > Image 1`] = `
update();
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
},
isBrowser: function isBrowser() {
@@ -10054,6 +10116,99 @@ exports[`Html > jsx > Typescript Test > classState 1`] = `
"
`;
+exports[`Html > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello
+
+
+ ! I can run in React, Vue, Solid, or Liquid!
+
+
+
+"
+`;
+
exports[`Html > jsx > Typescript Test > componentWithContext 1`] = `
"
@@ -11147,7 +11302,6 @@ exports[`Html > jsx > Typescript Test > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -11200,11 +11354,6 @@ exports[`Html > jsx > Typescript Test > renderBlock 1`] = `
componentRef: state.component?.component,
componentOptions: {
...getBlockComponentOptions(state.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(state.shouldWrap
? {}
: {
@@ -11217,28 +11366,14 @@ exports[`Html > jsx > Typescript Test > renderBlock 1`] = `
};
},
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return state.useBlock.children ?? [];
},
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!state.component?.component && !state.repeatItemData;
return shouldRenderChildrenOutsideRef ? state.useChildren : [];
},
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -11303,7 +11438,6 @@ exports[`Html > jsx > Typescript Test > renderBlock 1`] = `
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap b/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap
index a3abd00cb4..9e219485c8 100644
--- a/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap
@@ -542,6 +542,20 @@ exports[`Liquid > jsx > Javascript Test > classState 1`] = `
"
`;
+exports[`Liquid > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello {{name}} ! I can run in React, Vue, Solid, or Liquid!
+
diff --git a/packages/core/src/__tests__/__snapshots__/lit.test.ts.snap b/packages/core/src/__tests__/__snapshots__/lit.test.ts.snap
index 3140f0226a..3a6e0b528f 100644
--- a/packages/core/src/__tests__/__snapshots__/lit.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/lit.test.ts.snap
@@ -803,9 +803,7 @@ export default class CustomCode extends LitElement {
@state() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -878,9 +876,7 @@ export default class CustomCode extends LitElement {
@state() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1003,8 +999,7 @@ export default class FormComponent extends LitElement {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1031,7 +1026,6 @@ export default class FormComponent extends LitElement {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1059,14 +1053,11 @@ export default class FormComponent extends LitElement {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1075,10 +1066,7 @@ export default class FormComponent extends LitElement {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -1103,15 +1091,11 @@ export default class FormComponent extends LitElement {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -1123,13 +1107,10 @@ export default class FormComponent extends LitElement {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -1154,13 +1135,11 @@ export default class FormComponent extends LitElement {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (formRef) {
@@ -1292,7 +1271,6 @@ export default class Image extends LitElement {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -2370,6 +2348,44 @@ export default class MyBasicComponent extends LitElement {
"
`;
+exports[`Lit > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"import { LitElement, html, css } from \\"lit\\";
+import { customElement, property, state, query } from \\"lit/decorators.js\\";
+
+@customElement(\\"my-component\\")
+export default class MyComponent extends LitElement {
+ createRenderRoot() {
+ return this;
+ }
+
+ @state() name = \\"Steve\\";
+
+ handleFn() {}
+ doSomething = function doSomething() {
+ console.log(\\"This is a aa\\");
+ };
+
+ render() {
+ return html\`
+
+
+ {
+ this.name = event.target.value;
+ }} @click=\${(event) => this.doSomething()} /> Hello \${
+ this.name
+ } ! I can run in
+ React, Vue, Solid, or Liquid!
+
+
+ \`;
+ }
+}
+"
+`;
+
exports[`Lit > jsx > Javascript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -3282,7 +3298,6 @@ export default class RenderBlock extends LitElement {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -3335,11 +3350,6 @@ export default class RenderBlock extends LitElement {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -3351,28 +3361,14 @@ export default class RenderBlock extends LitElement {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -3433,7 +3429,6 @@ export default class RenderBlock extends LitElement {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -5009,9 +5004,7 @@ export default class CustomCode extends LitElement {
@state() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5089,9 +5082,7 @@ export default class CustomCode extends LitElement {
@state() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5242,8 +5233,7 @@ export default class FormComponent extends LitElement {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -5273,7 +5263,6 @@ export default class FormComponent extends LitElement {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -5301,14 +5290,11 @@ export default class FormComponent extends LitElement {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -5317,10 +5303,7 @@ export default class FormComponent extends LitElement {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -5345,15 +5328,11 @@ export default class FormComponent extends LitElement {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -5365,13 +5344,10 @@ export default class FormComponent extends LitElement {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -5396,13 +5372,11 @@ export default class FormComponent extends LitElement {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (formRef) {
@@ -5556,7 +5530,6 @@ export default class Image extends LitElement {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -6775,6 +6748,44 @@ export default class MyBasicComponent extends LitElement {
"
`;
+exports[`Lit > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"import { LitElement, html, css } from \\"lit\\";
+import { customElement, property, state, query } from \\"lit/decorators.js\\";
+
+@customElement(\\"my-component\\")
+export default class MyComponent extends LitElement {
+ createRenderRoot() {
+ return this;
+ }
+
+ @state() name = \\"Steve\\";
+
+ handleFn() {}
+ doSomething = function doSomething() {
+ console.log(\\"This is a aa\\");
+ };
+
+ render() {
+ return html\`
+
+
+ {
+ this.name = event.target.value;
+ }} @click=\${(event) => this.doSomething()} /> Hello \${
+ this.name
+ } ! I can run in
+ React, Vue, Solid, or Liquid!
+
+
+ \`;
+ }
+}
+"
+`;
+
exports[`Lit > jsx > Typescript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -7788,7 +7799,6 @@ export default class RenderBlock extends LitElement {
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -7841,11 +7851,6 @@ export default class RenderBlock extends LitElement {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -7857,28 +7862,14 @@ export default class RenderBlock extends LitElement {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -7939,7 +7930,6 @@ export default class RenderBlock extends LitElement {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/marko.test.ts.snap b/packages/core/src/__tests__/__snapshots__/marko.test.ts.snap
index bdf74033d7..90818fade1 100644
--- a/packages/core/src/__tests__/__snapshots__/marko.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/marko.test.ts.snap
@@ -523,9 +523,7 @@ exports[`Marko > jsx > Javascript Test > ContentSlotJSX 1`] = `
exports[`Marko > jsx > Javascript Test > CustomCode 1`] = `
"class {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -588,9 +586,7 @@ exports[`Marko > jsx > Javascript Test > CustomCode 1`] = `
exports[`Marko > jsx > Javascript Test > Embed 1`] = `
"class {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -681,8 +677,7 @@ class {
const el = event.currentTarget;
const headers = this.input.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -709,7 +704,6 @@ class {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -737,14 +731,11 @@ class {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -753,10 +744,7 @@ class {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.input.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.input.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -783,7 +771,6 @@ class {
)}&name=\${encodeURIComponent(this.input.name || \\"\\")}\`;
fetch(
this.input.sendSubmissionsTo === \\"email\\" ? formUrl : this.input.action,
- /* TODO: throw error if no action URL */
{
body,
headers,
@@ -801,13 +788,10 @@ class {
}
if (!res.ok && this.input.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.input.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -832,13 +816,11 @@ class {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.input.resetFormOnSubmit !== false) {
this.formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.input.successUrl) {
if (this.formRef) {
@@ -894,7 +876,7 @@ class {
}
style {
- .pre-82880ee4 {
+ .pre-fdd5ed4a {
padding: 10px;
color: red;
text-align: center;
@@ -929,7 +911,7 @@ style {
>
-
+ {
+ state.name = event.target.value;
+})
+ on-click(event => component.doSomething())
+ />
+
+ Hello \${state.name} ! I can run in React, Vue, Solid, or Liquid!
+
"
+`;
+
exports[`Marko > jsx > Javascript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -1962,7 +1974,6 @@ class {
const ref = this.input.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -2015,11 +2026,6 @@ class {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -2031,28 +2037,14 @@ class {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.input.block;
if (!repeat?.collection) {
@@ -2113,7 +2105,6 @@ class {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -2895,9 +2886,7 @@ class {
exports[`Marko > jsx > Typescript Test > CustomCode 1`] = `
"class {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -2960,9 +2949,7 @@ exports[`Marko > jsx > Typescript Test > CustomCode 1`] = `
exports[`Marko > jsx > Typescript Test > Embed 1`] = `
"class {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3057,8 +3044,7 @@ class {
const el = event.currentTarget;
const headers = this.input.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -3088,7 +3074,6 @@ class {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3116,14 +3101,11 @@ class {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -3132,10 +3114,7 @@ class {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.input.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.input.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -3162,7 +3141,6 @@ class {
)}&name=\${encodeURIComponent(this.input.name || \\"\\")}\`;
fetch(
this.input.sendSubmissionsTo === \\"email\\" ? formUrl : this.input.action!,
- /* TODO: throw error if no action URL */
{
body,
headers,
@@ -3180,13 +3158,10 @@ class {
}
if (!res.ok && this.input.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.input.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -3211,13 +3186,11 @@ class {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.input.resetFormOnSubmit !== false) {
this.formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.input.successUrl) {
if (this.formRef) {
@@ -3273,7 +3246,7 @@ class {
}
style {
- .pre-19a35b98 {
+ .pre-7945d906 {
padding: 10px;
color: red;
text-align: center;
@@ -3308,7 +3281,7 @@ style {
>
-
+ {
+ state.name = event.target.value;
+})
+ on-click(event => component.doSomething())
+ />
+
+ Hello \${state.name} ! I can run in React, Vue, Solid, or Liquid!
+
"
+`;
+
exports[`Marko > jsx > Typescript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -4352,7 +4355,6 @@ class {
const ref = this.input.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -4405,11 +4407,6 @@ class {
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -4421,28 +4418,14 @@ class {
};
}
get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
}
get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
}
get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.input.block;
if (!repeat?.collection) {
@@ -4503,7 +4486,6 @@ class {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/parse-jsx.test.ts.snap b/packages/core/src/__tests__/__snapshots__/parse-jsx.test.ts.snap
index fa63ed3bbe..28bbf97707 100644
--- a/packages/core/src/__tests__/__snapshots__/parse-jsx.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/parse-jsx.test.ts.snap
@@ -3237,9 +3237,7 @@ exports[`Parse JSX > Javascript > CustomCode 1`] = `
"state": {
"findAndRunScripts": {
"code": "findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== 'undefined') {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName('script');
for (let i = 0; i < scripts.length; i++) {
@@ -3340,9 +3338,7 @@ exports[`Parse JSX > Javascript > Embed 1`] = `
"state": {
"findAndRunScripts": {
"code": "findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== 'undefined') {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName('script');
for (let i = 0; i < scripts.length; i++) {
@@ -3920,8 +3916,7 @@ exports[`Parse JSX > Javascript > Form 1`] = `
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(event.currentTarget.querySelectorAll('input,select,textarea')).filter(el => !!el.name).map(el => {
let value;
const key = el.name;
@@ -3944,7 +3939,6 @@ exports[`Parse JSX > Javascript > Form 1`] = `
value = num;
}
} else if (el.type === 'file') {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3970,14 +3964,11 @@ exports[`Parse JSX > Javascript > Form 1`] = `
if (value instanceof File || Array.isArray(value) && value[0] instanceof File || value instanceof FileList) {
contentType = 'multipart/form-data';
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== 'application/json') {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({
value,
@@ -3989,9 +3980,7 @@ exports[`Parse JSX > Javascript > Form 1`] = `
}
if (contentType && contentType !== 'multipart/form-data') {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes('zapier.com'))) {
+ if (!(sendWithJs && props.action?.includes('zapier.com'))) {
headers['content-type'] = contentType;
}
}
@@ -4012,9 +4001,7 @@ exports[`Parse JSX > Javascript > Form 1`] = `
state.formState = 'sending';
const formUrl = \`\${builder.env === 'dev' ? 'http://localhost:5000' : 'https://builder.io'}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(props.sendSubmissionsToEmail || '')}&name=\${encodeURIComponent(props.name || '')}\`;
- fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action
- /* TODO: throw error if no action URL */
- , {
+ fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action, {
body,
headers,
method: props.method || 'post'
@@ -4029,13 +4016,10 @@ exports[`Parse JSX > Javascript > Form 1`] = `
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== 'string') {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -4060,15 +4044,11 @@ exports[`Parse JSX > Javascript > Form 1`] = `
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
-
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
-
if (props.successUrl) {
if (formRef) {
@@ -4420,7 +4400,6 @@ exports[`Parse JSX > Javascript > Image 1`] = `
},
"useLazyLoading": {
"code": "useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
}",
"type": "method",
@@ -7468,6 +7447,140 @@ exports[`Parse JSX > Javascript > classState 1`] = `
}
`;
+exports[`Parse JSX > Javascript > commentsWithQuotes 1`] = `
+{
+ "@type": "@builder.io/mitosis/component",
+ "children": [
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "
+ ",
+ },
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {
+ "css": {
+ "code": "{
+ color: \\"red\\"
+}",
+ "type": "single",
+ },
+ "onChange": {
+ "arguments": [
+ "event",
+ ],
+ "code": "{
+ state.name = event.target.value;
+}",
+ "type": "single",
+ },
+ "onClick": {
+ "code": "state.doSomething()",
+ "type": "single",
+ },
+ "value": {
+ "code": "state.name",
+ "type": "single",
+ },
+ },
+ "children": [],
+ "meta": {},
+ "name": "input",
+ "properties": {},
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "
+ Hello
+ ",
+ },
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {
+ "_text": {
+ "code": "state.name",
+ "type": "single",
+ },
+ },
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {},
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "! I can run in React, Vue, Solid, or Liquid!
+ ",
+ },
+ "scope": {},
+ },
+ ],
+ "meta": {},
+ "name": "div",
+ "properties": {},
+ "scope": {},
+ },
+ ],
+ "context": {
+ "get": {},
+ "set": {},
+ },
+ "exports": {},
+ "hooks": {
+ "onEvent": [],
+ "onMount": [],
+ },
+ "imports": [],
+ "inputs": [],
+ "meta": {},
+ "name": "MyComponent",
+ "refs": {},
+ "state": {
+ "doSomething": {
+ "code": "function doSomething() {
+ console.log(\\"This is a aa\\");
+}",
+ "type": "function",
+ },
+ "handleFn": {
+ "code": "handleFn() {}",
+ "type": "method",
+ },
+ "name": {
+ "code": "\\"Steve\\"",
+ "propertyType": "normal",
+ "type": "property",
+ },
+ },
+ "subComponents": [],
+}
+`;
+
exports[`Parse JSX > Javascript > componentWithContext 1`] = `
{
"@type": "@builder.io/mitosis/component",
@@ -10409,12 +10522,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
},
"childrenWithoutParentComponent": {
"code": "get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef = !state.component?.component && !state.repeatItemData;
return shouldRenderChildrenOutsideRef ? state.useChildren : [];
}",
@@ -10436,7 +10543,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -10468,11 +10574,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
blockChildren: state.useChildren,
componentRef: state.component?.component,
componentOptions: { ...getBlockComponentOptions(state.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(state.shouldWrap ? {} : {
attributes: { ...state.attributes,
...state.actions
@@ -10490,7 +10591,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
if (TARGET === 'reactNative') {
return RenderComponentWithContext;
} else if (TARGET === 'vue3') {
- // vue3 expects a string for the component tag
return 'RenderComponent';
} else {
return RenderComponent;
@@ -10500,10 +10600,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
},
"repeatItemData": {
"code": "get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const {
repeat,
...blockWithoutRepeat
@@ -10565,10 +10661,6 @@ exports[`Parse JSX > Javascript > renderBlock 1`] = `
},
"useChildren": {
"code": "get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return state.useBlock.children ?? [];
}",
"type": "getter",
@@ -15920,9 +16012,7 @@ exports[`Parse JSX > Typescript > CustomCode 1`] = `
"state": {
"findAndRunScripts": {
"code": "findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== 'undefined') {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName('script');
for (let i = 0; i < scripts.length; i++) {
@@ -16031,9 +16121,7 @@ exports[`Parse JSX > Typescript > Embed 1`] = `
"state": {
"findAndRunScripts": {
"code": "findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== 'undefined') {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName('script');
for (let i = 0; i < scripts.length; i++) {
@@ -16622,8 +16710,7 @@ exports[`Parse JSX > Typescript > Form 1`] = `
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -16649,7 +16736,6 @@ exports[`Parse JSX > Typescript > Form 1`] = `
value = num;
}
} else if (el.type === 'file') {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -16675,14 +16761,11 @@ exports[`Parse JSX > Typescript > Form 1`] = `
if (value instanceof File || Array.isArray(value) && value[0] instanceof File || value instanceof FileList) {
contentType = 'multipart/form-data';
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== 'application/json') {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({
value,
@@ -16694,9 +16777,7 @@ exports[`Parse JSX > Typescript > Form 1`] = `
}
if (contentType && contentType !== 'multipart/form-data') {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes('zapier.com'))) {
+ if (!(sendWithJs && props.action?.includes('zapier.com'))) {
headers['content-type'] = contentType;
}
}
@@ -16717,9 +16798,7 @@ exports[`Parse JSX > Typescript > Form 1`] = `
state.formState = 'sending';
const formUrl = \`\${builder.env === 'dev' ? 'http://localhost:5000' : 'https://builder.io'}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(props.sendSubmissionsToEmail || '')}&name=\${encodeURIComponent(props.name || '')}\`;
- fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action!
- /* TODO: throw error if no action URL */
- , {
+ fetch(props.sendSubmissionsTo === 'email' ? formUrl : props.action!, {
body,
headers,
method: props.method || 'post'
@@ -16734,13 +16813,10 @@ exports[`Parse JSX > Typescript > Form 1`] = `
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== 'string') {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -16765,15 +16841,11 @@ exports[`Parse JSX > Typescript > Form 1`] = `
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
-
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
-
if (props.successUrl) {
if (formRef) {
@@ -17152,7 +17224,6 @@ exports[`Parse JSX > Typescript > Image 1`] = `
},
"useLazyLoading": {
"code": "useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
}",
"type": "method",
@@ -20386,6 +20457,140 @@ exports[`Parse JSX > Typescript > classState 1`] = `
}
`;
+exports[`Parse JSX > Typescript > commentsWithQuotes 1`] = `
+{
+ "@type": "@builder.io/mitosis/component",
+ "children": [
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "
+ ",
+ },
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {
+ "css": {
+ "code": "{
+ color: \\"red\\"
+}",
+ "type": "single",
+ },
+ "onChange": {
+ "arguments": [
+ "event",
+ ],
+ "code": "{
+ state.name = event.target.value;
+}",
+ "type": "single",
+ },
+ "onClick": {
+ "code": "state.doSomething()",
+ "type": "single",
+ },
+ "value": {
+ "code": "state.name",
+ "type": "single",
+ },
+ },
+ "children": [],
+ "meta": {},
+ "name": "input",
+ "properties": {},
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "
+ Hello
+ ",
+ },
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {
+ "_text": {
+ "code": "state.name",
+ "type": "single",
+ },
+ },
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {},
+ "scope": {},
+ },
+ {
+ "@type": "@builder.io/mitosis/node",
+ "bindings": {},
+ "children": [],
+ "meta": {},
+ "name": "div",
+ "properties": {
+ "_text": "! I can run in React, Vue, Solid, or Liquid!
+ ",
+ },
+ "scope": {},
+ },
+ ],
+ "meta": {},
+ "name": "div",
+ "properties": {},
+ "scope": {},
+ },
+ ],
+ "context": {
+ "get": {},
+ "set": {},
+ },
+ "exports": {},
+ "hooks": {
+ "onEvent": [],
+ "onMount": [],
+ },
+ "imports": [],
+ "inputs": [],
+ "meta": {},
+ "name": "MyComponent",
+ "refs": {},
+ "state": {
+ "doSomething": {
+ "code": "function doSomething() {
+ console.log(\\"This is a aa\\");
+}",
+ "type": "function",
+ },
+ "handleFn": {
+ "code": "handleFn() {}",
+ "type": "method",
+ },
+ "name": {
+ "code": "\\"Steve\\"",
+ "propertyType": "normal",
+ "type": "property",
+ },
+ },
+ "subComponents": [],
+}
+`;
+
exports[`Parse JSX > Typescript > componentWithContext 1`] = `
{
"@type": "@builder.io/mitosis/component",
@@ -23490,12 +23695,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
},
"childrenWithoutParentComponent": {
"code": "get childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef = !state.component?.component && !state.repeatItemData;
return shouldRenderChildrenOutsideRef ? state.useChildren : [];
}",
@@ -23517,7 +23716,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -23549,11 +23747,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
blockChildren: state.useChildren,
componentRef: state.component?.component,
componentOptions: { ...getBlockComponentOptions(state.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(state.shouldWrap ? {} : {
attributes: { ...state.attributes,
...state.actions
@@ -23571,7 +23764,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
if (TARGET === 'reactNative') {
return RenderComponentWithContext;
} else if (TARGET === 'vue3') {
- // vue3 expects a string for the component tag
return 'RenderComponent';
} else {
return RenderComponent;
@@ -23581,10 +23773,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
},
"repeatItemData": {
"code": "get repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const {
repeat,
...blockWithoutRepeat
@@ -23646,10 +23834,6 @@ exports[`Parse JSX > Typescript > renderBlock 1`] = `
},
"useChildren": {
"code": "get useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return state.useBlock.children ?? [];
}",
"type": "getter",
@@ -26146,12 +26330,7 @@ exports[`Parse JSX > parseStateObject 1`] = `
{
"allRegisteredComponents": {
"code": "get allRegisteredComponents() {
- const allComponentsArray = [...getDefaultRegisteredComponents(), // While this \`components\` object is deprecated, we must maintain support for it.
- // Since users are able to override our default components, we need to make sure that we do not break such
- // existing usage.
- // This is why we spread \`components\` after the default Builder.io components, but before the \`props.customComponents\`,
- // which is the new standard way of providing custom components, and must therefore take precedence.
- ...components, ...(props.customComponents || [])];
+ const allComponentsArray = [...getDefaultRegisteredComponents(), ...components, ...(props.customComponents || [])];
const allComponents = allComponentsArray.reduce((acc, curr) => ({ ...acc,
[curr.name]: curr
}), ({} as RegisteredComponents));
@@ -26207,7 +26386,6 @@ exports[`Parse JSX > parseStateObject 1`] = `
},
"evaluateJsCode": {
"code": "evaluateJsCode() {
- // run any dynamic JS code attached to content
const jsCode = state.useContent?.data?.jsCode;
if (jsCode) {
@@ -26299,7 +26477,6 @@ exports[`Parse JSX > parseStateObject 1`] = `
case 'builder.patchUpdates':
{
- // TODO
break;
}
}
diff --git a/packages/core/src/__tests__/__snapshots__/preact.test.ts.snap b/packages/core/src/__tests__/__snapshots__/preact.test.ts.snap
index 5dcf30ff6e..5c659e27bf 100644
--- a/packages/core/src/__tests__/__snapshots__/preact.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/preact.test.ts.snap
@@ -637,9 +637,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -709,9 +707,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -808,8 +804,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -836,7 +831,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -864,14 +858,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -880,77 +871,90 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -962,23 +966,28 @@ function FormComponent(props) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
);
}
+
export default FormComponent;
"
`;
@@ -1063,7 +1075,6 @@ function Image(props) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -1888,6 +1899,47 @@ export default MyBasicComponent;
"
`;
+exports[`Preact > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"/** @jsx h */
+import { h, Fragment } from \\"preact\\";
+import { useState } from \\"preact/hooks\\";
+
+function MyComponent(props) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`Preact > jsx > Javascript Test > componentWithContext 1`] = `
"/** @jsx h */
import { h, Fragment } from \\"preact\\";
@@ -2580,7 +2632,6 @@ export default OnUpdate;
exports[`Preact > jsx > Javascript Test > renderBlock 1`] = `
"/** @jsx h */
import { h, Fragment } from \\"preact\\";
-import { useState } from \\"preact/hooks\\";
import { TARGET } from \\"../../constants/target.js\\";
import { evaluate } from \\"../../functions/evaluate.js\\";
import { extractTextStyles } from \\"../../functions/extract-text-styles.js\\";
@@ -2612,7 +2663,6 @@ function RenderBlock(props) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -2671,11 +2721,6 @@ function RenderBlock(props) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -2688,30 +2733,16 @@ function RenderBlock(props) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -2775,15 +2806,12 @@ function RenderBlock(props) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
@@ -4013,9 +4041,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4090,9 +4116,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4217,8 +4241,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -4248,7 +4271,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -4276,14 +4298,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -4292,77 +4311,90 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action! /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -4374,23 +4406,28 @@ function FormComponent(props: FormProps) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
);
}
+
export default FormComponent;
"
`;
@@ -4494,7 +4534,6 @@ function Image(props: ImageProps) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -5457,6 +5496,47 @@ export default MyBasicComponent;
"
`;
+exports[`Preact > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"/** @jsx h */
+import { h, Fragment } from \\"preact\\";
+import { useState } from \\"preact/hooks\\";
+
+function MyComponent(props: any) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`Preact > jsx > Typescript Test > componentWithContext 1`] = `
"/** @jsx h */
import { h, Fragment } from \\"preact\\";
@@ -6239,7 +6319,6 @@ export default OnUpdate;
exports[`Preact > jsx > Typescript Test > renderBlock 1`] = `
"/** @jsx h */
import { h, Fragment } from \\"preact\\";
-import { useState } from \\"preact/hooks\\";
export type RenderBlockProps = {
block: BuilderBlock;
@@ -6284,7 +6363,6 @@ function RenderBlock(props: RenderBlockProps) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -6343,11 +6421,6 @@ function RenderBlock(props: RenderBlockProps) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -6360,30 +6433,16 @@ function RenderBlock(props: RenderBlockProps) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -6447,15 +6506,12 @@ function RenderBlock(props: RenderBlockProps) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
diff --git a/packages/core/src/__tests__/__snapshots__/qwik.test.ts.snap b/packages/core/src/__tests__/__snapshots__/qwik.test.ts.snap
index f41400aefa..4dfc7a8366 100644
--- a/packages/core/src/__tests__/__snapshots__/qwik.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/qwik.test.ts.snap
@@ -2393,9 +2393,7 @@ export const findAndRunScripts = function findAndRunScripts(
state,
elem
) {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -2470,9 +2468,7 @@ export const findAndRunScripts = function findAndRunScripts(
state,
elem
) {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -2568,8 +2564,7 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -2596,7 +2591,6 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -2624,14 +2618,11 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -2640,10 +2631,7 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -2668,15 +2656,11 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -2688,13 +2672,10 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -2719,13 +2700,11 @@ export const onSubmit = function onSubmit(props, state, formRef, event) {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.value.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef.value) {
@@ -2862,7 +2841,6 @@ export const useLazyLoading = function useLazyLoading(
state,
pictureRef
) {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
};
export const isBrowser = function isBrowser(props, state, pictureRef) {
@@ -3693,6 +3671,51 @@ export const STYLES = \`
"
`;
+exports[`qwik > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"import {
+ $,
+ Fragment,
+ component$,
+ h,
+ useStore,
+ useStylesScoped$,
+} from \\"@builder.io/qwik\\";
+
+export const handleFn = function handleFn(props, state) {};
+export const doSomething = function doSomething(props, state) {
+ console.log(\\"This is a aa\\");
+};
+export const MyComponent = component$((props) => {
+ useStylesScoped$(STYLES);
+
+ const state = useStore({ name: \\"Steve\\" });
+
+ return (
+
+ {
+ state.name = event.target.value;
+ })}
+ onClick$={$((event) => state.doSomething())}
+ />
+ Hello
+ {state.name}! I can run in React, Vue, Solid, or Liquid!
+
+ );
+});
+
+export default MyComponent;
+
+export const STYLES = \`
+.input-MyComponent {
+ color: red;
+}
+\`;
+"
+`;
+
exports[`qwik > jsx > Javascript Test > contentState 1`] = `
"import {
Fragment,
@@ -4285,7 +4308,6 @@ export const RenderBlock = component$((props) => {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -4338,11 +4360,6 @@ export const RenderBlock = component$((props) => {
componentRef: component.value?.component,
componentOptions: {
...getBlockComponentOptions(useBlock.value),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap.value
? {}
: {
@@ -4354,28 +4371,14 @@ export const RenderBlock = component$((props) => {
};
});
const useChildren = useComputed$(() => {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock.value.children ?? [];
});
const childrenWithoutParentComponent = useComputed$(() => {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component.value?.component && !repeatItemData.value;
return shouldRenderChildrenOutsideRef ? useChildren.value : [];
});
const repeatItemData = useComputed$(() => {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -4436,7 +4439,6 @@ export const RenderBlock = component$((props) => {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -5621,9 +5623,7 @@ export const findAndRunScripts = function findAndRunScripts(
state,
elem
) {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5702,9 +5702,7 @@ export const findAndRunScripts = function findAndRunScripts(
state,
elem
) {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -5830,8 +5828,7 @@ export const onSubmit = function onSubmit(
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -5861,7 +5858,6 @@ export const onSubmit = function onSubmit(
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -5889,14 +5885,11 @@ export const onSubmit = function onSubmit(
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -5905,10 +5898,7 @@ export const onSubmit = function onSubmit(
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -5933,15 +5923,11 @@ export const onSubmit = function onSubmit(
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -5953,13 +5939,10 @@ export const onSubmit = function onSubmit(
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -5984,13 +5967,11 @@ export const onSubmit = function onSubmit(
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.value.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef.value) {
@@ -6145,7 +6126,6 @@ export const useLazyLoading = function useLazyLoading(
state,
pictureRef
) {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && state.isBrowser();
};
export const isBrowser = function isBrowser(props, state, pictureRef) {
@@ -7103,6 +7083,51 @@ export const STYLES = \`
"
`;
+exports[`qwik > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"import {
+ $,
+ Fragment,
+ component$,
+ h,
+ useStore,
+ useStylesScoped$,
+} from \\"@builder.io/qwik\\";
+
+export const handleFn = function handleFn(props, state) {};
+export const doSomething = function doSomething(props, state) {
+ console.log(\\"This is a aa\\");
+};
+export const MyComponent = component$((props: any) => {
+ useStylesScoped$(STYLES);
+
+ const state = useStore({ name: \\"Steve\\" });
+
+ return (
+
+ {
+ state.name = event.target.value;
+ })}
+ onClick$={$((event) => state.doSomething())}
+ />
+ Hello
+ {state.name}! I can run in React, Vue, Solid, or Liquid!
+
+ );
+});
+
+export default MyComponent;
+
+export const STYLES = \`
+.input-MyComponent {
+ color: red;
+}
+\`;
+"
+`;
+
exports[`qwik > jsx > Typescript Test > contentState 1`] = `
"import {
Fragment,
@@ -7785,7 +7810,6 @@ export const RenderBlock = component$((props: RenderBlockProps) => {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -7838,11 +7862,6 @@ export const RenderBlock = component$((props: RenderBlockProps) => {
componentRef: component.value?.component,
componentOptions: {
...getBlockComponentOptions(useBlock.value),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap.value
? {}
: {
@@ -7854,28 +7873,14 @@ export const RenderBlock = component$((props: RenderBlockProps) => {
};
});
const useChildren = useComputed$(() => {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock.value.children ?? [];
});
const childrenWithoutParentComponent = useComputed$(() => {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component.value?.component && !repeatItemData.value;
return shouldRenderChildrenOutsideRef ? useChildren.value : [];
});
const repeatItemData = useComputed$(() => {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -7936,7 +7941,6 @@ export const RenderBlock = component$((props: RenderBlockProps) => {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/react-native.test.ts.snap b/packages/core/src/__tests__/__snapshots__/react-native.test.ts.snap
index 921230750b..469b007cf4 100644
--- a/packages/core/src/__tests__/__snapshots__/react-native.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/react-native.test.ts.snap
@@ -744,9 +744,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -815,9 +813,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -913,8 +909,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -941,7 +936,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -969,14 +963,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -985,77 +976,90 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -1067,20 +1071,26 @@ function FormComponent(props) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
onSubmit(event)}
{...props.attributes}
>
- {\\" \\"}
{props.builderBlock && props.builderBlock.children ? (
<>
{props.builderBlock?.children?.map((block, index) => (
))}
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"error\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"sending\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"error\\" && responseData ? (
<>
- {\\" \\"}
- {JSON.stringify(responseData, null, 2)}{\\" \\"}
+ {JSON.stringify(responseData, null, 2)}
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"success\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
);
}
+
const styles = StyleSheet.create({
view1: { padding: 10, color: \\"red\\", textAlign: \\"center\\" },
});
+
export default FormComponent;
"
`;
@@ -1161,7 +1175,6 @@ function Image(props) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -2131,6 +2144,50 @@ export default MyBasicComponent;
"
`;
+exports[`React Native > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"import * as React from \\"react\\";
+import {
+ FlatList,
+ ScrollView,
+ View,
+ StyleSheet,
+ Image,
+ Text,
+} from \\"react-native\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ style={styles.view1}
+ />
+ Hello
+ {name}
+ ! I can run in React, Vue, Solid, or Liquid!
+
+ );
+}
+
+const styles = StyleSheet.create({ view1: { color: \\"red\\" } });
+
+export default MyComponent;
+"
+`;
+
exports[`React Native > jsx > Javascript Test > componentWithContext 1`] = `
"import * as React from \\"react\\";
import {
@@ -3016,7 +3073,6 @@ import {
Image,
Text,
} from \\"react-native\\";
-import { useState } from \\"react\\";
import { TARGET } from \\"../../constants/target.js\\";
import { evaluate } from \\"../../functions/evaluate.js\\";
import { extractTextStyles } from \\"../../functions/extract-text-styles.js\\";
@@ -3048,7 +3104,6 @@ function RenderBlock(props) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -3107,11 +3162,6 @@ function RenderBlock(props) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -3124,30 +3174,16 @@ function RenderBlock(props) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -3211,15 +3247,12 @@ function RenderBlock(props) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
@@ -4682,9 +4715,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4758,9 +4789,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4884,8 +4913,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -4915,7 +4943,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -4943,14 +4970,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -4959,77 +4983,90 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action! /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -5041,20 +5078,26 @@ function FormComponent(props: FormProps) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
onSubmit(event)}
{...props.attributes}
>
- {\\" \\"}
{props.builderBlock && props.builderBlock.children ? (
<>
{props.builderBlock?.children?.map((block, index) => (
))}
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"error\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"sending\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"error\\" && responseData ? (
<>
- {\\" \\"}
- {JSON.stringify(responseData, null, 2)}{\\" \\"}
+ {JSON.stringify(responseData, null, 2)}
>
- ) : null}{\\" \\"}
+ ) : null}
+
{submissionState() === \\"success\\" ? (
<>
>
- ) : null}{\\" \\"}
+ ) : null}
);
}
+
const styles = StyleSheet.create({
view1: { padding: 10, color: \\"red\\", textAlign: \\"center\\" },
});
+
export default FormComponent;
"
`;
@@ -5154,7 +5201,6 @@ function Image(props: ImageProps) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -6262,6 +6308,50 @@ export default MyBasicComponent;
"
`;
+exports[`React Native > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"import * as React from \\"react\\";
+import {
+ FlatList,
+ ScrollView,
+ View,
+ StyleSheet,
+ Image,
+ Text,
+} from \\"react-native\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props: any) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ style={styles.view1}
+ />
+ Hello
+ {name}
+ ! I can run in React, Vue, Solid, or Liquid!
+
+ );
+}
+
+const styles = StyleSheet.create({ view1: { color: \\"red\\" } });
+
+export default MyComponent;
+"
+`;
+
exports[`React Native > jsx > Typescript Test > componentWithContext 1`] = `
"import * as React from \\"react\\";
import {
@@ -7237,7 +7327,6 @@ import {
Image,
Text,
} from \\"react-native\\";
-import { useState } from \\"react\\";
export type RenderBlockProps = {
block: BuilderBlock;
@@ -7282,7 +7371,6 @@ function RenderBlock(props: RenderBlockProps) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -7341,11 +7429,6 @@ function RenderBlock(props: RenderBlockProps) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -7358,30 +7441,16 @@ function RenderBlock(props: RenderBlockProps) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -7445,15 +7514,12 @@ function RenderBlock(props: RenderBlockProps) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
diff --git a/packages/core/src/__tests__/__snapshots__/react.test.ts.snap b/packages/core/src/__tests__/__snapshots__/react.test.ts.snap
index b5cb3227e2..abd6ef7ed6 100644
--- a/packages/core/src/__tests__/__snapshots__/react.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/react.test.ts.snap
@@ -632,9 +632,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -704,9 +702,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -803,8 +799,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -831,7 +826,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -859,14 +853,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -875,77 +866,90 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -957,23 +961,28 @@ function FormComponent(props) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
<>
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
>
);
}
+
export default FormComponent;
"
`;
@@ -1058,7 +1070,6 @@ function Image(props) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -1872,6 +1883,47 @@ export default MyBasicComponent;
"
`;
+exports[`React > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"\\"use client\\";
+import * as React from \\"react\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+ <>
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`React > jsx > Javascript Test > componentWithContext 1`] = `
"\\"use client\\";
import * as React from \\"react\\";
@@ -2554,9 +2606,7 @@ export default OnUpdate;
`;
exports[`React > jsx > Javascript Test > renderBlock 1`] = `
-"\\"use client\\";
-import * as React from \\"react\\";
-import { useState } from \\"react\\";
+"import * as React from \\"react\\";
import { TARGET } from \\"../../constants/target.js\\";
import { evaluate } from \\"../../functions/evaluate.js\\";
import { extractTextStyles } from \\"../../functions/extract-text-styles.js\\";
@@ -2588,7 +2638,6 @@ function RenderBlock(props) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -2647,11 +2696,6 @@ function RenderBlock(props) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -2664,30 +2708,16 @@ function RenderBlock(props) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -2751,15 +2781,12 @@ function RenderBlock(props) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
@@ -3962,9 +3989,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4039,9 +4064,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4166,8 +4189,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -4197,7 +4219,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -4225,14 +4246,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -4241,77 +4259,90 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action! /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -4323,23 +4354,28 @@ function FormComponent(props: FormProps) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
<>
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
>
);
}
+
export default FormComponent;
"
`;
@@ -4443,7 +4482,6 @@ function Image(props: ImageProps) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -5395,6 +5433,47 @@ export default MyBasicComponent;
"
`;
+exports[`React > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"\\"use client\\";
+import * as React from \\"react\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props: any) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+ <>
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`React > jsx > Typescript Test > componentWithContext 1`] = `
"\\"use client\\";
import * as React from \\"react\\";
@@ -6167,9 +6246,7 @@ export default OnUpdate;
`;
exports[`React > jsx > Typescript Test > renderBlock 1`] = `
-"\\"use client\\";
-import * as React from \\"react\\";
-import { useState } from \\"react\\";
+"import * as React from \\"react\\";
export type RenderBlockProps = {
block: BuilderBlock;
@@ -6214,7 +6291,6 @@ function RenderBlock(props: RenderBlockProps) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -6273,11 +6349,6 @@ function RenderBlock(props: RenderBlockProps) {
componentRef: component?.()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -6290,30 +6361,16 @@ function RenderBlock(props: RenderBlockProps) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? useBlock().children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`useBlock()\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -6377,15 +6434,12 @@ function RenderBlock(props: RenderBlockProps) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
}
}
- const [componentInfo, setComponentInfo] = useState(() => null);
-
const RenderComponentTagRef = renderComponentTag();
const TagRef = tag();
diff --git a/packages/core/src/__tests__/__snapshots__/rsc.test.ts.snap b/packages/core/src/__tests__/__snapshots__/rsc.test.ts.snap
index 2c95aa1fae..2459844405 100644
--- a/packages/core/src/__tests__/__snapshots__/rsc.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/rsc.test.ts.snap
@@ -629,9 +629,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -701,9 +699,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -800,8 +796,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -828,7 +823,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -856,14 +850,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -872,77 +863,90 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -954,23 +958,28 @@ function FormComponent(props) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
<>
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
>
);
}
+
export default FormComponent;
"
`;
@@ -1055,7 +1067,6 @@ function Image(props) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -1869,6 +1880,47 @@ export default MyBasicComponent;
"
`;
+exports[`RSC > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"\\"use client\\";
+import * as React from \\"react\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+ <>
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`RSC > jsx > Javascript Test > componentWithContext 1`] = `
"\\"use client\\";
import * as React from \\"react\\";
@@ -2551,14 +2603,14 @@ export default OnUpdate;
`;
exports[`RSC > jsx > Javascript Test > renderBlock 1`] = `
-"Identifier expected. (212:10)
- 210 | {shouldWrap() ? (
- 211 | <>{isEmptyHtmlElement(tag()) ? (
-> 212 | <>>
- | ^
- 213 | ) : null}
- 214 | {!isEmptyHtmlElement(tag()) && repeatItemData() ? (
- 215 | <>{repeatItemData()?.map((data, index) => ("
+"Identifier expected. (190:9)
+ 188 | {shouldWrap() ? (
+ 189 | <>{isEmptyHtmlElement(tag()) ? (
+> 190 | <>>
+ | ^
+ 191 | ) : null}
+ 192 | {!isEmptyHtmlElement(tag()) && repeatItemData() ? (
+ 193 | <>{repeatItemData()?.map((data, index) => ("
`;
exports[`RSC > jsx > Javascript Test > renderContentExample 1`] = `
@@ -3697,9 +3749,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3774,9 +3824,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = useState(() => []);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.current && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.current.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3901,8 +3949,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -3932,7 +3979,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3960,14 +4006,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -3976,77 +4019,90 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */ !(
- sendWithJs && props.action?.includes(\\"zapier.com\\")
- )
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
- const presubmitEvent = new CustomEvent(\\"presubmit\\", { detail: { body } });
+
+ const presubmitEvent = new CustomEvent(\\"presubmit\\", {
+ detail: {
+ body,
+ },
+ });
+
if (formRef.current) {
formRef.current.dispatchEvent(presubmitEvent);
+
if (presubmitEvent.defaultPrevented) {
return;
}
}
+
setFormState(\\"sending\\");
const formUrl = \`\${
builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\"
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\"
- ? formUrl
- : props.action! /* TODO: throw error if no action URL */,
- { body, headers, method: props.method || \\"post\\" }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
+
if (contentType && contentType.indexOf(\\"application/json\\") !== -1) {
body = await res.json();
} else {
body = await res.text();
}
+
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */ let message =
- get(body, props.errorMessagePath);
+ let message = get(body, props.errorMessagePath);
+
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message =
- JSON.stringify(message);
+ message = JSON.stringify(message);
}
+
setFormErrorMessage(message);
}
}
+
setResponseData(body);
setFormState(res.ok ? \\"success\\" : \\"error\\");
+
if (res.ok) {
const submitSuccessEvent = new CustomEvent(\\"submit:success\\", {
- detail: { res, body },
+ detail: {
+ res,
+ body,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitSuccessEvent);
+
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */ if (
- props.resetFormOnSubmit !== false
- ) {
+
+ if (props.resetFormOnSubmit !== false) {
formRef.current.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */ if (
- props.successUrl
- ) {
+
+ if (props.successUrl) {
if (formRef.current) {
const event = new CustomEvent(\\"route\\", {
- detail: { url: props.successUrl },
+ detail: {
+ url: props.successUrl,
+ },
});
formRef.current.dispatchEvent(event);
+
if (!event.defaultPrevented) {
location.href = props.successUrl;
}
@@ -4058,23 +4114,28 @@ function FormComponent(props: FormProps) {
},
(err) => {
const submitErrorEvent = new CustomEvent(\\"submit:error\\", {
- detail: { error: err },
+ detail: {
+ error: err,
+ },
});
+
if (formRef.current) {
formRef.current.dispatchEvent(submitErrorEvent);
+
if (submitErrorEvent.defaultPrevented) {
return;
}
}
+
setResponseData(err);
setFormState(\\"error\\");
}
);
}
}
+
return (
<>
- {\\" \\"}
{\\" \\"}
+ ) : null}
+
{\\" \\"}
+ \`}
>
);
}
+
export default FormComponent;
"
`;
@@ -4178,7 +4242,6 @@ function Image(props: ImageProps) {
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
@@ -5130,6 +5193,47 @@ export default MyBasicComponent;
"
`;
+exports[`RSC > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"\\"use client\\";
+import * as React from \\"react\\";
+import { useState } from \\"react\\";
+
+function MyComponent(props: any) {
+ const [name, setName] = useState(() => \\"Steve\\");
+
+ function handleFn() {}
+
+ function doSomething() {
+ console.log(\\"This is a aa\\");
+ }
+
+ return (
+ <>
+
+ {
+ setName(event.target.value);
+ }}
+ onClick={(event) => doSomething()}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`RSC > jsx > Typescript Test > componentWithContext 1`] = `
"\\"use client\\";
import * as React from \\"react\\";
@@ -5902,14 +6006,14 @@ export default OnUpdate;
`;
exports[`RSC > jsx > Typescript Test > renderBlock 1`] = `
-"Identifier expected. (220:10)
- 218 | {shouldWrap() ? (
- 219 | <>{isEmptyHtmlElement(tag()) ? (
-> 220 | <>>
- | ^
- 221 | ) : null}
- 222 | {!isEmptyHtmlElement(tag()) && repeatItemData() ? (
- 223 | <>{repeatItemData()?.map((data, index) => ("
+"Identifier expected. (198:9)
+ 196 | {shouldWrap() ? (
+ 197 | <>{isEmptyHtmlElement(tag()) ? (
+> 198 | <>>
+ | ^
+ 199 | ) : null}
+ 200 | {!isEmptyHtmlElement(tag()) && repeatItemData() ? (
+ 201 | <>{repeatItemData()?.map((data, index) => ("
`;
exports[`RSC > jsx > Typescript Test > renderContentExample 1`] = `
diff --git a/packages/core/src/__tests__/__snapshots__/solid.test.ts.snap b/packages/core/src/__tests__/__snapshots__/solid.test.ts.snap
index cc09103256..6728028015 100644
--- a/packages/core/src/__tests__/__snapshots__/solid.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/solid.test.ts.snap
@@ -1289,9 +1289,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1362,9 +1360,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1435,9 +1431,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1508,9 +1502,7 @@ function CustomCode(props) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -1611,8 +1603,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1639,7 +1630,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1667,14 +1657,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1683,10 +1670,7 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -1711,15 +1695,11 @@ function FormComponent(props) {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -1731,13 +1711,10 @@ function FormComponent(props) {
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -1762,13 +1739,11 @@ function FormComponent(props) {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef) {
@@ -1915,8 +1890,7 @@ function FormComponent(props) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1943,7 +1917,6 @@ function FormComponent(props) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1971,14 +1944,11 @@ function FormComponent(props) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1987,10 +1957,7 @@ function FormComponent(props) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -2015,15 +1982,11 @@ function FormComponent(props) {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -2035,13 +1998,10 @@ function FormComponent(props) {
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -2066,13 +2026,11 @@ function FormComponent(props) {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef) {
@@ -2154,7 +2112,7 @@ function FormComponent(props) {
>
-
+
{JSON.stringify(responseData(), null, 2)}
@@ -2166,7 +2124,7 @@ function FormComponent(props) {
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`Solid > jsx > Javascript Test > componentWithContext 1`] = `
"import { useContext } from \\"solid-js\\";
@@ -5098,7 +5131,6 @@ function RenderBlock(props) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -5157,11 +5189,6 @@ function RenderBlock(props) {
componentRef: component()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -5174,30 +5201,16 @@ function RenderBlock(props) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -5261,7 +5274,6 @@ function RenderBlock(props) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -5372,7 +5384,6 @@ function RenderBlock(props) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -5431,11 +5442,6 @@ function RenderBlock(props) {
componentRef: component()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -5448,30 +5454,16 @@ function RenderBlock(props) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -5535,7 +5527,6 @@ function RenderBlock(props) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -7918,9 +7909,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -7995,9 +7984,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -8073,9 +8060,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -8150,9 +8135,7 @@ function CustomCode(props: CustomCodeProps) {
const [scriptsRun, setScriptsRun] = createSignal([]);
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -8280,8 +8263,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -8311,7 +8293,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -8339,14 +8320,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -8355,10 +8333,7 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -8383,15 +8358,11 @@ function FormComponent(props: FormProps) {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -8403,13 +8374,10 @@ function FormComponent(props: FormProps) {
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -8434,13 +8402,11 @@ function FormComponent(props: FormProps) {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef) {
@@ -8614,8 +8580,7 @@ function FormComponent(props: FormProps) {
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -8645,7 +8610,6 @@ function FormComponent(props: FormProps) {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -8673,14 +8637,11 @@ function FormComponent(props: FormProps) {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -8689,10 +8650,7 @@ function FormComponent(props: FormProps) {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -8717,15 +8675,11 @@ function FormComponent(props: FormProps) {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -8737,13 +8691,10 @@ function FormComponent(props: FormProps) {
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -8768,13 +8719,11 @@ function FormComponent(props: FormProps) {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef) {
@@ -8856,7 +8805,7 @@ function FormComponent(props: FormProps) {
>
-
+
{JSON.stringify(responseData(), null, 2)}
@@ -8868,7 +8817,7 @@ function FormComponent(props: FormProps) {
+ >
+ );
+}
+
+export default MyComponent;
+"
+`;
+
exports[`Solid > jsx > Typescript Test > componentWithContext 1`] = `
"import { useContext } from \\"solid-js\\";
@@ -12256,7 +12280,6 @@ function RenderBlock(props: RenderBlockProps) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -12315,11 +12338,6 @@ function RenderBlock(props: RenderBlockProps) {
componentRef: component()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -12332,30 +12350,16 @@ function RenderBlock(props: RenderBlockProps) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -12419,7 +12423,6 @@ function RenderBlock(props: RenderBlockProps) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -12542,7 +12545,6 @@ function RenderBlock(props: RenderBlockProps) {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -12601,11 +12603,6 @@ function RenderBlock(props: RenderBlockProps) {
componentRef: component()?.component,
componentOptions: {
...getBlockComponentOptions(useBlock()),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap()
? {}
: {
@@ -12618,30 +12615,16 @@ function RenderBlock(props: RenderBlockProps) {
}
function useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock().children ?? [];
}
function childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component()?.component && !repeatItemData();
return shouldRenderChildrenOutsideRef ? useChildren() : [];
}
function repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -12705,7 +12688,6 @@ function RenderBlock(props: RenderBlockProps) {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/stencil.test.ts.snap b/packages/core/src/__tests__/__snapshots__/stencil.test.ts.snap
index 2222ba7768..94f8056374 100644
--- a/packages/core/src/__tests__/__snapshots__/stencil.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/stencil.test.ts.snap
@@ -618,9 +618,7 @@ export default class CustomCode {
@State() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -692,9 +690,7 @@ export default class CustomCode {
@State() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -815,8 +811,7 @@ export default class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -843,7 +838,6 @@ export default class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -871,14 +865,11 @@ export default class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -887,10 +878,7 @@ export default class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -915,15 +903,11 @@ export default class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -935,13 +919,10 @@ export default class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -966,13 +947,11 @@ export default class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (formRef) {
@@ -1109,7 +1088,6 @@ export default class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -2006,6 +1984,45 @@ export default class MyBasicComponent {
"
`;
+exports[`Stencil > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"import { Component, Prop, h, State, Fragment } from \\"@stencil/core\\";
+
+@Component({
+ tag: \\"my-component\\",
+ styles: \`
+ .input {
+ color: red;
+ }
+\`,
+})
+export default class MyComponent {
+ @State() name = \\"Steve\\";
+
+ handleFn() {}
+ doSomething = function doSomething() {
+ console.log(\\"This is a aa\\");
+ };
+
+ render() {
+ return (
+
+ {
+ this.name = event.target.value;
+ }}
+ onClick={(event) => this.doSomething()}
+ />
+ Hello
+ {this.name}! I can run in React, Vue, Solid, or Liquid!
+
+ );
+ }
+}
+"
+`;
+
exports[`Stencil > jsx > Javascript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -2604,14 +2621,14 @@ export default class OnUpdate {
`;
exports[`Stencil > jsx > Javascript Test > renderBlock 1`] = `
-"':' expected. (205:15)
- 203 | return (
- 204 |
-> 205 | {this.shouldWrap ? (
+"':' expected. (184:15)
+ 182 | return (
+ 183 |
+> 184 | {this.shouldWrap ? (
| ^
- 206 | <>{isEmptyHtmlElement(this.tag) ? (
- 207 | <>>
- 208 | ) : null}"
+ 185 | <>{isEmptyHtmlElement(this.tag) ? (
+ 186 | <>>
+ 187 | ) : null}"
`;
exports[`Stencil > jsx > Javascript Test > renderContentExample 1`] = `
@@ -3663,9 +3680,7 @@ export default class CustomCode {
@State() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3737,9 +3752,7 @@ export default class CustomCode {
@State() scriptsRun = [];
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3864,8 +3877,7 @@ export default class FormComponent {
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -3895,7 +3907,6 @@ export default class FormComponent {
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3923,14 +3934,11 @@ export default class FormComponent {
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -3939,10 +3947,7 @@ export default class FormComponent {
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -3967,15 +3972,11 @@ export default class FormComponent {
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -3987,13 +3988,10 @@ export default class FormComponent {
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -4018,13 +4016,11 @@ export default class FormComponent {
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (formRef) {
@@ -4161,7 +4157,6 @@ export default class Image {
this.imageLoaded = true;
}
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
}
isBrowser = function isBrowser() {
@@ -5060,6 +5055,45 @@ export default class MyBasicComponent {
"
`;
+exports[`Stencil > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"import { Component, Prop, h, State, Fragment } from \\"@stencil/core\\";
+
+@Component({
+ tag: \\"my-component\\",
+ styles: \`
+ .input {
+ color: red;
+ }
+\`,
+})
+export default class MyComponent {
+ @State() name = \\"Steve\\";
+
+ handleFn() {}
+ doSomething = function doSomething() {
+ console.log(\\"This is a aa\\");
+ };
+
+ render() {
+ return (
+
+ {
+ this.name = event.target.value;
+ }}
+ onClick={(event) => this.doSomething()}
+ />
+ Hello
+ {this.name}! I can run in React, Vue, Solid, or Liquid!
+
+ );
+ }
+}
+"
+`;
+
exports[`Stencil > jsx > Typescript Test > componentWithContext 1`] = `
"import Context1 from \\"@dummy/1\\";
import Context2 from \\"@dummy/2\\";
@@ -5659,14 +5693,14 @@ export default class OnUpdate {
`;
exports[`Stencil > jsx > Typescript Test > renderBlock 1`] = `
-"':' expected. (210:15)
- 208 | return (
- 209 |
-> 210 | {this.shouldWrap ? (
+"':' expected. (189:15)
+ 187 | return (
+ 188 |
+> 189 | {this.shouldWrap ? (
| ^
- 211 | <>{isEmptyHtmlElement(this.tag) ? (
- 212 | <>>
- 213 | ) : null}"
+ 190 | <>{isEmptyHtmlElement(this.tag) ? (
+ 191 | <>>
+ 192 | ) : null}"
`;
exports[`Stencil > jsx > Typescript Test > renderContentExample 1`] = `
diff --git a/packages/core/src/__tests__/__snapshots__/svelte.test.ts.snap b/packages/core/src/__tests__/__snapshots__/svelte.test.ts.snap
index 36a6dcc965..789864d338 100644
--- a/packages/core/src/__tests__/__snapshots__/svelte.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/svelte.test.ts.snap
@@ -507,9 +507,7 @@ exports[`Svelte > jsx > Javascript Test > CustomCode 1`] = `
export let code;
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -574,9 +572,7 @@ exports[`Svelte > jsx > Javascript Test > Embed 1`] = `
export let code;
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -677,8 +673,7 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
const el = event.currentTarget;
const headers = customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -705,7 +700,6 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -733,14 +727,11 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -749,10 +740,7 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -777,15 +765,11 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(name || \\"\\")}\`;
- fetch(
- sendSubmissionsTo === \\"email\\" ? formUrl : action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: method || \\"post\\",
- }
- ).then(
+ fetch(sendSubmissionsTo === \\"email\\" ? formUrl : action, {
+ body,
+ headers,
+ method: method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -797,13 +781,10 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
}
if (!res.ok && errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -828,13 +809,11 @@ exports[`Svelte > jsx > Javascript Test > Form 1`] = `
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (resetFormOnSubmit !== false) {
formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (successUrl) {
if (formRef) {
@@ -947,7 +926,6 @@ exports[`Svelte > jsx > Javascript Test > Image 1`] = `
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!lazy && isBrowser();
}
@@ -1643,6 +1621,36 @@ exports[`Svelte > jsx > Javascript Test > classState 1`] = `
"
`;
+exports[`Svelte > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"
+
+
+ {
+ doSomething();
+ }}
+ bind:value={name}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+ {
+ doSomething();
+ }}
+ bind:value={name}
+ />
+ Hello
+ {name}! I can run in React, Vue, Solid, or Liquid!
+
+
+"
+`;
+
exports[`Svelte > jsx > Typescript Test > componentWithContext 1`] = `
"
+
+"
+`;
+
exports[`Vue > jsx > Javascript Test > componentWithContext 1`] = `
"
{{ foo.value }}
@@ -2448,7 +2458,6 @@ const component = computed(() => {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -2501,11 +2510,6 @@ const renderComponentProps = computed(() => {
componentRef: component?.component,
componentOptions: {
...getBlockComponentOptions(useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap
? {}
: {
@@ -2517,28 +2521,14 @@ const renderComponentProps = computed(() => {
};
});
const useChildren = computed(() => {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock.children ?? [];
});
const childrenWithoutParentComponent = computed(() => {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.component && !repeatItemData;
return shouldRenderChildrenOutsideRef ? useChildren : [];
});
const repeatItemData = computed(() => {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -2599,7 +2589,6 @@ const renderComponentTag = computed(() => {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -3619,9 +3608,7 @@ onMounted(() => {
});
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3705,9 +3692,7 @@ onMounted(() => {
});
function findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (elem.value && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = elem.value.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3876,8 +3861,7 @@ function onSubmit(
const el = event.currentTarget;
const headers = props.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -3907,7 +3891,6 @@ function onSubmit(
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -3935,14 +3918,11 @@ function onSubmit(
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -3951,10 +3931,7 @@ function onSubmit(
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && props.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && props.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -3979,15 +3956,11 @@ function onSubmit(
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
props.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(props.name || \\"\\")}\`;
- fetch(
- props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: props.method || \\"post\\",
- }
- ).then(
+ fetch(props.sendSubmissionsTo === \\"email\\" ? formUrl : props.action!, {
+ body,
+ headers,
+ method: props.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -3999,13 +3972,10 @@ function onSubmit(
}
if (!res.ok && props.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, props.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -4030,13 +4000,11 @@ function onSubmit(
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (props.resetFormOnSubmit !== false) {
formRef.value.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (props.successUrl) {
if (formRef.value) {
@@ -4177,7 +4145,6 @@ function setLoaded() {
imageLoaded.value = true;
}
function useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!props.lazy && isBrowser();
}
function isBrowser() {
@@ -5003,6 +4970,38 @@ function _classStringToObject(str: string) {
"
`;
+exports[`Vue > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello
+ {{ name }}! I can run in React, Vue, Solid, or Liquid!
+
+
+
+
+
+"
+`;
+
exports[`Vue > jsx > Typescript Test > componentWithContext 1`] = `
"
{{ foo.value }}
@@ -5728,7 +5727,6 @@ const component = computed(() => {
const ref = props.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -5781,11 +5779,6 @@ const renderComponentProps = computed(() => {
componentRef: component?.component,
componentOptions: {
...getBlockComponentOptions(useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(shouldWrap
? {}
: {
@@ -5797,28 +5790,14 @@ const renderComponentProps = computed(() => {
};
});
const useChildren = computed(() => {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return useBlock.children ?? [];
});
const childrenWithoutParentComponent = computed(() => {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!component?.component && !repeatItemData;
return shouldRenderChildrenOutsideRef ? useChildren : [];
});
const repeatItemData = computed(() => {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = props.block;
if (!repeat?.collection) {
@@ -5879,7 +5858,6 @@ const renderComponentTag = computed(() => {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/vue.test.ts.snap b/packages/core/src/__tests__/__snapshots__/vue.test.ts.snap
index ec0d8abcfe..69ef3f3f6f 100644
--- a/packages/core/src/__tests__/__snapshots__/vue.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/vue.test.ts.snap
@@ -722,9 +722,7 @@ export default defineComponent({
methods: {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -809,9 +807,7 @@ export default defineComponent({
methods: {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -983,8 +979,7 @@ export default defineComponent({
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs = Array.from(
event.currentTarget.querySelectorAll(\\"input,select,textarea\\")
)
@@ -1011,7 +1006,6 @@ export default defineComponent({
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -1039,14 +1033,11 @@ export default defineComponent({
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -1055,10 +1046,7 @@ export default defineComponent({
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -1083,15 +1071,11 @@ export default defineComponent({
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -1103,13 +1087,10 @@ export default defineComponent({
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -1134,13 +1115,11 @@ export default defineComponent({
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.$refs.formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.$refs.formRef) {
@@ -1268,7 +1247,6 @@ export default defineComponent({
this.imageLoaded = true;
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
},
isBrowser: function isBrowser() {
@@ -2165,6 +2143,46 @@ export default defineComponent({
"
`;
+exports[`Vue > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello
+ {{ name }}! I can run in React, Vue, Solid, or Liquid!
+
+
+
+
+
+"
+`;
+
exports[`Vue > jsx > Javascript Test > componentWithContext 1`] = `
"
{{ foo.value }}
@@ -2987,7 +3005,6 @@ export default defineComponent({
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -3040,11 +3057,6 @@ export default defineComponent({
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -3056,28 +3068,14 @@ export default defineComponent({
};
},
useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
},
childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
},
repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -3138,7 +3136,6 @@ export default defineComponent({
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
@@ -4443,9 +4440,7 @@ export default defineComponent({
methods: {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4535,9 +4530,7 @@ export default defineComponent({
methods: {
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (this.$refs.elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = this.$refs.elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -4737,8 +4730,7 @@ export default defineComponent({
const el = event.currentTarget;
const headers = this.customHeaders || {};
let body: any;
- const formData = new FormData(el); // TODO: maybe support null
-
+ const formData = new FormData(el);
const formPairs: {
key: string;
value: File | boolean | number | string | FileList;
@@ -4768,7 +4760,6 @@ export default defineComponent({
value = num;
}
} else if (el.type === \\"file\\") {
- // TODO: one vs multiple files
value = el.files;
} else {
value = el.value;
@@ -4796,14 +4787,11 @@ export default defineComponent({
) {
contentType = \\"multipart/form-data\\";
}
- }); // TODO: send as urlEncoded or multipart by default
- // because of ease of use and reliability in browser API
- // for encoding the form?
+ });
if (contentType !== \\"application/json\\") {
body = formData;
} else {
- // Json
const json = {};
Array.from(formPairs).forEach(({ value, key }) => {
set(json, key, value);
@@ -4812,10 +4800,7 @@ export default defineComponent({
}
if (contentType && contentType !== \\"multipart/form-data\\") {
- if (
- /* Zapier doesn't allow content-type header to be sent from browsers */
- !(sendWithJs && this.action?.includes(\\"zapier.com\\"))
- ) {
+ if (!(sendWithJs && this.action?.includes(\\"zapier.com\\"))) {
headers[\\"content-type\\"] = contentType;
}
}
@@ -4840,15 +4825,11 @@ export default defineComponent({
}/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa(
this.sendSubmissionsToEmail || \\"\\"
)}&name=\${encodeURIComponent(this.name || \\"\\")}\`;
- fetch(
- this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!,
- /* TODO: throw error if no action URL */
- {
- body,
- headers,
- method: this.method || \\"post\\",
- }
- ).then(
+ fetch(this.sendSubmissionsTo === \\"email\\" ? formUrl : this.action!, {
+ body,
+ headers,
+ method: this.method || \\"post\\",
+ }).then(
async (res) => {
let body;
const contentType = res.headers.get(\\"content-type\\");
@@ -4860,13 +4841,10 @@ export default defineComponent({
}
if (!res.ok && this.errorMessagePath) {
- /* TODO: allow supplying an error formatter function */
let message = get(body, this.errorMessagePath);
if (message) {
if (typeof message !== \\"string\\") {
- /* TODO: ideally convert json to yaml so it woul dbe like
- error: - email has been taken */
message = JSON.stringify(message);
}
@@ -4891,13 +4869,11 @@ export default defineComponent({
if (submitSuccessEvent.defaultPrevented) {
return;
}
- /* TODO: option to turn this on/off? */
if (this.resetFormOnSubmit !== false) {
this.$refs.formRef.reset();
}
}
- /* TODO: client side route event first that can be preventDefaulted */
if (this.successUrl) {
if (this.$refs.formRef) {
@@ -5044,7 +5020,6 @@ export default defineComponent({
this.imageLoaded = true;
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!this.lazy && this.isBrowser();
},
isBrowser: function isBrowser() {
@@ -6082,6 +6057,46 @@ export default defineComponent({
"
`;
+exports[`Vue > jsx > Typescript Test > commentsWithQuotes 1`] = `
+"
+
+
+ Hello
+ {{ name }}! I can run in React, Vue, Solid, or Liquid!
+
+
+
+
+
+"
+`;
+
exports[`Vue > jsx > Typescript Test > componentWithContext 1`] = `
"
{{ foo.value }}
@@ -7005,7 +7020,6 @@ export default defineComponent({
const ref = this.context.registeredComponents[componentName];
if (!ref) {
- // TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
@@ -7058,11 +7072,6 @@ export default defineComponent({
componentRef: this.component?.component,
componentOptions: {
...getBlockComponentOptions(this.useBlock),
-
- /**
- * These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
- * they are provided to the component itself directly.
- */
...(this.shouldWrap
? {}
: {
@@ -7074,28 +7083,14 @@ export default defineComponent({
};
},
useChildren() {
- // TO-DO: When should \`canHaveChildren\` dictate rendering?
- // This is currently commented out because some Builder components (e.g. Box) do not have \`canHaveChildren: true\`,
- // but still receive and need to render children.
- // return state.componentInfo?.canHaveChildren ? state.useBlock.children : [];
return this.useBlock.children ?? [];
},
childrenWithoutParentComponent() {
- /**
- * When there is no \`componentRef\`, there might still be children that need to be rendered. In this case,
- * we render them outside of \`componentRef\`.
- * NOTE: We make sure not to render this if \`repeatItemData\` is non-null, because that means we are rendering an array of
- * blocks, and the children will be repeated within those blocks.
- */
const shouldRenderChildrenOutsideRef =
!this.component?.component && !this.repeatItemData;
return shouldRenderChildrenOutsideRef ? this.useChildren : [];
},
repeatItemData() {
- /**
- * we don't use \`state.useBlock\` here because the processing done within its logic includes evaluating the block's bindings,
- * which will not work if there is a repeat.
- */
const { repeat, ...blockWithoutRepeat } = this.block;
if (!repeat?.collection) {
@@ -7156,7 +7151,6 @@ export default defineComponent({
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
- // vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
diff --git a/packages/core/src/__tests__/__snapshots__/webcomponent.test.ts.snap b/packages/core/src/__tests__/__snapshots__/webcomponent.test.ts.snap
index 495f4b622a..f0c8588dff 100644
--- a/packages/core/src/__tests__/__snapshots__/webcomponent.test.ts.snap
+++ b/packages/core/src/__tests__/__snapshots__/webcomponent.test.ts.snap
@@ -3601,9 +3601,7 @@ class CustomCode extends HTMLElement {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (self._elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = self._elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3764,9 +3762,7 @@ class CustomCode extends HTMLElement {
scriptsInserted: [],
scriptsRun: [],
findAndRunScripts() {
- // TODO: Move this function to standalone one in '@builder.io/utils'
if (self._elem && typeof window !== \\"undefined\\") {
- /** @type {HTMLScriptElement[]} */
const scripts = self._elem.getElementsByTagName(\\"script\\");
for (let i = 0; i < scripts.length; i++) {
@@ -3931,7 +3927,6 @@ class Image extends HTMLElement {
self.update();
},
useLazyLoading() {
- // TODO: Add more checks here, like testing for real web browsers
return !!self.props.lazy && self.state.isBrowser();
},
isBrowser: function isBrowser() {
@@ -7963,6 +7958,180 @@ customElements.define(\\"my-basic-component\\", MyBasicComponent);
"
`;
+exports[`webcomponent > jsx > Javascript Test > commentsWithQuotes 1`] = `
+"/**
+ * Usage:
+ *
+ *
+ *
+ */
+class MyComponent extends HTMLElement {
+ get _root() {
+ return this.shadowRoot || this;
+ }
+
+ constructor() {
+ super();
+ const self = this;
+
+ this.state = {
+ name: \\"Steve\\",
+ handleFn() {},
+ doSomething: function doSomething() {
+ console.log(\\"This is a aa\\");
+ },
+ };
+ if (!this.props) {
+ this.props = {};
+ }
+
+ // used to keep track of all nodes created by show/for
+ this.nodesToDestroy = [];
+ // batch updates
+ this.pendingUpdate = false;
+
+ // Event handler for 'input' event on input-my-component-1
+ this.onInputMyComponent1Input = (event) => {
+ this.state.name = event.target.value;
+ this.update();
+ };
+
+ // Event handler for 'click' event on input-my-component-1
+ this.onInputMyComponent1Click = (event) => {
+ this.state.doSomething();
+ };
+
+ if (undefined) {
+ this.attachShadow({ mode: \\"open\\" });
+ }
+ }
+
+ destroyAnyNodes() {
+ // destroy current view template refs before rendering again
+ this.nodesToDestroy.forEach((el) => el.remove());
+ this.nodesToDestroy = [];
+ }
+
+ connectedCallback() {
+ this._root.innerHTML = \`
+
+
+
+ Hello
+
+
+ ! I can run in React, Vue, Solid, or Liquid!
+