From e6ed5e74cec1f5f054beef0a9958c5f7c634b0d0 Mon Sep 17 00:00:00 2001 From: Jaya Krishna Namburu Date: Tue, 19 Oct 2021 14:13:01 +0530 Subject: [PATCH] feat(proj-html): Duplicating global html tags for each page for html project generators (#621) * feat(proj-html): duplicating global html tags for each page for html project generators * Add missing dependency for the html project generator --- .../__tests__/end2end/index.ts | 25 +++++++++ .../package.json | 4 +- .../src/index.ts | 22 +++----- .../src/utils.ts | 54 +++++++++++++++++++ yarn.lock | 10 +++- 5 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 packages/teleport-project-generator-html/src/utils.ts diff --git a/packages/teleport-project-generator-html/__tests__/end2end/index.ts b/packages/teleport-project-generator-html/__tests__/end2end/index.ts index 8f55eb8dc..31caecbe7 100644 --- a/packages/teleport-project-generator-html/__tests__/end2end/index.ts +++ b/packages/teleport-project-generator-html/__tests__/end2end/index.ts @@ -2,17 +2,42 @@ import uidlSample from '../../../../examples/uidl-samples/simple-html.json' import invalidUidlSample from '../../../../examples/test-samples/project-invalid-sample.json' import { createHTMLProjectGenerator } from '../../src' import HTMLTemplate from '../../src/project-template' +import { FileType } from '@teleporthq/teleport-types' describe('Html Project Generator', () => { const generator = createHTMLProjectGenerator() it('runs without crasing', async () => { const { name, files, subFolders } = await generator.generateProject(uidlSample, HTMLTemplate) + const pages = subFolders[0]?.subFolders.find((folder) => folder.name === 'pages') + const aboutPage = pages.files.find( + (page) => page.name === 'about' && page.fileType === FileType.HTML + ) expect(name).toBe('teleport-project-html') expect(files.length).toBe(1) expect(files[0].content).toContain('start') + expect(subFolders.length).toBe(1) + expect(aboutPage.content).toContain('head') + expect(aboutPage.content).toContain('html') + }) + + it('run withut crashing and appends entry things into single index.html', async () => { + const singularGenerator = createHTMLProjectGenerator({ individualEntyFile: false }) + const { name, files, subFolders } = await singularGenerator.generateProject( + uidlSample, + HTMLTemplate + ) + const pages = subFolders[0]?.subFolders.find((folder) => folder.name === 'pages') + const aboutPage = pages.files.find( + (page) => page.name === 'about' && page.fileType === FileType.HTML + ) + + expect(name).toBe('teleport-project-html') + expect(files.length).toBe(1) expect(subFolders.length).toBe(2) + expect(aboutPage.content).not.toContain('head') + expect(aboutPage.content).not.toContain('html') }) it('throws error when invalid UIDL sample is used', async () => { diff --git a/packages/teleport-project-generator-html/package.json b/packages/teleport-project-generator-html/package.json index 4ffa5ef42..42b3b41ab 100644 --- a/packages/teleport-project-generator-html/package.json +++ b/packages/teleport-project-generator-html/package.json @@ -24,9 +24,11 @@ "build": "tsc -p tsconfig.json && tsc -p tsconfig.json --module commonjs --outDir dist/cjs" }, "dependencies": { + "node-html-parser":"^5.0.0", "@teleporthq/teleport-component-generator": "^0.19.1", "@teleporthq/teleport-component-generator-html": "^0.19.1", "@teleporthq/teleport-plugin-css": "^0.19.1", - "@teleporthq/teleport-project-generator": "^0.19.1" + "@teleporthq/teleport-project-generator": "^0.19.1", + "@teleporthq/teleport-postprocessor-prettier-html": "^0.19.1" } } diff --git a/packages/teleport-project-generator-html/src/index.ts b/packages/teleport-project-generator-html/src/index.ts index 13898376e..2ce87f81a 100644 --- a/packages/teleport-project-generator-html/src/index.ts +++ b/packages/teleport-project-generator-html/src/index.ts @@ -4,8 +4,11 @@ import { createComponentGenerator } from '@teleporthq/teleport-component-generat import { createStyleSheetPlugin } from '@teleporthq/teleport-plugin-css' import prettierHTML from '@teleporthq/teleport-postprocessor-prettier-html' import HTMLTemplate from './project-template' +import { pluginHtmlGenerators } from './utils' + +const createHTMLProjectGenerator = (config?: { individualEntyFile: boolean }) => { + const { individualEntyFile } = config || { individualEntyFile: true } -const createHTMLProjectGenerator = () => { const generator = createProjectGenerator({ id: 'teleport-project-html', components: { @@ -31,22 +34,13 @@ const createHTMLProjectGenerator = () => { postprocessors: [prettierHTML], fileName: 'index', path: [''], - options: { - appRootOverride: `
Entry file of the project
`, - customTags: [ - { - tagName: 'link', - targetTag: 'head', - attributes: [ - { attributeKey: 'href', attributeValue: './src/style.css' }, - { attributeKey: 'rel', attributeValue: 'stylesheet' }, - ], - }, - ], - }, }, }) + if (individualEntyFile) { + generator.addPlugin(pluginHtmlGenerators) + } + return generator } diff --git a/packages/teleport-project-generator-html/src/utils.ts b/packages/teleport-project-generator-html/src/utils.ts new file mode 100644 index 000000000..10f52ab4b --- /dev/null +++ b/packages/teleport-project-generator-html/src/utils.ts @@ -0,0 +1,54 @@ +import { + FileType, + GeneratedFile, + ProjectPlugin, + ProjectPluginStructure, +} from '@teleporthq/teleport-types' +import { parse, HTMLElement } from 'node-html-parser' +import prettierHTML from '@teleporthq/teleport-postprocessor-prettier-html' + +class ProjectPluginHTMLGeneratprs implements ProjectPlugin { + async runBefore(structure: ProjectPluginStructure) { + return structure + } + + async runAfter(structure: ProjectPluginStructure) { + const { files, uidl } = structure + const entryFile = files.get('entry') + if (!entryFile) { + return structure + } + + const result = parse(entryFile.files[0].content) + const body = result.querySelector('body') + body.childNodes = [] + + if (Object.values(uidl.root?.styleSetDefinitions || {}).length > 0) { + const head = result.querySelector('head') + head.appendChild(new HTMLElement('link', {}, 'rel="stylesheet" href="../style.css"', result)) + } + + files.forEach((fileId, key) => { + const { path } = fileId + if (path.includes('pages')) { + const newFiles: GeneratedFile[] = fileId.files.map((file) => { + if (file.fileType === FileType.HTML) { + body.innerHTML = file.content + const prettyFile = prettierHTML({ + [FileType.HTML]: result.toString(), + }) + + return { name: file.name, content: prettyFile[FileType.HTML], fileType: FileType.HTML } + } + return file + }) + files.set(key, { path, files: newFiles }) + } + }) + + files.delete('entry') + return structure + } +} + +export const pluginHtmlGenerators = Object.freeze(new ProjectPluginHTMLGeneratprs()) diff --git a/yarn.lock b/yarn.lock index 14c2e18f3..6e56d2f10 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5021,7 +5021,7 @@ hast-util-whitespace@^1.0.3: resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== -he@^1.2.0: +he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -7473,6 +7473,14 @@ node-gyp@^5.0.2: tar "^4.4.12" which "^1.3.1" +node-html-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-5.0.0.tgz#a398d6d27459346c517dc1b1e3dd779e12d685c3" + integrity sha512-TTcYevvxqIyRfc1Y/3O6EwzmPFmN9fykfdP3DewtDaVMzft4HFfs21ogw5LGDYhieIq8QBFG+PSBNd5x3n0WZQ== + dependencies: + css-select "^4.1.3" + he "1.2.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"