Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import * as path from 'path';
import { nls } from '../i18n';
import { CreateUtil } from '../utils';
import {
isAllowedLightningEmbeddingSrcUrl,
LIGHTNING_EMBEDDING_SANDBOX_TOKENS,
} from '../utils/lightningEmbedding';
import { LightningEmbeddingOptions } from '../utils/types';
isAllowedUIEmbeddingSrcUrl,
UI_EMBEDDING_SANDBOX_TOKENS,
} from '../utils/uiEmbedding';
import { UIEmbeddingOptions } from '../utils/types';
import { BaseGenerator } from './baseGenerator';

const VALID_SANDBOX_TOKENS: ReadonlySet<string> = new Set(
LIGHTNING_EMBEDDING_SANDBOX_TOKENS
UI_EMBEDDING_SANDBOX_TOKENS
);

export default class LightningEmbeddingGenerator extends BaseGenerator<LightningEmbeddingOptions> {
export default class UIEmbeddingGenerator extends BaseGenerator<UIEmbeddingOptions> {
public validateOptions(): void {
CreateUtil.checkInputs(this.options.componentname);

Expand All @@ -29,27 +29,27 @@ export default class LightningEmbeddingGenerator extends BaseGenerator<Lightning
throw new Error(nls.localize('MissingLWCDir'));
}

if (!isAllowedLightningEmbeddingSrcUrl(this.options.src)) {
throw new Error(nls.localize('InvalidLightningEmbeddingSrcUrl'));
if (!isAllowedUIEmbeddingSrcUrl(this.options.src)) {
throw new Error(nls.localize('InvalidUIEmbeddingSrcUrl'));
}

if (this.options.src.includes("'")) {
throw new Error(nls.localize('InvalidLightningEmbeddingSrcChar'));
throw new Error(nls.localize('InvalidUIEmbeddingSrcChar'));
}

if (!this.options.shellTitle || !this.options.shellTitle.trim()) {
throw new Error(nls.localize('MissingLightningEmbeddingShellTitle'));
throw new Error(nls.localize('MissingUIEmbeddingShellTitle'));
}

if (this.options.shellTitle.includes('"')) {
throw new Error(nls.localize('InvalidLightningEmbeddingShellTitleChar'));
throw new Error(nls.localize('InvalidUIEmbeddingShellTitleChar'));
}

const tokens = this.options.sandbox.split(/\s+/).filter(Boolean);
const invalid = tokens.filter((t) => !VALID_SANDBOX_TOKENS.has(t));
if (invalid.length) {
throw new Error(
nls.localize('InvalidLightningEmbeddingSandboxToken', [
nls.localize('InvalidUIEmbeddingSandboxToken', [
invalid.join(', '),
[...VALID_SANDBOX_TOKENS].join(', '),
])
Expand All @@ -67,7 +67,7 @@ export default class LightningEmbeddingGenerator extends BaseGenerator<Lightning
.substring(0, 1)
.toLowerCase()}${componentname.substring(1)}`;

this.sourceRootWithPartialPath(path.join('lightningembedding', 'default'));
this.sourceRootWithPartialPath(path.join('uiembedding', 'default'));

await this.render(
this.templatePath('default.html'),
Expand Down
14 changes: 7 additions & 7 deletions src/i18n/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ export const messages = {
InvalidSObjectType:
'Invalid sobjecttype "%s". It must be a valid SObject API name: start with a letter, contain only letters, numbers, and underscores, and not end with an underscore.',

InvalidLightningEmbeddingSrcUrl:
InvalidUIEmbeddingSrcUrl:
'The --src flag must be an absolute https URL (e.g., https://app.example.com). Plain http is only allowed for localhost or 127.0.0.1.',
InvalidLightningEmbeddingSrcChar:
InvalidUIEmbeddingSrcChar:
'The --src flag must not contain a single-quote character; it would break the generated JavaScript string literal.',
InvalidLightningEmbeddingSandboxToken:
InvalidUIEmbeddingSandboxToken:
'Invalid sandbox tokens: %s. Valid tokens are: %s.',
MissingLightningEmbeddingShellTitle:
MissingUIEmbeddingShellTitle:
'The --shell-title flag is required and must be a non-empty string used as the iframe accessible name.',
InvalidLightningEmbeddingShellTitleChar:
InvalidUIEmbeddingShellTitleChar:
'The --shell-title flag must not contain a double-quote character; it would break the generated HTML attribute.',
LightningEmbeddingBundle:
'A Lightning Web Component that wraps the lightning-embedding base component.',
UIEmbeddingBundle:
'A Lightning Web Component that wraps the <lightning-ui-embedding> base component.',
};
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ import { TemplateService } from './service/templateService';
export { TemplateService };
export * from './utils/types';
export * from './utils/createUtil';
export * from './utils/lightningEmbedding';
export * from './utils/uiEmbedding';
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<lightning-embedding
src={widgetUrl}
<lightning-ui-embedding
src={embeddingUrl}
sandbox="<%= sandbox %>"
shell-title="<%= shellTitle %>">
</lightning-embedding>
</lightning-ui-embedding>
</template>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LightningElement } from 'lwc';

export default class <%= pascalCaseComponentName %> extends LightningElement {
widgetUrl = '<%= src %>';
embeddingUrl = '<%= src %>';
}
10 changes: 5 additions & 5 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ApexTriggerGenerator from '../generators/apexTriggerGenerator';
import FlexipageGenerator from '../generators/flexipageGenerator';
import LightningAppGenerator from '../generators/lightningAppGenerator';
import LightningComponentGenerator from '../generators/lightningComponentGenerator';
import LightningEmbeddingGenerator from '../generators/lightningEmbeddingGenerator';
import UIEmbeddingGenerator from '../generators/uiEmbeddingGenerator';
import LightningEventGenerator from '../generators/lightningEventGenerator';
import LightningInterfaceGenerator from '../generators/lightningInterfaceGenerator';
import LightningTestGenerator from '../generators/lightningTestGenerator';
Expand Down Expand Up @@ -52,7 +52,7 @@ export type Generators =
| typeof LightningTestGenerator
| typeof LightningInterfaceGenerator
| typeof DigitalExperienceSiteGenerator
| typeof LightningEmbeddingGenerator
| typeof UIEmbeddingGenerator
| typeof ProjectGenerator
| typeof StaticResourceGenerator
| typeof VisualforceComponentGenerator
Expand All @@ -77,7 +77,7 @@ export enum TemplateType {
LightningInterface,
LightningTest,
DigitalExperienceSite,
LightningEmbedding,
UIEmbedding,
Project,
VisualforceComponent,
VisualforcePage,
Expand All @@ -96,7 +96,7 @@ export const generators = new Map<TemplateType, GeneratorClass<any>>([
[TemplateType.LightningInterface, LightningInterfaceGenerator],
[TemplateType.LightningTest, LightningTestGenerator],
[TemplateType.DigitalExperienceSite, DigitalExperienceSiteGenerator],
[TemplateType.LightningEmbedding, LightningEmbeddingGenerator],
[TemplateType.UIEmbedding, UIEmbeddingGenerator],
[TemplateType.Project, ProjectGenerator],
[TemplateType.StaticResource, StaticResourceGenerator],
[TemplateType.VisualforceComponent, VisualforceComponentGenerator],
Expand Down Expand Up @@ -196,7 +196,7 @@ export interface LightningTestOptions extends TemplateOptions {
internal: boolean;
}

export interface LightningEmbeddingOptions extends TemplateOptions {
export interface UIEmbeddingOptions extends TemplateOptions {
componentname: string;
src: string;
sandbox: string;
Expand Down
12 changes: 6 additions & 6 deletions src/utils/lightningEmbedding.ts → src/utils/uiEmbedding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
*/

/**
* W3C-defined iframe sandbox tokens accepted by the lightning-embedding wrapper template.
* W3C-defined iframe sandbox tokens accepted by the UI embedding wrapper template.
* Exposed so CLI plugins can derive their flag `options` list from a single source of truth.
*/
export const LIGHTNING_EMBEDDING_SANDBOX_TOKENS = [
export const UI_EMBEDDING_SANDBOX_TOKENS = [
'allow-forms',
'allow-modals',
'allow-orientation-lock',
Expand All @@ -24,15 +24,15 @@ export const LIGHTNING_EMBEDDING_SANDBOX_TOKENS = [
'allow-top-navigation-by-user-activation',
] as const;

export type LightningEmbeddingSandboxToken =
(typeof LIGHTNING_EMBEDDING_SANDBOX_TOKENS)[number];
export type UIEmbeddingSandboxToken =
(typeof UI_EMBEDDING_SANDBOX_TOKENS)[number];

/**
* Returns true if `src` is an absolute URL acceptable as the iframe source on the
* lightning-embedding wrapper. https is accepted everywhere; plain http is permitted
* UI embedding wrapper. https is accepted everywhere; plain http is permitted
* only for localhost / 127.0.0.1 to support local development servers.
*/
export function isAllowedLightningEmbeddingSrcUrl(src: string): boolean {
export function isAllowedUIEmbeddingSrcUrl(src: string): boolean {
let parsed: URL;
try {
parsed = new URL(src);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as chai from 'chai';
import * as fs from 'fs';
import * as path from 'path';
import { TemplateService, TemplateType } from '../../src';
import LightningEmbeddingGenerator from '../../src/generators/lightningEmbeddingGenerator';
import UIEmbeddingGenerator from '../../src/generators/uiEmbeddingGenerator';
import { getDefaultApiVersion } from '../../src/generators/baseGenerator';

chai.config.truncateThreshold = 100000;
Expand All @@ -32,7 +32,7 @@ function assertFileContent(file: string, needle: string | RegExp) {
.be.true;
}

describe('LightningEmbeddingGenerator', () => {
describe('UIEmbeddingGenerator', () => {
const apiVersion = getDefaultApiVersion();
const lwcOutputDir = path.join('testsoutput', 'lwc');
const nonLwcOutputDir = path.join('testsoutput', 'embedding');
Expand All @@ -46,7 +46,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should throw when componentname is empty', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: '',
src: 'https://app.example.com',
sandbox: 'allow-scripts',
Expand All @@ -60,7 +60,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should throw when not internal and outputdir is missing lwc parent', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts',
Expand All @@ -74,7 +74,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should accept http src on localhost', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'http://localhost:3000',
sandbox: 'allow-scripts',
Expand All @@ -88,7 +88,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should accept http src on 127.0.0.1', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'http://127.0.0.1:8080',
sandbox: 'allow-scripts',
Expand All @@ -102,7 +102,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject http src on non-localhost host', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'http://app.example.com',
sandbox: 'allow-scripts',
Expand All @@ -116,7 +116,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject non-URL src', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'not a url',
sandbox: 'allow-scripts',
Expand All @@ -130,7 +130,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject non-http(s) protocols', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'ftp://example.com',
sandbox: 'allow-scripts',
Expand All @@ -144,7 +144,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject empty shellTitle', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts',
Expand All @@ -158,7 +158,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject invalid sandbox tokens', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts allow-everything',
Expand All @@ -172,7 +172,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should accept multiple valid sandbox tokens', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts allow-forms allow-same-origin',
Expand All @@ -186,7 +186,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject a single-quote character in src (would break the generated JS string)', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: "https://app.example.com/path?q='foo",
sandbox: 'allow-scripts',
Expand All @@ -200,7 +200,7 @@ describe('LightningEmbeddingGenerator', () => {
it('should reject a double-quote character in shellTitle (would break the generated HTML attribute)', () => {
expect(
() =>
new LightningEmbeddingGenerator({
new UIEmbeddingGenerator({
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts',
Expand All @@ -215,18 +215,15 @@ describe('LightningEmbeddingGenerator', () => {
describe('generate', () => {
it('should create the LWC bundle (internal — no meta xml)', async () => {
const templateService = TemplateService.getInstance(process.cwd());
const result = await templateService.create(
TemplateType.LightningEmbedding,
{
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts allow-forms',
shellTitle: 'Demo Shell',
outputdir: lwcOutputDir,
apiversion: apiVersion,
internal: true,
}
);
const result = await templateService.create(TemplateType.UIEmbedding, {
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts allow-forms',
shellTitle: 'Demo Shell',
outputdir: lwcOutputDir,
apiversion: apiVersion,
internal: true,
});

const base = path.join(lwcOutputDir, 'embeddingDemo');
assertFileExists(path.join(base, 'embeddingDemo.html'));
Expand All @@ -250,7 +247,7 @@ describe('LightningEmbeddingGenerator', () => {

it('should generate meta xml when not internal', async () => {
const templateService = TemplateService.getInstance(process.cwd());
await templateService.create(TemplateType.LightningEmbedding, {
await templateService.create(TemplateType.UIEmbedding, {
componentname: 'embeddingDemo',
src: 'https://app.example.com',
sandbox: 'allow-scripts',
Expand Down