Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handlebars app #16

Merged
merged 2 commits into from
Aug 31, 2023
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ Contributions to the `deco-cx/apps` repository are highly encouraged! We maintai

We adhere to **semantic versioning**, and all apps within this repository are versioned collectively using git tags. To release a new version, simply fork the repository, open a pull request, and once approved, request any maintainer to run `deno task release`. There are no strict rules about release frequency, so you can release updates as soon as your changes are merged into the main branch.

### Developing a new app

Just run:

```sh
deno task new `APP_NAME` && deno task start
```

The app folder and the `deco.ts` will be changed in order to support your newly created app.

## Transition from deco-sites/std to deco-cx/apps

This repository isn't a deco site as it used to be in `deco-sites/std`. In the past, we used `deco-sites/std` as a central hub for various platform integrations. Now, we've modularized these integrations into smaller, installable, and composable apps. These apps now reside in the `deco-cx/apps` repository. Additionally, the `/compat` folder contains two apps, `$live` and `deco-sites/std`, which serve as drop-in replacements for the older apps that contained all blocks together. As users progressively adopt the new apps, they can take full advantage of app extensibility and enhance their websites' capabilities.
Expand All @@ -46,6 +56,10 @@ For more information, check out our documentation at [https://deco.cx/docs](http
| deco-sites/std | An app for compatibility with deco-sites/std app, contains various blocks merged from e-commerce apps. | [manifest](/compat/std/manifest.gen.ts) |
| decohub | The best place to find an app for your business case, here is where apps published by any developer in the deco ecosystem will live. | [manifest](/decohub/manifest.gen.ts) |

#### Adding a new app to Deco Hub

In order to make your app available to be installable in any deco site, just import/export your app inside decohub/apps folder.

## Thanks to all contributors

<a href="https://github.com/deco-cx/apps/graphs/contributors">
Expand Down
1 change: 1 addition & 0 deletions deco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const compatibilityApps = [{

const config = {
apps: [
app("handlebars"),
app("vtex"),
app("vnda"),
app("shopify"),
Expand Down
1 change: 1 addition & 0 deletions decohub/apps/handlebars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "../../handlebars/mod.ts";
3 changes: 2 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"link": "deno eval 'import \"$live/scripts/apps/link.ts\"'",
"unlink": "deno eval 'import \"$live/scripts/apps/unlink.ts\"'",
"serve": "deno eval 'import \"$live/scripts/apps/serve.ts\"'",
"update": "deno eval 'import \"$live/scripts/update.ts\"'"
"update": "deno eval 'import \"$live/scripts/update.ts\"'",
"new": "deno run -A ./scripts/new.ts"
},
"githooks": {
"pre-commit": "check"
Expand Down
12 changes: 12 additions & 0 deletions handlebars/manifest.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// DO NOT EDIT. This file is generated by deco.
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.

const manifest = {
"name": "handlebars",
"baseUrl": import.meta.url,
};

export type Manifest = typeof manifest;

export default manifest;
82 changes: 82 additions & 0 deletions handlebars/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { App, AppContext as AC } from "$live/mod.ts";
import HTMLRenderer from "deco-sites/std/components/HTMLRenderer.tsx";
import { SourceMap } from "deco/blocks/app.ts";
import { SectionModule } from "deco/blocks/section.ts";
import { JSONSchema7 } from "deco/deps.ts";
import { BlockModuleRef } from "deco/engine/block.ts";
import Handlebars from "https://esm.sh/v131/handlebars@4.7.8";
import manifest, { Manifest } from "./manifest.gen.ts";

const h = Handlebars as unknown as typeof Handlebars["export="];
export interface HandlebarSection {
name: string;
/**
* @format html
*/
content: string;
}

const getHBVars = (content: string) => {
const ast = h.parse(content);
const keys: Record<string, boolean> = {};

for (const i in ast.body) {
if (ast.body[i].type === "MustacheStatement") {
keys[
(ast.body[i] as unknown as { path: { original: string } }).path.original
] = true;
}
}
return Object.keys(keys);
};
export interface State {
sections: HandlebarSection[];
}
/**
* @title Build your own Sections
*/
export default function App(
state: State,
): App<Manifest, State> {
const [sections, sourceMap] = (state.sections ?? []).reduce(
([currentSections, currentSourceMap], sec) => {
const sectionName = `handlebars/sections/${sec.name}.tsx`;
const compiled = h.compile(sec.content);
const properties: Record<string, JSONSchema7> = {};
const vars = getHBVars(sec.content);
for (const key of vars) {
properties[key] = {
type: "string",
};
}
return [{
...currentSections,
[sectionName]: {
default: (props) => {
return HTMLRenderer({ html: compiled(props) });
},
} as SectionModule,
}, {
...currentSourceMap,
[sectionName]: () => {
return Promise.resolve({
functionRef: sectionName,
inputSchema: {
file: import.meta.url,
name: crypto.randomUUID(),
type: "inline",
value: {
type: "object",
properties,
},
},
} as BlockModuleRef);
},
}];
},
[{}, {}] as [Record<string, SectionModule>, SourceMap],
);
return { manifest: { ...manifest, sections } as Manifest, state, sourceMap };
}

export type AppContext = AC<ReturnType<typeof App>>;
4 changes: 2 additions & 2 deletions import_map.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"imports": {
"$live/": "https://denopkg.com/deco-cx/deco@1.31.3/",
"$live/": "https://denopkg.com/deco-cx/deco@1.32.0/",
"$fresh/": "https://denopkg.com/denoland/fresh@1.4.2/",
"preact": "https://esm.sh/preact@10.15.1",
"preact/": "https://esm.sh/preact@10.15.1/",
Expand All @@ -10,6 +10,6 @@
"std/": "https://deno.land/std@0.190.0/",
"partytown/": "https://deno.land/x/partytown@0.3.4/",
"deco-sites/std/": "https://denopkg.com/deco-sites/std@1.20.15/",
"deco/": "https://denopkg.com/deco-cx/deco@1.31.3/"
"deco/": "https://denopkg.com/deco-cx/deco@1.32.0/"
}
}
32 changes: 32 additions & 0 deletions scripts/new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { join } from "std/path/mod.ts";

const appName = Deno.args[0];
const decoTsPath = join(Deno.cwd(), "deco.ts");
const decoTs = await Deno.readTextFile(decoTsPath);

await Deno.mkdir(join(Deno.cwd(), appName));
await Deno.writeTextFile(
decoTsPath,
decoTs.replace(` apps: [`, ` apps: [\n app("${appName}"),`),
);

await Deno.writeTextFile(
join(Deno.cwd(), appName, "mod.ts"),
`
import type { App, AppContext as AC } from "$live/mod.ts";
import manifest, { Manifest } from "./manifest.gen.ts";

// deno-lint-ignore ban-types
export type State = {};
/**
* @title ${appName}
*/
export default function App(
state: State,
): App<Manifest, State> {
return { manifest, state };
}

export type AppContext = AC<ReturnType<typeof App>>;
`,
);