Skip to content

Commit

Permalink
[samples] add static site generator example
Browse files Browse the repository at this point in the history
  • Loading branch information
kLabz committed Oct 13, 2023
1 parent bf75d56 commit 805c5b6
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 60 deletions.
6 changes: 6 additions & 0 deletions samples/docs/build-static.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env haxe

common.hxml

-main StaticGenerator
-js bin/static-gen.js
31 changes: 1 addition & 30 deletions samples/docs/build.hxml
Original file line number Diff line number Diff line change
@@ -1,35 +1,6 @@
#!/usr/bin/env haxe

-L react-next
-L react-css
-L css-types
-L classnames
-L datetime
-L markdown
-L event-types
-L html-entities
-L tink_domspec
-L hxnodejs
-L yaml
common.hxml

-cp src
-main Main
-js bin/server.js

# -dce full
-D js-es=6
# -D analyzer-optimize
-D message.reporting=pretty

-w -WDeprecatedEnumAbstract

# Configure react-css
-D react.css.out=bin/styles.css
-D react.css.base=res/base.css
# -D react.css.sourcemap=styles.css.map

# Configure react-next
-D react-wrap-strict
-D react-check-jsxstatic-type
-D react-disable-dynamic-components

30 changes: 30 additions & 0 deletions samples/docs/common.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-L react-next
-L react-css
-L css-types
-L classnames
-L datetime
-L markdown
-L event-types
-L html-entities
-L tink_domspec
-L hxnodejs
-L yaml

-cp src

# -dce full
-D js-es=6
# -D analyzer-optimize
-D message.reporting=pretty

-w -WDeprecatedEnumAbstract

# Configure react-css
-D react.css.out=bin/styles.css
-D react.css.base=res/base.css
# -D react.css.sourcemap=styles.css.map

# Configure react-next
-D react-wrap-strict
-D react-check-jsxstatic-type
-D react-disable-dynamic-components
6 changes: 6 additions & 0 deletions samples/docs/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ setup:
server:
node bin/server.js

static:
haxe build-static.hxml
node bin/static-gen.js

serve-static:
cd bin/static && python -m http.server 8043
48 changes: 48 additions & 0 deletions samples/docs/src/AppContext.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import react.React;
import react.ReactComponent;
import react.ReactContext;
import react.ReactMacro.jsx;
import react.ReactType;

typedef AppContextData = {
var staticSite:Bool;
}

typedef AppContextProviderProps = {
var value:AppContextData;
}

typedef AppContextConsumerProps = {
var children:AppContextData->ReactFragment;
}

class AppContext {
public static var Context(get, null):ReactContext<AppContextData>;
public static var Provider(get, null):ReactTypeOf<AppContextProviderProps>;
public static var Consumer(get, null):ReactTypeOf<AppContextConsumerProps>;

static function get_Context() {ensureReady(); return Context;}
static function get_Provider() {ensureReady(); return Provider;}
static function get_Consumer() {ensureReady(); return Consumer;}

static function ensureReady() @:bypassAccessor {
if (Context == null) {
Context = React.createContext();
Context.displayName = "AppContext";
Consumer = Context.Consumer;
Provider = Context.Provider;
}
}

public static function wrap(Comp:ReactType):ReactType {
return function (props:{}) {
return jsx(
<Consumer>
{value ->
<Comp {...props} staticSite={value.staticSite} />
}
</Consumer>);
}

}
}
1 change: 0 additions & 1 deletion samples/docs/src/Main.hx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import js.node.http.IncomingMessage;
import js.node.http.ServerResponse;

import react.ReactDOMServer;
import react.Suspense;
import react.ReactMacro.jsx;

import comp.App;
Expand Down
40 changes: 40 additions & 0 deletions samples/docs/src/StaticGenerator.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import haxe.io.Path;
import js.lib.Promise;
import js.node.Fs.Fs;
import sys.FileSystem;
import sys.io.File;

import data.DocChapter;
import react.ReactDOMServer;
import react.ReactMacro.jsx;

import comp.App;

class StaticGenerator {
static inline var OUT = "bin/static";

static function main() {
FileSystem.createDirectory(OUT);
for (f in FileSystem.readDirectory(OUT)) FileSystem.deleteFile(Path.join([OUT, f]));

loadChapters().then(chapters -> {
chapters.unshift(loadReadme());
Promise.all(chapters.map(renderChapter)).then(_ -> {
File.copy('bin/styles.css', '$OUT/styles.css');
Sys.println('Generated html and css files in $OUT');
});
});
}

static function renderChapter(chapter:DocChapter):Promise<Void> {
return new Promise((resolve, reject) -> {
var slug = chapter.slug == "/" ? null : chapter.slug;
var path = '$OUT${slug ?? "/index"}.html';
var fileWriter = Fs.createWriteStream(path);
var stream = ReactDOMServer.renderToStaticNodeStream(jsx(<App chapter={slug} staticSite />));
stream.on('end', resolve);
stream.on('error', resolve);
stream.pipe(fileWriter);
});
}
}
41 changes: 14 additions & 27 deletions samples/docs/src/comp/App.hx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package comp;

import haxe.io.Path;
import js.node.Fs;
import js.lib.Promise;

import comp.layout.*;
import data.DocChapter;

private typedef PublicProps = {
var chapter:Null<String>;
@:optional var staticSite:Bool;
}

private typedef Props = {
Expand Down Expand Up @@ -60,7 +57,7 @@ class App extends ReactComponent<Props> {
.then(chapters -> (_) -> jsx(
<Comp
{...props}
home={loadChapter(Path.join(["..", "..", "README.md"]))}
home={loadReadme()}
chapters={chapters}
/>
))
Expand All @@ -71,18 +68,6 @@ class App extends ReactComponent<Props> {
};
}

static function loadChapters():Promise<Array<DocChapter>> {
return new Promise((resolve, reject) -> {
Fs.readdir("../../doc", (err, files) -> {
var chapters = (files ?? [])
.map(f -> loadChapter(Path.join(["..", "..", "doc", f])))
.filter(f -> f != null);

resolve(sortChapters(chapters));
});
});
}

override function render():ReactFragment {
return jsx(
<html>
Expand All @@ -100,19 +85,21 @@ class App extends ReactComponent<Props> {

<body>
<div className={className}>
<StaticBorderTop />
<AppContext.Provider value={{staticSite: props.staticSite}}>
<StaticBorderTop />

<SidePanel chapter={props.chapter} chapters={props.chapters} />
<SidePanel chapter={props.chapter} chapters={props.chapters} />

<MainWrapper>
<MainContent>
<MainContentContainer>
<Article chapter={extractChapter()} />
</MainContentContainer>
</MainContent>
</MainWrapper>
<MainWrapper>
<MainContent>
<MainContentContainer>
<Article chapter={extractChapter()} />
</MainContentContainer>
</MainContent>
</MainWrapper>

<StaticBorderBottom />
<StaticBorderBottom />
</AppContext.Provider>
</div>
</body>
</html>
Expand Down
13 changes: 11 additions & 2 deletions samples/docs/src/comp/SidePanel.hx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package comp;

import AppContext;
import data.DocChapter;

private typedef Props = {
private typedef PublicProps = {
var chapter:Null<String>;
var chapters:Array<DocChapter>;
}

private typedef Props = {
> PublicProps,
> AppContextData,
}

@:css
@:publicProps(PublicProps)
@:wrap(AppContext.wrap)
class SidePanel extends ReactComponent<Props> {
static var styles:Stylesheet = {
'_': {
Expand Down Expand Up @@ -65,6 +73,7 @@ class SidePanel extends ReactComponent<Props> {
};

override function render():ReactFragment {
var ext = props.staticSite ? '.html' : '';
return jsx(
<div className={className}>
<a href="/" className={classNames({"active": props.chapter == null})}>Home</a>
Expand All @@ -73,7 +82,7 @@ class SidePanel extends ReactComponent<Props> {
<div className="subnav">
<for {chapter in props.chapters}>
<div key={chapter.slug}>
<a href={chapter.slug} className={chapter.slug == props.chapter ? "active" : null}>
<a href={chapter.slug + ext} className={chapter.slug == props.chapter ? "active" : null}>
{chapter.title}
</a>
</div>
Expand Down
20 changes: 20 additions & 0 deletions samples/docs/src/data/DocChapter.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package data;

import js.lib.Promise;
import js.node.Fs.Fs;
import sys.FileSystem;
import sys.io.File;

Expand Down Expand Up @@ -30,6 +32,24 @@ function sortChapters(chapters:Array<DocChapter>):Array<DocChapter> {
return chapters;
}

function loadChapters():Promise<Array<DocChapter>> {
return new Promise((resolve, reject) -> {
Fs.readdir("../../doc", (err, files) -> {
var chapters = (files ?? [])
.map(f -> loadChapter(Path.join(["..", "..", "doc", f])))
.filter(f -> f != null);

resolve(sortChapters(chapters));
});
});
}

function loadReadme():Null<DocChapter> {
var ret = loadChapter(Path.join(["..", "..", "README.md"]));
if (ret != null) ret.slug = '/';
return ret;
}

function loadChapter(path:String):Null<DocChapter> {
if (!FileSystem.exists(path)) return null;
if (!path.endsWith(".md")) return null;
Expand Down

0 comments on commit 805c5b6

Please sign in to comment.