Skip to content

Commit

Permalink
enhancement/issue 955 support multiple custom page formats at once (#…
Browse files Browse the repository at this point in the history
…1265)

* support multiple custom page formats at once

* add test cases for custom API routes page format
  • Loading branch information
thescientist13 committed Nov 2, 2024
1 parent 24fa5f5 commit 1205b86
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 22 deletions.
20 changes: 13 additions & 7 deletions packages/cli/src/lifecycles/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,28 @@ const generateGraph = async (compilation) => {
pages = nextPages.pages;
apiRoutes = nextPages.apiRoutes;
} else {
const req = new Request(filenameUrl, { headers: { 'Accept': 'text/html' } });
const extension = `.${filenameUrl.pathname.split('.').pop()}`;
const isCustom = customPageFormatPlugins[0] && customPageFormatPlugins[0].shouldServe && await customPageFormatPlugins[0].shouldServe(filenameUrl, req)
? customPageFormatPlugins[0].servePage
: null;
const relativePagePath = filenameUrl.pathname.replace(pagesDir.pathname, '/');
const relativeWorkspacePath = directory.pathname.replace(projectDirectory.pathname, '');
const isApiRoute = relativePagePath.startsWith('/api');
const req = isApiRoute
? new Request(filenameUrl)
: new Request(filenameUrl, { headers: { 'Accept': 'text/html' } });
let isCustom = null;

for (const plugin of customPageFormatPlugins) {
if (plugin.shouldServe && await plugin.shouldServe(filenameUrl, req)) {
isCustom = plugin.servePage;
break;
}
}

const isStatic = isCustom === 'static' || extension === '.md' || extension === '.html';
const isDynamic = isCustom === 'dynamic' || extension === '.js';
const isApiRoute = relativePagePath.startsWith('/api');
const isPage = isStatic || isDynamic;

if (isApiRoute) {
const req = new Request(filenameUrl);
const extension = filenameUrl.pathname.split('.').pop();
const isCustom = customPageFormatPlugins[0] && customPageFormatPlugins[0].shouldServe && await customPageFormatPlugins[0].shouldServe(filenameUrl, req);

if (extension !== 'js' && !isCustom) {
console.warn(`${filenameUrl} is not a supported API file extension, skipping...`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@ class FooResource {
this.servePage = options.servePage;

this.extensions = ['foo'];
this.contentType = 'text/html';
}

async shouldServe(url) {
return url.pathname.split('.').pop() === this.extensions[0] && this.servePage;
}

async serve(url) {
const body = await fs.readFile(url, 'utf-8');

return new Response(body, {
headers: new Headers({
'Content-Type': this.contentType
})
});
}
}

class BarResource {
constructor(compilation, options) {
this.compilation = compilation;
this.options = options;
this.servePage = options.servePage;

this.extensions = ['bar'];
this.contentType = 'text/javascript';
}

Expand All @@ -17,7 +42,7 @@ class FooResource {
async serve(url) {
let body = await fs.readFile(url, 'utf-8');

body = body.replace(/interface (.*){(.*)}/s, '');
body = body.replace(/interface (.*){(.*)}/, '');

return new Response(body, {
headers: new Headers({
Expand All @@ -35,10 +60,21 @@ const greenwoodPluginFooResource = (options = {}) => {
}];
};

const greenwoodPluginBarResource = (options = {}) => {
return [{
type: 'resource',
name: 'plugin-import-bar:resource',
provider: (compilation) => new BarResource(compilation, options)
}];
};

export default {
plugins: [
greenwoodPluginFooResource({
servePage: 'static'
}),
greenwoodPluginBarResource({
servePage: 'dynamic'
})
]
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*
* Use Case
* Run Greenwood with a custom resource plugin and default workspace with a custom page format.
* Run Greenwood with a custom resource plugin and default workspace with a custom page formats.
*
* User Result
* Should generate a bare bones Greenwood build with expected custom file (.foo) behavior.
* Should generate a bare bones Greenwood build with expected custom page format behaviors.
*
* User Command
* greenwood build
Expand All @@ -13,17 +13,27 @@
* // see complete implementation in the greenwood.config.js file used for this spec
* }
*
* class BarResource extends ResourceInterface {
* // see complete implementation in the greenwood.config.js file used for this spec
* }
*
* {
* plugins: [{
* type: 'resource',
* name: 'plugin-foo',
* provider: (compilation, options) => new FooResource(compilation, options)
* },{
* type: 'resource',
* name: 'plugin-bar',
* provider: (compilation, options) => new BarResource(compilation, options)
* }]
* }
*
* Custom Workspace
* src/
* pages/
* api
* greeting.bar
* about.foo
* contact.bar
* index.html
Expand All @@ -39,7 +49,7 @@ import { fileURLToPath, URL } from 'url';
const expect = chai.expect;

describe('Build Greenwood With: ', function() {
const LABEL = 'Custom FooResource Plugin and Default Workspace';
const LABEL = 'Custom Static and Dynamic Page Loaders';
const cliPath = path.join(process.cwd(), 'packages/cli/src/index.js');
const outputPath = fileURLToPath(new URL('.', import.meta.url));
let runner;
Expand All @@ -48,7 +58,7 @@ describe('Build Greenwood With: ', function() {
this.context = {
publicDir: path.join(outputPath, 'public')
};
runner = new Runner();
runner = new Runner(false, true);
});

describe(LABEL, function() {
Expand Down Expand Up @@ -89,24 +99,39 @@ describe('Build Greenwood With: ', function() {
});
});

// TODO not sure why this was disabled, but should enable this test case
xdescribe('Custom Format Dynamic Contact Page', function() {
let aboutPage;
describe('Custom Format Dynamic Contact Page (exported with prerendering)', function() {
let contactPage;

before(async function() {
aboutPage = await glob.promise(path.join(this.context.publicDir, 'contact.html'));
contactPage = await glob.promise(path.join(this.context.publicDir, 'contact/index.html'));
});

it('should have the expected JavaScript equivalent file in the output directory', function() {
expect(aboutPage).to.have.lengthOf(1);
it('should have the expected pre-rendered HTML file in the output directory', function() {
expect(contactPage).to.have.lengthOf(1);
});

it('should have expected text from from my-other-custom-file.foo in the script output file', function() {
const contents = fs.readFileSync(aboutPage[0], 'utf-8');
it('should have expected text from the output HTML file', function() {
const contents = fs.readFileSync(contactPage[0], 'utf-8');

expect(contents).to.contain('Welcome to our About page!');
expect(contents).to.contain('Welcome to our Contact page!');
});
});

describe('Custom Format Dynamic API Route', function() {
let handler;

before(async function() {
handler = (await import(new URL('./public/api/greeting.js', import.meta.url))).handler;
});

it('should have the expected output from the API route', async function() {
const response = await handler(new Request(new URL('http://localhost:8080/api/greeting')));
const data = await response.json();

expect(data.message).to.equal('Hello World!!!');
});

});
});

after(function() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface User { }

export async function handler(request) {
const params = new URLSearchParams(request.url.slice(request.url.indexOf('?')));
const name = params.has('name') ? params.get('name') : 'World';
const body = { message: `Hello ${name}!!!` };

return new Response(JSON.stringify(body), {
headers: new Headers({
'Content-Type': 'application/json'
})
});
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
interface User { }

export default class ContactPage extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<h1>Welcome to our Contact page!</h1>
`;
}
}
}

export const prerender = true;

0 comments on commit 1205b86

Please sign in to comment.