Skip to content

Commit

Permalink
Handlebars app (#16)
Browse files Browse the repository at this point in the history
* Handlebars app

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>

* Add handlebars app

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>

---------

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>
  • Loading branch information
mcandeia authored Aug 31, 2023
1 parent 50bbf4b commit 919c557
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 3 deletions.
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>>;
`,
);

0 comments on commit 919c557

Please sign in to comment.