Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:

- name: Install Dependencies
run: bun install

- name: Check Types
run: bun run check

- name: Build
run: bun run --bun build
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ You can now run these npm scripts

## Demo

This repo aims to demonstrate a couple of Greenwood's features ([API Routes](https://www.greenwoodjs.io/docs/api-routes/) and [SSR pages](https://www.greenwoodjs.io/docs/server-rendering/#routes)) focused on using Web Components (WCC) and Web Standards to deliver the content for the demo.
This repo aims to demonstrate a couple of Greenwood's features ([API Routes](https://www.greenwoodjs.io/docs/api-routes/) and [SSR pages](https://www.greenwoodjs.io/docs/server-rendering/#routes)) focused on using Web Components (Lit) and Web Standards to deliver the content for the demo.

> _Adapted from these two demo repos:_
> - https://github.com/thescientist13/greenwood-lit-ssr
> - https://github.com/ProjectEvergreen/greenwood-demo-adapter-vercel

### API Routes

Expand Down
36 changes: 36 additions & 0 deletions bun-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// TODO: adapt full node loaders / plugins compat - https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/loader.js
// TODO: https://github.com/thescientist13/greenwood-lit-ssr/pull/31/files#diff-331071217a3ab2aa8b4d355963f7f43aec384b080331f2ef67c675adb7d7cead
// 1) import the greenwood plugin and lifecycle helpers
import { greenwoodPluginTypeScript } from "@greenwood/cli/src/plugins/resource/plugin-typescript.js";
import { readAndMergeConfig } from "@greenwood/cli/src/lifecycles/config.js";
import { initContext } from "@greenwood/cli/src/lifecycles/context.js";

// 2) initialize Greenwood lifecycles
const config = await readAndMergeConfig();
const context = await initContext({ config });
const compilation = { context, config };

// 3) initialize the plugin
const typeScriptPlugin = greenwoodPluginTypeScript[0].provider(compilation);

import { plugin } from "bun";

/** @type {import('bun').PluginBuilder} */
plugin({
name: "custom greenwood loader",
setup(build) {
const filter = /\.(ts)$/

build.onLoad({ filter }, async (args) => {
console.log('onLoad', { args });
const response = await typeScriptPlugin.serve(new URL(`file://${args.path}`));
const contents = await response.text();

console.log({ contents });
return {
contents,
loader: "js",
};
});
},
});
77 changes: 74 additions & 3 deletions bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
preload = ["./bun-loader.js"]
11 changes: 11 additions & 0 deletions greenwood.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { greenwoodPluginImportRaw } from "@greenwood/plugin-import-raw";
import { greenwoodPluginRendererLit } from "@greenwood/plugin-renderer-lit";
import type { Config } from "@greenwood/cli";

export default {
useTsc: true,
plugins: [
greenwoodPluginImportRaw(),
greenwoodPluginRendererLit(),
]
} as Config;
16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"keywords": [
"Greenwood",
"Bun",
"WCC",
"Lit",
"Web Components",
"Serverless",
"Edge",
Expand All @@ -23,9 +23,19 @@
"dev": "greenwood develop",
"build": "greenwood build",
"serve": "greenwood build && greenwood serve",
"start": "bun serve"
"start": "bun serve",
"check": "tsc"
},
"dependencies": {
"lit": "^3.3.1"
},
"devDependencies": {
"@greenwood/cli": "~0.33.0"
"@greenwood/cli": "0.33.0",
"@greenwood/plugin-import-raw": "0.33.0",
"@greenwood/plugin-renderer-lit": "0.33.0",
"typescript": "^5.9.2"
},
"patchedDependencies": {
"@greenwood/cli@0.33.0": "patches/@greenwood%2Fcli@0.33.0.patch"
}
}
48 changes: 48 additions & 0 deletions patches/@greenwood%2Fcli@0.33.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
diff --git a/src/plugins/resource/plugin-active-content.js b/src/plugins/resource/plugin-active-content.js
index d0edaf1f75184b4ff602f48a838bfb7380f06397..4a573e34c77460c7ab208b5b63d5f646c9a7e063 100644
--- a/src/plugins/resource/plugin-active-content.js
+++ b/src/plugins/resource/plugin-active-content.js
@@ -138,7 +138,7 @@ class ContentAsDataResource {
async shouldOptimize(url, response) {
const { activeContent } = this.compilation.config;

- return response.headers.get("Content-Type").indexOf(this.contentType[0]) >= 0 && activeContent;
+ return response.headers.get("Content-Type")?.indexOf(this.contentType[0]) >= 0 && activeContent;
}

async optimize(url, response) {
diff --git a/src/plugins/resource/plugin-node-modules.js b/src/plugins/resource/plugin-node-modules.js
index 9c983a2f3f4bb043ee9aa3f6e090509444156edd..a4bd37de39c6894c32f4cab106abf4a1c7803e9d 100644
--- a/src/plugins/resource/plugin-node-modules.js
+++ b/src/plugins/resource/plugin-node-modules.js
@@ -41,14 +41,15 @@ class NodeModulesResource {
}

async shouldServe(url) {
- const { href, protocol } = url;
+ const { href, protocol, pathname } = url;

- return protocol === "file:" && (await checkResourceExists(new URL(href)));
+ return protocol === "file:" && pathname.indexOf("/node_modules/") >= 0 && (await checkResourceExists(new URL(href)));
}

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

+ // most likely a JavaScript file, but perhaps we should further refine based on extension?
return new Response(body, {
headers: new Headers({
"Content-Type": this.contentType,
diff --git a/src/plugins/resource/plugin-standard-html.js b/src/plugins/resource/plugin-standard-html.js
index f1d1153df9170f77cf8eef22b987e7299b906eb5..30ab824587539ec32a680be2ce0562c48241b019 100644
--- a/src/plugins/resource/plugin-standard-html.js
+++ b/src/plugins/resource/plugin-standard-html.js
@@ -13,7 +13,7 @@ import { parse } from "node-html-parser";
class StandardHtmlResource {
constructor(compilation) {
this.compilation = compilation;
- this.extensions = [".html"];
+ this.extensions = ["html"];
this.contentType = "text/html";
}

75 changes: 0 additions & 75 deletions src/components/card.js

This file was deleted.

44 changes: 44 additions & 0 deletions src/components/card/card.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
div {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
border: 1px solid #818181;
width: fit-content;
border-radius: 10px;
padding: 2rem 1rem;
height: 680px;
justify-content: space-between;
background-color: #fff;
overflow-x: hidden;
}

button {
background: var(--color-accent);
color: var(--color-white);
padding: 1rem 2rem;
border: 0;
font-size: 1rem;
border-radius: 5px;
cursor: pointer;
}

img {
max-width: 500px;
min-width: 500px;
width: 100%;
}

h3 {
font-size: 1.85rem;
}

@media(max-width: 768px) {
img {
max-width: 300px;
min-width: 300px;
}
div {
height: 500px;
}
}
48 changes: 48 additions & 0 deletions src/components/card/card.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { LitElement, html, unsafeCSS } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import styles from './card.css?type=raw';

@customElement('app-card')
export class Card extends LitElement {

@property()
accessor title: string;

@property()
accessor thumbnail: string;

static styles = [unsafeCSS(styles)];

constructor() {
super();

this.title;
this.thumbnail;
}

selectItem() {
const itemSelectedEvent = new CustomEvent("update-modal", {
detail: {
content: `You selected the "${this.title}"`,
},
});

window.dispatchEvent(itemSelectedEvent);
}

render() {
const { title, thumbnail } = this;

if(!title && !thumbnail) {
return;
}

return html`
<div>
<h3>${title}</h3>
<img src="${thumbnail}" alt="${title}" loading="lazy" width="100%">
<button @click="${this.selectItem}">View Item Details</button>
</div>
`;
}
}
Loading
Loading