');
expect(file2).not.toContain("ActivityIndicator");
});
================================================
FILE: examples/react-app-blog/content/pages/about.md
================================================
---
title: About me
image: https://images.unsplash.com/photo-1495681803763-410ec9ff583d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ba41fd89a4d5dd9008d04ccea959c072&auto=format&fit=crop&w=900&q=60
---
Ahh. Hey, Doc, we better back up, we don't have enough roads to get up to 88.
Hi. Where were we. In that case, I'll tell you strait out.
Thank you, don't forget to take a flyer. Look, I'm just not ready to ask
Lorraine out to the dance, and not you, nor anybody else on this planet is gonna
make me change my mind. Over there, on my hope chest. I've never seen purple
underwear before, Calvin. What's with the life preserver? Working.
I still don't understand, how am I supposed to go to the dance with her, if
she's already going to the dance with you. Our first television set, Dad just
picked it up today. Do you have a television? I hope so. Uh, look me up when you
get there. Stand tall, boy, have some respect for yourself. Don't you know that
if you let people walk all over you know, they'll be walking all over you for
the rest of your life? Listen to me, do you think I'm gonna spend the rest of my
life in this slop house?
Where were we. That's for messing up my hair. I'm sure that in 1985, plutonium
is available at every corner drug store, but in 1955, it's a little hard to come
by. Marty, I'm sorry, but I'm afraid you're stuck here. Where's Einstein, is he
with you? Listen, this is very important, I forgot my video camera, could you
stop by my place and pick it up on your way to the mall?
Hi. Now Biff, don't con me. Of course I do. Just a second, let's see if I could
find it. George, buddy. remember that girl I introduced you to, Lorraine. What
are you writing? Let's go.
================================================
FILE: examples/react-app-blog/content/pages/index.md
================================================
---
image: https://images.unsplash.com/photo-1495287949939-c5d3daf1cab4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=8969aebe524921f79c88b9ba605da6c2&auto=format&fit=crop&w=900&q=60
---
Hi there. Here is a good sample for you if you are starting with Phenomic and
React. It provides a simple but powerful codebase that you will be able to
adjust as you wish pretty easily. Be sure to check out the
[source code of this theme](https://github.com/phenomic/phenomic/tree/master/examples/react-app-blog).
Before asking any question about Phenomic, be sure to read the documentation :
- [Getting Started with Phenomic](https://phenomic.io/en/tutorials/)
- [Documentation](https://phenomic.io/en/packages/core/docs/)
Also take a look at
[existing websites that use Phenomic](https://phenomic.io/en/showcase/), some
projects share their source code!
---
You may want to take a look at the [404.html](/404.html) and tweak the render.
---
_You feel like the base theme is not enough or you just saw something wrong?_
[Please help us make Phenomic better!](https://github.com/phenomic/phenomic/blob/master/CONTRIBUTING.md)
================================================
FILE: examples/react-app-blog/content/posts/draft-post.md
================================================
---
title: "I won't be there in production"
date: "2017-01-06"
draft: true
---
You can see me in dev mode, but I will be skipped in production
================================================
FILE: examples/react-app-blog/content/posts/fifth-post.md
================================================
---
title: "I wrote my fifth post and you won't believe what happen next"
date: "2017-01-05"
layout: light
---
This post is using the `light` layout, defined from markdown front-matter. How
cool?
Another post that have a [link to the first one](../first-post/).
An wrong link to [a post that does not exist](../unknown-post/) and another one
to [a page that does not exist](/unknown-page/).
Here is an [external link](http://phenomic.io).
```md
# Some markdown...
...in a markdown file. **Markdownception?**.
```
```js
import unifiedProcessor from "./unifiedProcessor";
import type { plugin } from "./unifiedProcessor";
import defaultOptions from "./default-options";
// eslint-disable-next-line
const debug = require("debug")("phenomic:plugin:transform-markdown");
```
================================================
FILE: examples/react-app-blog/content/posts/first-post.md
================================================
---
title: "This is a first post"
date: "2017-01-01"
---
# This is a [Markdown](https://en.wikipedia.org/wiki/Markdown#Example) file
If you are new to Markdown, you might want to check those links:
- [What is Markdown?](http://whatismarkdown.com/)
- [Mastering Markdown, a GitHub guide](https://guides.github.com/features/mastering-markdown/)
- [wikipedia.org/wiki/Markdown](https://en.wikipedia.org/wiki/Markdown#Example)
- [masteringmarkdown.com](http://masteringmarkdown.com/)
Code is highlighted by default.
```js
const StatelessComponent = props => {
return (
I‘m a stateless component that accepts children
{props.children}
);
};
const ContentContainer = withPhenomicApi(Content, () => ({
page: query({ id: "content" }),
}));
export default createApp(() => (
));
================================================
FILE: examples/react-app-markdown-with-custom-components/README.md
================================================
# React app: markdown with custom components
This example show you own to render normal and custom html tags as your own
React components.
_In short, you can replace `` by a react component `SomeTag` and get
children nodes (text or other nodes) as objects (not just raw html) to render
those as you like._
🚀 **So wow, such power!**
---
See
[the raw markdown file](https://raw.githubusercontent.com/phenomic/phenomic/master/examples/react-app-markdown-with-custom-components/content/index.md)
and the
[components map](https://github.com/phenomic/phenomic/blob/master/examples/react-app-markdown-with-custom-components/App.js)
to get an idea of the power this feature unlocks.
================================================
FILE: examples/react-app-markdown-with-custom-components/__tests__/index.js
================================================
// @flow
/* eslint-disable import/no-extraneous-dependencies */
import path from "path";
import fs from "fs";
it("should build example correctly", () => {
const file1 = fs.readFileSync(
path.join(__dirname, "..", "dist", "index.html"),
{ encoding: "utf8" },
);
expect(file1).toContain("This is a Markdown file");
expect(file1).not.toContain(
">This is some content visible during development only",
// - ">" is important in this test as we test it's not in the html
// but it's in the json as in this example we filter during rendering
// - well it's bad, isn't it?
// - not sure as you can imagine a toggle to enable draft doc!
);
});
================================================
FILE: examples/react-app-markdown-with-custom-components/content/index.md
================================================
---
title: "This is a Markdown file"
---
But with some custom html tags. But be careful, all
tags ends-up are lowercase!. This is because old school HTML IN
UPPERCASE LIKE works like a .
Note that you can create CustomTag that can just uppercase
stings.
You can even leverage children to make dynamic stuff.
Click me!
This is some content!
You can even hide some parts that are not ready yet!
This is some content visible during development only
================================================
FILE: examples/react-app-markdown-with-custom-components/package.json
================================================
{
"private": true,
"name": "@phenomic/example-react-app-markdown-with-custom-components",
"version": "1.0.0",
"devDependencies": {
"@phenomic/cli": "^1.0.0",
"@phenomic/core": "^1.0.0",
"@phenomic/preset-react-app": "^1.0.0",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-router": "^3.2.0"
},
"scripts": {
"start": "phenomic start",
"build": "phenomic build"
},
"phenomic": {
"presets": [
"@phenomic/preset-react-app"
]
}
}
================================================
FILE: examples/react-app-minimal-hello-world/App.js
================================================
// @flow
import * as React from "react";
import { Router, Route, browserHistory } from "react-router";
import { createApp } from "@phenomic/preset-react-app/lib/client";
// import { createApp, renderApp } from "@phenomic/preset-react-app/lib/client";
export default createApp(() => (
);
export default MarkdownGenerated;
================================================
FILE: website/components/MarkdownHeading.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, createElement } from "react-native-web";
import IconLink from "../svgs/IconLink";
import Link from "./Link";
import Hoverable from "./react-stylable/hoverable";
import Focusable from "./react-stylable/focusable";
/* eslint-disable react/no-multi-comp */
const RNIconLink = p => createElement(IconLink, p);
const MarkdownHeading = (level: number) => {
const Header = p => createElement("h" + level, p);
return Hoverable(
Focusable(({ hovered, focused, ...props }: Object) => {
return (
{props.children.slice(1)}
);
}),
);
};
const anchorSize = 22;
const anchorPadding = 6;
const styles = StyleSheet.create({
link: {
display: "flex",
alignItems: "center",
position: "absolute",
top: 0,
bottom: 0,
left: -anchorSize - anchorPadding,
transitionDuration: "0.2s",
opacity: 0,
},
linkVisible: {
opacity: 0.8,
},
icon: {
height: anchorSize + anchorPadding,
padding: anchorPadding,
},
});
const headings = {
H1: MarkdownHeading(1),
H2: MarkdownHeading(2),
H3: MarkdownHeading(3),
H4: MarkdownHeading(4),
H5: MarkdownHeading(5),
H6: MarkdownHeading(6),
};
export default headings;
================================================
FILE: website/components/PackageListItem.js
================================================
// @flow
import * as React from "react";
import { View, Text, StyleSheet } from "react-native-web";
import Link from "./Link";
const PackageListItem = (props: {| package: Object |}) => (
{props.package.name}
{props.package.author && (
{"By " + props.package.author}
)}
{props.package.authors && (
{"By "}
{props.package.authors
.map(author => {
let a = author;
// remove (avoid spam)
a = a.replace(/ <.+@.+>/g, "");
// assume "Name (nick)" => "Name @github"
a = a.replace(/ \(([a-zA-Z_]+)\)/g, " @$1");
// no space at all? assume github handle
if (!a.includes(" ")) {
a = "@" + a;
}
// if something looks like a github handle, we only show that
if (
a.includes("@") &&
(a.startsWith("@") || a.includes("(@") || a.includes(" @"))
) {
a = a.slice(a.indexOf("@"));
}
return a;
})
.join(", ")}
)}
);
const styles = StyleSheet.create({
block: {
// flexBasis: 400,
minWidth: 250,
width: "33%",
},
wrapper: {
flexGrow: 1,
marginHorizontal: 10,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: "rgba(0, 0, 0, 0.1)",
},
link: {
flex: 1,
display: "flex",
flexDirection: "column",
textDecorationLine: "none",
color: "inherit",
paddingVertical: 20,
paddingHorizontal: 10,
},
name: {
fontWeight: "700",
fontSize: 22,
paddingBottom: 10,
},
author: {
fontWeight: "100",
color: "#999",
},
});
export default PackageListItem;
================================================
FILE: website/components/Page.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, View, Text } from "react-native-web";
/* eslint-disable-next-line */
import PropTypes from "prop-types";
/* eslint-disable-next-line */
import { isActive } from "@phenomic/plugin-renderer-react/lib/components/Link.js";
import Stylable from "./react-stylable";
import Flex from "./Flex";
import Link from "./Link";
import Spacer from "./Spacer";
import ActivityIndicator from "./ActivityIndicator";
import MarkdownGenerated from "./MarkdownGenerated";
import PageError from "./PageError";
import Header from "./Header";
import Footer from "./Footer";
import BodyContainer from "./BodyContainer";
import BodySmallContainer from "./BodySmallContainer";
const layouts = {
Default: props => (
),
};
const sort = (a, b) => {
if (a.priority && b.priority) {
if (a.priority < b.priority) return -1;
if (a.priority > b.priority) return 1;
}
if (a.priority) return 1;
if (b.priority) return -1;
if (a.id < b.id) return -1;
if (a.id > b.id) return 1;
return 0;
};
export function readPkgFromId(id: string) {
const pieces = id ? id.split("/") : [];
return pieces.shift();
}
// eslint-disable-next-line react/no-multi-comp
const Page = (props: Object, context: Object) => {
if (props.hasError) {
return ;
}
const Container = props.pages ? BodyContainer : BodySmallContainer;
let Layout = layouts.Default;
if (
props.page &&
props.page.node &&
props.page.node.layout &&
layouts[props.page.node.layout]
) {
Layout = layouts[props.page.node.layout];
}
const currentPkg = readPkgFromId(props.params.splat);
return (
{props.pages && (
{props.pages.node &&
props.pages.node.list
.filter(
p =>
readPkgFromId(p.id) == currentPkg &&
// avoid package.json files
!p.title.endsWith("package.json"),
)
.sort(sort)
.map(page => {
const href = `/en/packages/${page.id}/`;
return (
{page.title}
{isActive(href, context) && (
{Array.isArray(page.headings) &&
page.headings
.map(
h =>
h.level === 1 &&
page.title === h.text ? null : (
{h.text}
),
)
.filter(heading => heading)}
)}
);
})}
)}
{props.isLoading && }
{!props.isLoading && }
);
};
const styles = StyleSheet.create({
row: {
flexDirection: "row",
flexWrap: "wrap",
},
sidebar: {
flex: 0,
flexBasis: 250,
marginTop: 30,
},
sidebarLink: {
fontSize: 18,
color: "#006BF6",
borderLeftWidth: 4,
borderLeftStyle: "solid",
borderLeftColor: "transparent",
},
sidebarLinkActive: {
borderLeftColor: "#02CA83",
},
sidebarLinkFocused: {
color: "#fff",
backgroundColor: "#006BF6",
},
sidebarHeadingLink: {
fontWeight: "300",
color: "#006BF6",
},
sidebarHeadingLinkActive: {
borderLeftColor: "#02CA83",
},
sidebarHeadingLinkFocused: {
color: "#fff",
backgroundColor: "#006BF6",
},
/* eslint-disable react-native/no-unused-styles */
sidebarHeadingLink1: { marginLeft: Spacer.small * 1 },
sidebarHeadingLink2: { marginLeft: Spacer.small * 2 },
sidebarHeadingLink3: { marginLeft: Spacer.small * 3 },
sidebarHeadingLink4: { marginLeft: Spacer.small * 4 },
sidebarHeadingLink5: { marginLeft: Spacer.small * 5 },
sidebarHeadingLink6: { marginLeft: Spacer.small * 6 },
/* eslint-enable react-native/no-unused-styles */
content: {
flex: 2,
flexBasis: 400,
},
});
export default Page;
================================================
FILE: website/components/PageDoc.js
================================================
// @flow
import { withPhenomicApi, query } from "@phenomic/preset-react-app/lib/client";
import Page from "./Page";
export default withPhenomicApi(Page, props => {
return {
page: query({
path: `packages`,
id: props.params.splat,
}),
pages: query({
path: `packages`,
}),
};
});
================================================
FILE: website/components/PageError.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, View, Text } from "react-native-web";
import BodyContainer from "./BodyContainer";
import Header from "./Header";
import Footer from "./Footer";
const PageError = ({ error }: { error: Object }) => {
const status = (error && error.status) || 404;
const errorText =
error && status !== 404 ? error.statusText : "Page not found";
return (
{"Oooops!"}{status} {errorText}
{status === 404 && (
{"It seems you found a broken link. "}
{"Sorry about that. "}
{"Do not hesitate to report this page."}
)}
);
};
const styles = StyleSheet.create({
container: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
minHeight: "50vh",
padding: "1rem 0",
},
oops: {
fontSize: "4rem",
lineHeight: "4rem",
color: "#ddd",
},
title: {
margin: 60,
fontSize: 24,
lineHeight: 48,
textAlign: "center",
},
});
export default PageError;
================================================
FILE: website/components/PagePackageList.js
================================================
// @flow
import * as React from "react";
import { View, StyleSheet } from "react-native-web";
import { withPhenomicApi, query } from "@phenomic/preset-react-app/lib/client";
import Flex from "./Flex";
import Spacer from "./Spacer";
import ActivityIndicator from "./ActivityIndicator";
import PageError from "./PageError";
import Header from "./Header";
import Footer from "./Footer";
import BodyContainer from "./BodyContainer";
import PackageListItem from "./PackageListItem";
const PagePackageList = (props: Object) => {
if (props.hasError) {
return ;
}
return (
{props.isLoading && }
{!props.isLoading && (
{props.packages.node.list
// only released pkg
.filter(pkg => !pkg.private)
.map(item => (
))}
)}
);
};
const styles = StyleSheet.create({
container: {
paddingVertical: 20,
},
list: {
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "flex-start",
alignItems: "flex-start",
},
});
export default withPhenomicApi(PagePackageList, () => ({
packages: query({
path: "packages",
by: "keywords",
value: "phenomic-package",
sort: "name",
order: "asc",
}),
}));
================================================
FILE: website/components/PageShowcase.js
================================================
// @flow
import { withPhenomicApi, query } from "@phenomic/preset-react-app/lib/client";
import Page from "./Page";
export default withPhenomicApi(Page, props => ({
page: query({
path: "content/showcase",
id: props.params.splat,
}),
}));
================================================
FILE: website/components/PhenomicLogo.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, Dimensions, View, Text } from "react-native-web";
import { version } from "../../lerna.json";
import PhenomicLogoWhite from "../svgs/PhenomicLogoWhite";
import PhenomicText from "../svgs/PhenomicText";
import Link from "./Link";
import Spacer from "./Spacer";
class PhenomicLogo extends React.PureComponent {
componentDidMount() {
if (typeof window !== undefined) {
window.addEventListener("resize", this.handleLayout);
}
}
componentWillUnmount() {
if (typeof window !== undefined) {
window.removeEventListener("resize", this.handleLayout);
}
}
handleLayout = () => {
if (!this.timeout) {
this.timeout = setTimeout(() => {
this.timeout = null;
this.forceUpdate();
}, 500);
}
};
render() {
const { width } = Dimensions.get("window");
return (
{width > 500 && (
{"v" + version}
)}
);
}
}
const styles = StyleSheet.create({
container: {
flexGrow: 0,
flexShrink: 1,
flexBasis: 64,
flexDirection: "row",
alignItems: "center",
},
version: {
position: "absolute",
bottom: -Spacer.normal,
textDecorationLine: "none",
color: "#fff",
opacity: 0.2,
fontSize: 12,
},
versionText: {
wordBreak: "keep-all",
},
});
export default PhenomicLogo;
================================================
FILE: website/components/Plugins.js
================================================
// @flow
import * as React from "react";
import { View, Text, StyleSheet } from "react-native-web";
import Header from "./Header";
import Footer from "./Footer";
import BodyContainer from "./BodyContainer";
import Flex from "./Flex";
import Spacer from "./Spacer";
const Plugins = () => {
return (
{"WIP"}
);
};
const styles = StyleSheet.create({
row: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
},
});
export default Plugins;
================================================
FILE: website/components/ShowcaseList.js
================================================
// @flow
import * as React from "react";
import { View, Text, Image, StyleSheet, createElement } from "react-native-web";
import { withPhenomicApi, query } from "@phenomic/preset-react-app/lib/client";
import urlToSlug from "../modules/url-to-slug";
import { screenshotsSize } from "../package.json";
import Flex from "./Flex";
import Link from "./Link";
import Spacer from "./Spacer";
import ActivityIndicator from "./ActivityIndicator";
import Header from "./Header";
import Footer from "./Footer";
import BodyContainer from "./BodyContainer";
const Div = props => createElement("div", props);
// eslint-disable-next-line react/no-multi-comp
const ShowcaseList = (props: Object) => (
{props.isLoading && }
{!props.isLoading && (
{"+ Add your website"}
{props.params &&
props.params.showcaseTags && (
{"You are currently viewing projects that match "}
{props.params.showcaseTags}
{" tag. "}
{"View all."}
)}
{props.showcase.node.list.map(item => (
{item.title}{" "}
{item.source && (
{"(Source)"}
)}
{item.showcaseTags &&
item.showcaseTags.map(tag => (
{tag}
))}
))}
{props.showcase.node &&
props.showcase.node.previous && (
{"← Previous"}
)}
{props.showcase.node &&
props.showcase.node.next && (
{"Next →"}
)}
)}
);
const styles = StyleSheet.create({
row: {
flexDirection: "row",
alignItems: "center",
},
page: {
paddingTop: 10,
paddingBottom: 10,
},
addYourOwn: {
justifyContent: "flex-end",
position: "absolute",
right: 20,
top: -40,
fontSize: 16,
color: "#fff",
textDecorationLine: "underline",
},
currentFilter: {
padding: 10,
flexDirection: "row",
justifyContent: "center",
},
filterMessage: {
padding: 10,
color: "#4078c0",
backgroundColor: "#e6f1f6",
borderRadius: 3,
},
filterMessageLink: {
color: "#4078c0",
fontWeight: "bold",
},
list: {
flexDirection: "row",
flexWrap: "wrap",
},
item: {
flexGrow: 1,
minWidth: 250,
position: "relative",
width: "50%",
padding: 20,
},
imageLarge: {
flexGrow: 1,
paddingBottom:
(100 * screenshotsSize.large.height) / screenshotsSize.large.width + "%",
borderWidth: 1,
borderColor: "rgba(0,0,0,.1)",
borderRadius: 4,
},
imageContainerSmall: {
position: "absolute",
right: -10,
bottom: -10,
width: "20%",
},
imageSmall: {
flexGrow: 1,
width: "100%",
paddingBottom:
(100 * screenshotsSize.small.height) / screenshotsSize.small.width + "%",
borderWidth: 1,
borderColor: "rgba(0,0,0,.1)",
borderRadius: 4,
},
itemName: {
fontWeight: "700",
fontSize: 18,
lineHeight: 18 * 2,
color: "#424345",
},
itemLinkSource: {
fontSize: 12,
textDecorationLine: "none",
color: "#006df4",
opacity: 0.4,
},
tags: {
flexDirection: "row",
justifyContent: "flex-end",
marginRight: -10,
},
itemTag: {
fontSize: 12,
lineHeight: 24,
margin: 10,
paddingLeft: 6,
paddingRight: 6,
color: "#08b09b",
backgroundColor: "#fff",
borderRadius: 3,
},
paginationRow: {
flexDirection: "row",
},
paginationColumn: {
width: "50%",
padding: 10,
alignItems: "center",
justifyContent: "center",
},
link: {
color: "#006df4",
fontSize: 18,
padding: 20,
},
});
export { ShowcaseList as Component };
export default withPhenomicApi(ShowcaseList, props => ({
showcase: query({
path: "content/showcase/entry",
order: "asc",
sort: "showcase",
limit: 10,
after: props.params.after,
}),
}));
export const ShowcaseListByTag = withPhenomicApi(ShowcaseList, props => ({
showcase: query({
path: "content/showcase/entry",
by: "showcaseTags",
value: props.params.showcaseTags,
order: "asc",
sort: "showcase",
limit: 10,
after: props.params.after,
}),
}));
================================================
FILE: website/components/Spacer.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, View } from "react-native-web";
type p = {|
horizontal?: boolean,
vertical?: boolean,
small?: boolean,
smallHorizontal?: boolean,
smallVertical?: boolean,
large?: boolean,
largeHorizontal?: boolean,
largeVertical?: boolean,
|};
const Spacer = (props: p) => (
{props.children}
);
Spacer.small = 10;
Spacer.normal = 20;
Spacer.large = 40;
const styles = StyleSheet.create({
default: {
flex: 1,
},
normalMargin: {
marginHorizontal: Spacer.normal / 2,
marginVertical: Spacer.normal / 2,
},
normalMarginHorizontal: {
marginHorizontal: Spacer.normal / 2,
},
normalMarginVertical: {
marginVertical: Spacer.normal / 2,
},
smallMargin: {
marginHorizontal: Spacer.small / 2,
marginVertical: Spacer.small / 2,
},
smallMarginVertical: {
marginVertical: Spacer.small / 2,
},
smallMarginHorizontal: {
marginHorizontal: Spacer.small / 2,
},
largeMargin: {
marginHorizontal: Spacer.large / 2,
marginVertical: Spacer.large / 2,
},
largeMarginHorizontal: {
marginHorizontal: Spacer.large / 2,
},
largeMarginVertical: {
marginVertical: Spacer.large / 2,
},
});
export default Spacer;
================================================
FILE: website/components/Spinner.js
================================================
// @flow
import * as React from "react";
type props = {|
style?: any,
borderWidth?: string,
delay: number,
duration: string,
color: string,
color2: string,
|};
class Spinner extends React.PureComponent {
state = {
visible: false,
};
_timeout: TimeoutID;
componentDidMount() {
this._timeout = setTimeout(
() => this.setState({ visible: true }),
this.props.delay || 250,
);
}
componentWillUnmount() {
clearTimeout(this._timeout);
}
render() {
return (
);
}
}
export default Spinner;
================================================
FILE: website/components/Tutorials.js
================================================
// @flow
import * as React from "react";
import { View, Text, StyleSheet } from "react-native-web";
import Header from "./Header";
import Footer from "./Footer";
import BodyContainer from "./BodyContainer";
import Flex from "./Flex";
import Link from "./Link";
import Spacer from "./Spacer";
const items = [
{
title: "React App",
Icon: require("../svgs/ReactLogo").default,
link: "/en/packages/preset-react-app/docs/",
},
];
const Tutorials = () => {
return (
{"Start by choosing your ecosystem"}
{items.map((item, i) => (
{item.title}
))}
{"Don't see what you're looking for?"}
);
};
const styles = StyleSheet.create({
row: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
},
logos: {
marginTop: 48,
marginBottom: 24,
borderTopWidth: 1,
borderTopColor: "#dfe7ed",
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center",
alignItems: "center",
},
logoWrapper: {
minWidth: "33%",
},
logo: {
borderBottomWidth: 1,
borderBottomColor: "#dfe7ed",
borderBottomStyle: "solid",
flexGrow: 1,
flexDirection: "column",
paddingVertical: 48,
alignItems: "center",
color: "inherit",
textDecorationStyle: "none",
},
logoTitle: {
fontSize: 18,
fontWeight: "300",
color: "#4c4d63",
},
img: {
flexGrow: 1,
justifyContent: "center",
marginBottom: 24,
},
todo: {
opacity: 0.25,
filter: "blur(1px) grayscale(75%)",
},
notice: {
opacity: 0.25,
// fontSize: 24,
paddingVertical: 48,
},
});
export default Tutorials;
================================================
FILE: website/components/Wrapper.js
================================================
// @flow
import * as React from "react";
import { StyleSheet, View } from "react-native-web";
import Head from "react-helmet";
const Wrapper = (props: Object) => (
{props.children}
);
const styles = StyleSheet.create({
wrapper: {
flex: 1,
backgroundColor: "#F2F5F8",
},
});
export default Wrapper;
================================================
FILE: website/components/react-stylable/focusable.js
================================================
// @flow
import * as React from "react";
type props = {|
onFocus?: () => void,
onBlur?: () => void,
|};
type state = {|
focused: boolean,
|};
export default (ComposedComponent: React.ComponentType<*>) => {
class Focusable extends React.Component {
props: props;
state: state = {
focused: false,
};
handleFocus = (event: React$SyntheticEvent): void => {
this.setState({ focused: true });
if (typeof this.props.onFocus === "function") {
this.props.onFocus(event);
}
};
handleBlur = (event: React$SyntheticEvent): void => {
this.setState({ focused: false });
if (typeof this.props.onBlur === "function") {
this.props.onBlur(event);
}
};
render() {
return (
);
}
}
return Focusable;
};
================================================
FILE: website/components/react-stylable/hoverable.js
================================================
// @flow
import * as React from "react";
type props = {|
onMouseEnter?: () => void,
onMouseLeave?: () => void,
|};
type state = {|
hovered: boolean,
|};
export default (ComposedComponent: React.ComponentType<*>) => {
class Hoverable extends React.Component {
props: props;
state: state = {
hovered: false,
};
handleMouseEnter = (event: React$SyntheticEvent): void => {
this.setState({ hovered: true });
if (typeof this.props.onMouseEnter === "function") {
this.props.onMouseEnter(event);
}
};
handleMouseLeave = (event: React$SyntheticEvent): void => {
this.setState({ hovered: false });
if (typeof this.props.onMouseLeave === "function") {
this.props.onMouseLeave(event);
}
};
render() {
return (
);
}
}
return Hoverable;
};
================================================
FILE: website/components/react-stylable/index.js
================================================
// @flow
import React from "react";
import Hoverable from "./hoverable";
import Focusable from "./focusable";
import Touchable from "./touchable";
import TouchableMouse from "./touchable-mouse";
type p = {|
children?: React$Element,
// hoc
hovered: boolean,
focused: boolean,
touched: boolean,
// user
style?: any,
hoveredStyle?: any,
focusedStyle?: any,
touchedStyle?: any,
hoveredOrFocusedStyle?: any,
|};
const Stylable = (props: p) => {
const {
hovered,
focused,
touched,
style,
hoveredStyle,
focusedStyle,
touchedStyle,
hoveredOrFocusedStyle,
children,
...othersProps
} = props;
return React.cloneElement(children, {
...othersProps,
style: [
style,
hovered && hoveredStyle,
focused && focusedStyle,
(hovered || focused) && hoveredOrFocusedStyle,
touched && touchedStyle,
],
});
};
export default Hoverable(Focusable(Touchable(TouchableMouse(Stylable))));
================================================
FILE: website/components/react-stylable/touchable-mouse.js
================================================
// @flow
import * as React from "react";
type props = {|
onMouseDown?: () => void,
onMouseUp?: () => void,
|};
type state = {|
touched: boolean,
|};
export default (ComposedComponent: React.ComponentType<*>) => {
class MouseDownable extends React.Component {
props: props;
state: state = {
touched: false,
};
handleMouseDown = (event: React$SyntheticEvent): void => {
this.setState({ touched: true });
if (typeof this.props.onMouseDown === "function") {
this.props.onMouseDown(event);
}
};
handleMouseUp = (event: React$SyntheticEvent): void => {
this.setState({ touched: false });
if (typeof this.props.onMouseUp === "function") {
this.props.onMouseUp(event);
}
};
render() {
return (
);
}
}
return MouseDownable;
};
================================================
FILE: website/components/react-stylable/touchable.js
================================================
// @flow
import * as React from "react";
type props = {|
onTouchStart?: () => void,
onTouchEnd?: () => void,
|};
type state = {|
touched: boolean,
|};
export default (ComposedComponent: React.ComponentType<*>) => {
class TouchStartable extends React.Component {
props: props;
state: state = {
touched: false,
};
handleTouchStart = (event: React$SyntheticEvent): void => {
this.setState({ touched: true });
if (typeof this.props.onTouchStart === "function") {
this.props.onTouchStart(event);
}
};
handleTouchEnd = (event: React$SyntheticEvent): void => {
this.setState({ touched: false });
if (typeof this.props.onTouchEnd === "function") {
this.props.onTouchEnd(event);
}
};
render() {
return (
);
}
}
return TouchStartable;
};
================================================
FILE: website/content/blog/2017-06-02-introducing-1.0.0-alpha.md
================================================
---
title: Introducing Phenomic 1.0.0 first alpha
author: bloodyowl
---
## A complete rewrite
Phenomic is a static website generator that has been in v0.\* for quite a while
now. As we wanted to release a v1, we took some time to think about what needed
to change, and what we could do better for our stable API.
A few months ago, we started the reflexion. As our GitHub issues were mainly
bikeshedding and user-specific needs, we realised that we were trying to bring
too much in our core module, which was preventing us from moving forward to
where we wanted to push Phenomic.
We then started prototyping a new version in consideration of what we want it to
be capable of:
- Use an HTTP API as content source, which would enable us to build static
versions of multiple CMS
- Have a powerful querying API
- Build scalable static web apps
- Handle pagination
Therefore we decided to make a simple core API and put the specifics in plugins.
Phenomic for now has a default preset with Webpack and React, but opens the way
for any other bundler or UI library (ping us if you'd like to implement Rollup,
Vue or Angular).
Today we're officially releasing the first alpha of our 1.0.0 API, and we'd be
really grateful for your feedback while we finalise the last details and the
docs.
Be sure to check out ["Getting Started"](https://phenomic.io/en/tutorials/)
page!
You can have a look on
[this website source](https://github.com/phenomic/phenomic/tree/master/website)
and
[learn how to get started](https://github.com/phenomic/phenomic/tree/master/packages/preset-react-app/docs/getting-started/README.md).
We hope you'll like this release!
================================================
FILE: website/content/blog/2017-06-10-v1.0.0-alpha.3.md
================================================
---
title: v1.0.0-alpha.3
tag_name: v1.0.0-alpha.3
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.3
author: MoOx
prerelease: true
---
## Changes
- change(`@phenomic/core`): merge `getMiddlewares` and `defineDevMiddleware` as
`addDevServerMiddlewares`
([4322731](https://github.com/phenomic/phenomic/commit/4322731a7abbd18dd0557b488af875cc5152c9ae) -
@MoOx)
- change(`@phenomic/plugin-bundler-webpack`): now require a consistent
bundleName (from config, default to "phenomic.main")
([c8678c0](https://github.com/phenomic/phenomic/commit/c8678c0bf2b24389d2faa8508c4c543b0d99f889) -
@MoOx)
- `@phenomic/core` is now a peer dependency of all packages
([f86f253](https://github.com/phenomic/phenomic/commit/f86f2538a9643331e6979f9da2415ded4472ab80) -
@MoOx)
## Fixes
- fix(`@phenomic/plugin-bundler-webpack`): set webpack & webpack-dev-middleware
as deps ([#1049](https://github.com/phenomic/phenomic/issues/1049) - @MoOx)
- fix(`@phenomic/plugin-collector-files`): normalize path for windows
([#1046](https://github.com/phenomic/phenomic/issues/1046) - @shaunmarx)
- fix(`@phenomic/plugin-public-assets`): make "public" folder optional
([4322731](https://github.com/phenomic/phenomic/commit/4322731a7abbd18dd0557b488af875cc5152c9ae) -
@MoOx)
- fix(`@phenomic/core`): make "content" folder optional
([e892781](https://github.com/phenomic/phenomic/commit/e892781e9e0a9f80f33cc572ed0211785a7677b5) -
@MoOx)
- fix(`@phenomic/core`): don't log start & do cleanup when build script is
interpreted (should happen when used)
([d361185](https://github.com/phenomic/phenomic/commit/d361185da835159a3b92e21f3543eeb19efde5b0) -
@MoOx)
## New features
- feat(`@phenomic/core`): add an logger utility to normalize plugin logs ouput
(`import logger from '@phenomic/core/lib/logger'; const log = logger("plugin name"); log.info("stuff");`)
([f908a58](https://github.com/phenomic/phenomic/commit/f908a58c99c8cba1bac3f6e78bcd70914013a759) -
@MoOx)
- feat(`@phenomic/plugin-renderer-react`): BodyRenderer component now accept a
"components" map
([d3500ae](https://github.com/phenomic/phenomic/commit/d3500ae6d04202518efdbf280387d9713d15807f) -
@MoOx)
================================================
FILE: website/content/blog/2017-07-11-v1.0.0-alpha.4.md
================================================
---
title: v1.0.0-alpha.4
tag_name: v1.0.0-alpha.4
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.4
author: MoOx
prerelease: true
---
fix(@phenomic/core): support static rendering of "by" parameters for main
(first) collection `collection` params in routes is now useless as we consider
the first collection of the queries as the main query. (@MoOx)
feat(@phenomic/cli): add a default babel config
([#1071](https://github.com/phenomic/phenomic/issues/1071) - @MoOx)
feat(@phenomic/plugin-renderer-react): render path that finish with html as is
([#1106](https://github.com/phenomic/phenomic/issues/1106) - @MoOx)
fix(@phenomic/plugin-renderer-react): Prevent our react context usage from
colliding with redux
([#1086](https://github.com/phenomic/phenomic/issues/1086) - @bloodyowl)
================================================
FILE: website/content/blog/2017-08-09-v1.0.0-alpha.5.md
================================================
---
title: v1.0.0-alpha.5
tag_name: v1.0.0-alpha.5
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.5
author: MoOx
prerelease: true
---
🎉 We added examples in `examples/*` for
[react-app](https://github.com/phenomic/phenomic/tree/master/examples/react-app)
and
[reason-react-app](https://github.com/phenomic/phenomic/tree/master/examples/reason-react-app).
We also have prepared a workflow to be able to quickly add more examples with
automated testing to prevent any kind of regressions. Documentation is also
covered by tests to prevent regressions.
Stay tuned for more examples. And do not hesitate to add some!
Do not hesitate to contact us if you want to contribute as our CONTRIBUTING.md
is still a WIP :)
# tl;dr;
- Tons of fixes in
[Getting Started](https://github.com/phenomic/phenomic/blob/master/packages/preset-react-app/docs/getting-started/README.md)
- Fixed & improved pagination and static rendering
- Examples for preset-react-app & reason
- Client side navigation enabled for markdown link
- "Various fixes" 🙃
# Notable fixes & improvements
## `@phenomic/core`
- Fix static rendering for collection items (when no by param is used)
([#1114](https://github.com/phenomic/phenomic/issues/1114) - @MoOx)
- Fix pagination `previous` that was incorrect for second page (@MoOx)
- Fix `order: 'asc'` for queries (@MoOx)
- Pre-rendering now handle ALL possible pages for pagination. This is a huge
step forward as we now have a real immutable pagination that opens a number of
possibilities like infinite scrolling mixed with immutable pages urls! (@MoOx,
@bloodyowl)
## `@phenomic/plugin-public-assets`
- Prevent infinite static build step if no "public" folder exist (@MoOx)
## `@phenomic/plugin-bundler-webpack`
- Only shallow error if config file does not exist
([#1085](https://github.com/phenomic/phenomic/issues/1085) - @MoOx)
## `@phenomic/plugin-renderer-react`
- New `Link` component that you should use instead of react-router v3 one. It
enables client side routing for markdown by default and **also handle relative
and external urls** unlike react-router v3 `Link`. (@MoOx)
## `@phenomic/preset-react-app`
- Update for Getting Started (@MoOx, @Izhaki, @nicolas-zozol, @andrwh, @soycode,
@YuyingWu, @syndia)
## `@phenomic/reason`
- Various mysterious updates by @bloodyowl. Please refer to the
[examples/reason-react-app](https://github.com/phenomic/phenomic/tree/master/examples/reason-react-app)
until API is stable & doc is complete.
[PR #1111](https://github.com/phenomic/phenomic/pull/1111)
================================================
FILE: website/content/blog/2017-09-08-v1.0.0-alpha.6.md
================================================
---
title: v1.0.0-alpha.6
tag_name: v1.0.0-alpha.6
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.6
author: MoOx
prerelease: true
---
We have made some tiny breaking changes (easy to update) for a better future (to
give you more power (eg: query for sub-folder & choice for whatever css-in-js
solution you want :)
We have added plenty of
[examples](https://github.com/phenomic/phenomic/tree/master/examples). Be sure
to take a look!
FYI, those examples will always be up to date with Phenomic API as those are
automatically tested in our full test suit (with some assertions to check the
result)!
# tl;dr
## 💥 **Breaking change**
- `collection` concept has been replaced by a simple `path`.
- Html component must be in its own file & offers controls for rendering of the
HTML (eg: for CSS-in-JS static rendering), see details below.
- Some change simple have been made for API of render plugins (if you wrote one,
let us know!).
## ✨ New features
- JS/CSS now have hashes in the filename to avoid caching issues.
- CSS files can now be easily injected in the Html.
- Some enhancements on webpack default config.
- React plugin now exports a function to render content as raw text (handy for
meta description & similar)
---
## Details
### `@phenomic/core`
- 💥 **Breaking change** we changed a little renderer plugin API:
- `renderServer` becomes `renderStatic`
- `renderHTML` is now hidden and replaced by `renderDevServer` method that
accept assets (key: array of filenames) returned by build or injected by
`addDevServerMiddlewares` in res.locals.assets (@MoOx)
- 💥 **Breaking change** `collection` concept has been replaced by a simple
`path`. You can just replace all `collection` in your query by `path` and it
should work. What you are winning here is the ability to query using a
sub-folder.
### `@phenomic/plugin-bundler-webpack`
- Upgrade to webpack@^3.0.0. It's a bit faster on our website (28s vs 24s -
Phenomic part is > 2s).
([#1137](https://github.com/phenomic/phenomic/pull/1137) - @MoOx)
- Properly pass assets to the core (so CSS and JS files are known) (@MoOx)
### `@phenomic/plugin-renderer-react` & `@phenomic/preset-react-app`
- 💥 **Breaking change** props passed to Html components are now components to
render & not string. This will allow people to wrap rendering (eg: so they can
use whatever CSS-in-JS solutions).
Previously, a minimal `Html` component was like
```js
const Html = props => (
{props.body}
{props.state}
{props.script}
);
```
Now it should be
```js
const Html = ({ App, render }) => {
const { Main, State, Script, Style } = render();
// you have also an `assets` object if you want more control to renders js/css files
return (
);
```
([#1094](https://github.com/phenomic/phenomic/issues/1094) - @MoOx)
- A new `textRenderer` to convert page content to raw text is now export.
```js
import {
createApp,
createContainer,
query,
BodyRenderer,
/***** I AM NEW *****/
textRenderer,
/********************/
} from "@phenomic/preset-react-app/lib/client";
// also available from "@phenomic/plugin-renderer-react/lib/client"
const BlogPost = ({ isLoading, page }) => (
);
```
([#1084](https://github.com/phenomic/phenomic/issues/1084) - @MoOx)
================================================
FILE: website/content/blog/2017-09-15-v1.0.0-alpha.7.md
================================================
---
title: v1.0.0-alpha.7
tag_name: v1.0.0-alpha.7
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.7
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
Only fixes & improvements!
---
- [`@phenomic/core`: **Fix encoding issue for static generated API files**](https://github.com/phenomic/phenomic/commit/058b20a6b674cd750c8e4ebdeb89dc669c8559f4),
by @MoOx, reported by @ArthurClemens in
[#1158](https://github.com/phenomic/phenomic/issues/1158)
- [`@phenomic/plugin-bundler-webpack`: **Fix react-native-web StyleSheet pre-rendering (regression with 1.0.0-alpha-6 changes)**](https://github.com/phenomic/phenomic/commit/aa3d06f605b20d2744e186e24f6371d5f2604d50),
by @MoOx
- [`@phenomic/plugin-renderer-react`: **Avoid unnecessary React warning in development**](https://github.com/phenomic/phenomic/commit/0918b79370c066f0e4ff3577ee448f6356c92d45),
by @MoOx, reported by @DominikGuzei in
[#1155](https://github.com/phenomic/phenomic/issues/1155)
- [`@phenomic/core`: **Add a explicit message if dev server is running when you try to build static version**](https://github.com/phenomic/phenomic/commit/2a3f40e2cb95a8a92408eb9ac7be56cfee8116dc),
by @MoOx, reported by @ArthurClemens in
[#1156](https://github.com/phenomic/phenomic/issues/1156)
- [`@phenomic/plugin-renderer-react`: **Fix incorrect class name(s) rendering for Link component**](https://github.com/phenomic/phenomic/commit/50f9a62dbee06eabc631259d056f06e962db9c0e),
by @MoOx, reported by @DominikGuzei in
[#1154](https://github.com/phenomic/phenomic/issues/1154)
- [`@phenomic/plugin-renderer-react`: **Improve Link behavior for better accessibility (respect modifiers, target + keyboard navigation)**](https://github.com/phenomic/phenomic/commit/5b7422465c7755e51ef07bac1a53a6bcaf4610ab),
by @MoOx
The Link component (by default used to navigate between content (eg: markdown)
link) has been improved:
- does not use directly react-router Link, but instead just push the url in
the navigation history (which is supported by react-router)
- respect target=\_blank original behavior
- respect keyboard modifiers original behaviors (eg: cmd+click, alt+click etc)
- work better with keyboard navigation (enter key) has it's now triggering
client side navigation!
This component can receive onClick and onPress callback that can trigger a
preventDefault() to avoid the original behavior of the component if necessary.
================================================
FILE: website/content/blog/2017-09-16-v1.0.0-alpha.8.md
================================================
---
title: v1.0.0-alpha.8
tag_name: v1.0.0-alpha.8
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.8
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
A simple bug fix on an edge case for paginated queries + a fix for an
undocumented component :)
---
- [`@phenomic/core:` Fix "hasNextPage" & "next" reference for a paginated query when a page ends with the last item of the entire collection](https://github.com/phenomic/phenomic/commit/7c167686c679493b594d771222fc961eccd921fb),
by @MoOx, reported by @ArthurClemens
- [`@phenomic/plugin-renderer-react:` Fix activeStyle for Link component (+ refactoring for internal/external links management)](https://github.com/phenomic/phenomic/commit/83b0181ae6444670b65703d65cce59cb3516b1a8),
by @MoOx
================================================
FILE: website/content/blog/2017-09-27-v1.0.0-alpha.10.md
================================================
---
title: 1.0.0 Super Alpha X
tag_name: v1.0.0-alpha.10
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.10
author: MoOx
prerelease: true
---
Because it’s a trend to skip version 9, we are bumping from alpha.8 to alpha.10
(pronounced “alpha X”).

---
😍 Phenomic was already React 16 ready thanks to our architecture. We are now
fully compatible (= no warnings)
# 💥 2 minor breaking changes
- [`@phenomic/reason`: `Link` component `toURL` prop is now `href`](https://github.com/phenomic/phenomic/commit/b126dc9dae6b57e2c49509577e45135b79ce7f21),
by @MoOx
- `@phenomic/plugin-transform-markdown`: Anchor that was present by default have
been removed by default. See new feature at the end 😉
## 🐛 Bugfixes
- [`@phenomic/api-client`: Fix encoding issue for query with path + id](https://github.com/phenomic/phenomic/commit/34a223f9620f01ada8be75e832670292089c2a1a),
by @MoOx, reported by @ArthurClemens & @tleef (in
[#1168](https://github.com/phenomic/phenomic/issues/1168))
- [`@phenomic/plugin-bundler-webpack`: react-helmet `renderStatic()` now works as expected](https://github.com/phenomic/phenomic/commit/f9ce59c8d3997592a14a6f0ad11d5c997edfee89),
by @MoOx, reported by @ArthurClemens & @hellais (in
[#1167](https://github.com/phenomic/phenomic/issues/1167))
- [`@phenomic/reason`: pass all props to Link component](https://github.com/phenomic/phenomic/commit/2dd164f8a46e3514149d789dbf77b9364e50d12a),
by @MoOx
- [`@phenomic/plugin-bundler-webpack`: ensure full glamor & aphrodite static rendering compatibility out of the box](https://github.com/phenomic/phenomic/commit/381b4490bb4b9418273958533ae46c2384b79044),
by @MoOx, reported by @owenhoskins
## 👍 Improvements
- [`@phenomic/plugin-renderer-react`: React 16 compatibility](https://github.com/phenomic/phenomic/commit/19a8246ffd1ec88b069340791659b862abc772c2),
by @MoOx, helped by @JulienPradet
- [`@phenomic/babel-preset`: babel-preset-react-app to latest version](https://github.com/phenomic/phenomic/commit/137ca8c96b0033ac80300900e03cda7d65fb27a1),
by @MoOx, reported by @DominikGuzei (in
[#1162](https://github.com/phenomic/phenomic/issues/1162))
- [`@phenomic/plugin-renderer-react`: avoid some warnings about some props that Link component pass to a tag](https://github.com/phenomic/phenomic/commit/a83b0d113364c4074ace5c21a55a281b4a541069),
by @MoOx
## ✨ New (AWESOME) feature 🔥
- [`@phenomic/plugin-transform-markdown`: allow custom markup](https://github.com/phenomic/phenomic/commit/1bd1d2f6f15a12082d07061bdc25d46aaae1b86f),
by @MoOx, reported by @MoOx, @bherila, @daine and @jfjessup (in
[#817](https://github.com/phenomic/phenomic/issues/817) &
[#1098](https://github.com/phenomic/phenomic/issues/1098)) This plugin now use
[unified](http://unifiedjs.github.io) directly instead of
[remark](https://github.com/wooorm/remark) so we can mix remark with
[rehype](https://github.com/wooorm/rehype) to allow custom markup. This will
open up usage of custom react components when rendering markdown tree with a
custom mapping. Anchor that was present by default have been removed. We will
introduce in next release a support for custom plugin passed from the config
to add it back.
================================================
FILE: website/content/blog/2017-09-30-v1.0.0-alpha.11.md
================================================
---
title: v1.0.0 Super Alpha XI
tag_name: v1.0.0-alpha.11
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.11
author: MoOx
prerelease: true
---
## 💥 Minor breaking change
- [`@phenomic/plugin-bundler-webpack`: upgrade to webpack@^3.0.0](https://github.com/phenomic/phenomic/commit/b5a9694528293af964dc75f3525ac71d2a5d2a3b),
by @MoOx, reported (in
[#1078](https://github.com/phenomic/phenomic/issues/1078)) This should not
create you any issue and upgrade should be transparent for you.
## 🐛 Bugfix
- [`@phenomic/cli`: Use a dump babel-preset-(env|react) to cover most use case for node executed code](https://github.com/phenomic/phenomic/commit/98bdfa4d053511090dbb75a9c3a2a437d9714245),
by @MoOx, reported by @benjaminshafii, @ArthurClemens & @DominikGuzei (in
[#1170](https://github.com/phenomic/phenomic/issues/1170))
================================================
FILE: website/content/blog/2017-10-11-v1.0.0-alpha.12.md
================================================
---
title: v1.0.0-alpha.12
tag_name: v1.0.0-alpha.12
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.12
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
Only good stuff!
Notable additions & changes:
## 🔥 New plugin
- [`@phenomic/plugin-transform-asciidoc`: Create asciidoc transformer plugin using Asciidoctor.js](https://github.com/phenomic/phenomic/commit/807f296145e47a211488f09455b5162826fc4e41),
by @ezralalonde, requested by @kepinpin (in
[#1153](https://github.com/phenomic/phenomic/issues/1153))
## 🌟 New Example
**_⚠️ WARNING: This example can blow you mind as it can show you things you were
not prepared to. ⚠️_**
- [React app with custom markdown tags rendered by custom react component](https://github.com/phenomic/phenomic/commit/9631a697f54b682a9bd9fd9eb1120101e9e41279)
by @MoOx
## 🐛 Bugfixes
- [`@phenomic/reason`: Bring bsconfig.json to the npm package](https://github.com/phenomic/phenomic/commit/b388e8ad0e17733898e09ec65eeba23617728e56),
by @bloodyowl, reported by @bloodyowl (in
[#1171](https://github.com/phenomic/phenomic/issues/1171)) and @rickyvetter So
now we can use reason package without any copy/paste/hack 🙃 Note that this
package is going to be exploded as a `preset-reason` that will contains
`plugin-renderer-reason` + `plugin-renderer-reason-react` in next release.
- [`@phenomic/api-client`: correctly handle url without path (and protect path from query by id)](https://github.com/phenomic/phenomic/commit/bb2748162739faac0741637d111981bcab7569ef),
by @MoOx
## 👍 Improvements
- [`@phenomic/core`: Display a warning if no html files are generated during static build](https://github.com/phenomic/phenomic/commit/e8ffa26e65f9b353d4614e97baa891c5ec84f537),
by @MoOx, requested by @xuopled (in
[#1166](https://github.com/phenomic/phenomic/issues/1166))
- [`@phenomic/core` + `@phenomic/api-client`: Make `path` parameter for query optional](https://github.com/phenomic/phenomic/commit/c6fdb5c48daec2955f64110c53ffa85363cc0b64),
by @MoOx (in [#1173](https://github.com/phenomic/phenomic/issues/1173))
================================================
FILE: website/content/blog/2017-10-19-v1.0.0-alpha.13.md
================================================
---
title: v1.0.0-alpha.13
tag_name: v1.0.0-alpha.13
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.13
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
Main reason of this release is the scalability issue: you can now build a
website with hundreds of pages. Pre-rendering step takes around 4s for 1000
pages 😁
## 🐛 Bugfix
- [`@phenomic/core`: Fix issue when too many files are being transformed and contains undefined or null by adding a concurrency limit to hit API](https://github.com/phenomic/phenomic/commit/bc97c107aca59f46097e7b77cd6961d0f51462ea),
by @MoOx, reported by @ArthurClemens
## 👍 Improvement
- [`@phenomic/core`: Stop shallowing error from API server during static build](https://github.com/phenomic/phenomic/commit/928d67799ea36366b07784b53ef1ebbc0cc4a2d7),
by @MoOx, reported by @ArthurClemens
## ✨ New feature
- [`@phenomic/plugin-renderer-react`: expose html from `renderApp()` result](https://github.com/phenomic/phenomic/commit/24f301aca59c2ba0b368123b0304836596b3fbd2),
That allows CSS-in-JS to easily optimize (critical) CSS extraction. by @MoOx
## 🌟 New Example
- [`examples/react-app-styles-with-emotion`](https://github.com/phenomic/phenomic/commit/4855324ade822fb90c2b9b31fd0615231ac61765),
by @tgrecojs and @MoOx
## 👌 Improved Examples
- [`examples/react-app-styles-with-glamor`: critical css only](https://github.com/phenomic/phenomic/commit/561d59581a9fd3728ba65bbf505c1192fc3e4082),
by @MoOx
- [`examples/react-app-styles-with-glamorous``: critical css only](https://github.com/phenomic/phenomic/commit/2ad218202c2b43349ed4762ca79bac001a61b76e),
by @MoOx
================================================
FILE: website/content/blog/2017-12-04-v1.0.0-alpha.14.md
================================================
---
title: v1.0.0-alpha.14
tag_name: v1.0.0-alpha.14
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.14
author: MoOx
prerelease: true
---
Windows compatibility! Yeay! We can thanks [tretton37](http://tretton37.com)
that invited @MoOx to work on phenomic for an entire day with a dedicated team
of developers (including @oscar-b, @emilpalsson and many more)!
🎉 **[We can also thanks our backers](http://opencollective.com/phenomic) that
are supporting us for a while! Thanks for believing in Phenomic!**
---
## If you are a JavaScript user 🎉 No breaking changes 🎉
## If you are a ReasonML user 💥 _(minor) breaking change_ is expected 💥
---
Note that we replaced our database engine, to unlock new features in future
releases. This should not change anything for you, but if you have weird
differences or behaviors, please reach us.
---
## 💥 Breaking changes
- [`@phenomic/reason`: this plugin is deprecated](https://github.com/phenomic/phenomic/commit/4c9fb4a738ee1c26035e53d15ba8878298b9b26c)
by @MoOx You can now directly includes some packages instead of this one in
your `bsconfig.json`. See
https://github.com/phenomic/phenomic/blob/4c9fb4a738ee1c26035e53d15ba8878298b9b26c/examples/reason-react-app/bsconfig.json#L14-L16
You can remove this package from your `package.json`. Each packages should
have bs-bindings (or native reasonml code). If not, do not hesitate to open
issue or help us! Feel free to reach us on our
[chat](http://gitter.im/phenomic/phenomic) if you struggle updating.
## 🐛 Bugfixes
- [`@phenomic/plugin-collector-files`: Fix date parse from filename when using sub folders](https://github.com/phenomic/phenomic/commit/6a593daf159cc325c48d11efa10a9e19267b1bf6),
by @emilpalsson , reported by @dlindahl (in
[#1096](https://github.com/phenomic/phenomic/issues/1096))
- [`@phenomic/plugin-bundler-webpack`: Make webpack follow configured outdir](https://github.com/phenomic/phenomic/commit/0e15e24121b2dc463437b0b9684d9264abd53bb9),
by @emilpalsson
## 👍 Improvements
- `@phenomic/core`: Full windows compatibility
([433c63d](https://github.com/phenomic/phenomic/commit/433c63d723126707ba12f9f25deadf54fbbaa88c)
and
[f858688](https://github.com/phenomic/phenomic/commit/f85868832cd2ef2c096bbd71f60c6ba9f6e13c55))
- [`@phenomic/core`: Gracefully handle if port is busy when starting dev server](https://github.com/phenomic/phenomic/commit/ac792d5bba85cbf73be9d01e9a68a73b2b8d2619),
by @oscar-b, reported by @DavidWells (in
[#897](https://github.com/phenomic/phenomic/issues/897))
================================================
FILE: website/content/blog/2017-12-04-v1.0.0-alpha.15.md
================================================
---
title: v1.0.0-alpha.15
tag_name: v1.0.0-alpha.15
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.15
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
## 🐛 Bugfix
- [`@phenomic/core`: Prevent watcher from crashing when a file is renamed (or saved with vim)](https://github.com/phenomic/phenomic/commit/a132ad03d5cec522703c2b95160a0b1eaebf5d18),
by @hugmanrique, reported by @ArthurClemens (in
[#1157](https://github.com/phenomic/phenomic/issues/1157)) and @drazik (in
[#1208](https://github.com/phenomic/phenomic/issues/1208)) (#1211)
================================================
FILE: website/content/blog/2017-12-06-v1.0.0-alpha.16.md
================================================
---
title: v1.0.0-alpha.16
tag_name: v1.0.0-alpha.16
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.16
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
## 🐛 Reason fix
Ooops! We forgot to publish `bsconfig.json` files for new reason packages. Fixed
by @MoOx in
[#19746b6](https://github.com/phenomic/phenomic/commit/19746b622f69359097c28182ac709e73dfec0cd9),
reported by @Essential
================================================
FILE: website/content/blog/2017-12-06-v1.0.0-alpha.17.md
================================================
---
title: v1.0.0-alpha.17
tag_name: v1.0.0-alpha.17
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.17
author: MoOx
prerelease: true
---
# 🎉 No breaking changes 🎉
## 🐛 Reason fix, round 2
Ooops! We forgot to publish `.re` files for new reason packages. Fixed by @MoOx
in
[#e010f0f](https://github.com/phenomic/phenomic/commit/e010f0fc257dceac19f57e5bf2e938d0d2f5e1f2)
================================================
FILE: website/content/blog/2017-12-20-v1.0.0-alpha.18.md
================================================
---
title: v1.0.0-alpha.18
tag_name: v1.0.0-alpha.18
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.18
author: MoOx
prerelease: true
---
- 🐛 `@phenomic/core`: various regression to database introduced in
`v1.0.0-alpha.14` by @MoOx
* 💥
[`@phenomic/plugin-collector-files`: remove specific code for `author` field automatically associated with `authors` in the database](https://github.com/phenomic/phenomic/commit/2e2b3e17e21a51c933e4437be7e92b7eeac55778),
by @MoOx
If you were previously relying on the fact that the meta `author` from a file
was magically resolved to a possible `authors` from your database, you should
instead rely on the generic behavior that works with identical names. This means
you should change `author: "name"` to `authors: ["name"]`. This will produce the
same magic resolution when retrieving content from a single (`id` based) query.
If you really want the old behavior back, we should think about a generic
solution. So please open an issue.
================================================
FILE: website/content/blog/2018-01-11-v1.0.0-alpha.19.md
================================================
---
title: v1.0.0-alpha.19
tag_name: v1.0.0-alpha.19
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.19
author: MoOx
prerelease: true
---
# 💥 Includes _Breaking changes_ for Reason users.
This release is mostly a bunch of improvements (with a minor breaking change)
for Reason users in addition to a bugfix for an edge case.
## 💥 Breaking changes (Reason only)
- [`@phenomic/plugin-renderer-react`: (Reason) `jsEdgeToReason` is now `jsEdge`](https://github.com/phenomic/phenomic/commit/6599f41d4139c430801b44a2e043b60f29a1f4bd),
by @MoOx There is no transformation anymore. Transformation should be made in
your component. This change is accompanied with a new type to help you (see
`jsNodeList` type below). We highly recommend you to take a look to the
updated example. See below for more details.
## 🐛 Bugfixes
- [`@phenomic/core`: support query without path for prerendering as it’s supported by database](https://github.com/phenomic/phenomic/commit/a32c7dbd095ba16c703e71d30a935f5d509db81f),
by @MoOx
## ⚠️ Deprecation
- [`hasPreviousPage` & `hasNextPage` are deprecated](https://github.com/phenomic/phenomic/commit/69361b82c856f30727ec5588b098f31831be5637),
by @MoOx Please test directly the existence of `previous` and `next`. It will
continue to work for a while, but will be remove some day. _This is to make it
more straight forward to use pagination in Reason._
## 💪 Improvements
- [`@phenomic/core`: `previousPageIsFirst` now always return a value (`false` instead of `undefined`)](https://github.com/phenomic/phenomic/commit/e12b53d464c005e8bf44d66a58099f886870aff8),
by @MoOx _This is to make it more straight forward to use pagination in
Reason._
- [`@phenomic/plugin-renderer-react`: (Reason) expose `jsNodeList` type](https://github.com/phenomic/phenomic/commit/3d0f24c7e96857d614d3ae1478ce59626f2ea65a),
by @MoOx It is the type of data that comes from list queries.
## 👌 Improved Example (Reason)
@MoOx worked a lot on the `examples/reason-react-app`:
- upgrade to reason-react 0.3.1
- we switched to es6 for bs generated files
- we added pagination, like in the JavaScript example
- we added react-helmet usage (via bs-react-helmet)
- we reorganized the code and added tiny helpers
---
♥️ If you have questions, recommendations or improvements to submit, you can
reach us on our [chat](https://gitter.im/phenomic/phenomic) or via the
[issues](https://github.com/phenomic/phenomic/issues/new)
================================================
FILE: website/content/blog/2018-01-24-v1.0.0-alpha.20.md
================================================
---
title: v1.0.0-alpha.20
tag_name: v1.0.0-alpha.20
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-alpha.20
author: MoOx
prerelease: true
---
- [💥 `@phenomic/plugin-bundler-webpack`: remove react-native-web alias for react-native as latest version (0.3.x) rely on babel plugin](https://github.com/phenomic/phenomic/commit/3659957b08b1b983f902af0d4a1d93d7d54e2864),
by @MoOx
- [🐛 `@phenomic/plugin-bundler-webpack`: fix react-native-web styles prerendering issues with latest version (0.3.x))](https://github.com/phenomic/phenomic/commit/d51090852dab5dc750f4b92ceb0b0c0e4134389d),
by @MoOx
- [🐛 `@phenomic/plugin-bundler-webpack`: stop hiding user webpack issues](https://github.com/phenomic/phenomic/commit/242f6c5eac2a009dc42bcdb73b59feed8e82b64b),
by @MoOx, reported by @thangngoc89 (in
[#1216](https://github.com/phenomic/phenomic/issues/1216))
================================================
FILE: website/content/blog/2018-03-08-v1.0.0-beta.0.md
================================================
---
title: v1.0.0-beta.0
tag_name: v1.0.0-beta.0
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.0
author: MoOx
prerelease: true
---
We are on the road to final 1.0.0!
What is planned:
- We only plan to add an new generic API to fetch any kind of data (like
`async getInitialProps` in Next.js) & a few minor improvements.
- We will also soon publish a few benchmarks between some well known others
static site gen (that might reveal things…).
- We will try to add a bunch of plugins to show the world what Phenomic can
really do.
If you have any question you can ask us on
[Spectrum](https://spectrum.chat/phenomic) or on
[Gitter](https://gitter.im/MoOx/phenomic).
## Core
- [🚨 `@phenomic/core`: `dist` option is now relative to `path`](https://github.com/phenomic/phenomic/commit/24657cc6b9b85e725d25f2dd5bb82367a2956b59)
by @MoOx
- [✨ `@phenomic/core`: introduce `content` option to folder for the content](https://github.com/phenomic/phenomic/commit/24657cc6b9b85e725d25f2dd5bb82367a2956b59)
by @MoOx
- [🐛 `@phenomic/core`: correctly throw fetch error during static build](https://github.com/phenomic/phenomic/commit/141a6cbb0fa51426685e3f5ca8e4274a87f35b64)
by @MoOx
- [🐛 `@phenomic/core`: add missing API entry points for queries without path](https://github.com/phenomic/phenomic/commit/d0572d3ac6c817f64e6cb7680595e5db2e458bbd)
by @MoOx
## ReasonML
- Use bs-platform@^2.2.0
- [🐛 `@phenomic/plugin-renderer-react`: Fix jsEdge Errored state that was never in this state](https://github.com/phenomic/phenomic/commit/7efdffa78defb974d0f2ff9bbfd1cd47af7dbe23),
by @MoOx
- [🐛 `@phenomic/plugin-renderer-react`: Remove unneeded div around bodyRenderer](https://github.com/phenomic/phenomic/commit/9c6fb6627cb6b075267f367b0a0d3541975da38d),
by @ulrikstrid
- [🐛 `@phenomic/plugin-renderer-react`: (reason) Fix return type for query builder](https://github.com/phenomic/phenomic/commit/a54a78e1dfa7a6138a488103ded6816891f8ed90),
by @bloodyowl, reported by @ulrikstrid (in
[#1230](https://github.com/phenomic/phenomic/pull/1230))
- [✨ `examples/reason-react-app`: handle error pages](https://github.com/phenomic/phenomic/commit/b0f585622dd6eec1d553d6545cd2ee0716d504f5),
by @MoOx
## Website
- Remove sites in the showcase that were not using Phenomic anymore (or where
unavailable). We used a script to detect Phenomic on those website that we
will run periodically. by @MoOx
- Move the website from `docs` to `website` folder, more clear for contributors
by @MoOx
- Add a link to our new [Spectrum community](https://spectrum.chat/phenomic) (by
@mxstbr)
- Add favicons & friends
## Internal
- Migration to Circle CI 2.0
- Readme update
- PNGs logo added into git repo (previously only sketch & svgs were available)
================================================
FILE: website/content/blog/2018-03-30-v1.0.0-beta.1.md
================================================
---
title: v1.0.0-beta.1
tag_name: v1.0.0-beta.1
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.1
author: MoOx
prerelease: true
---
This release might include breaking changes for you.
This is one of the final step before stable 1.0.0! The breaking changes included
in this release are for the best. We have worked hard so you can be able to use
simple options for plugins, exactly like babel. More on this below.
**If you use `@phenomic/preset-react-app` without any customisation, you are
probably all good**
- Just be careful if you where using JSON
- If you code was working without any warning, you don’t have anything to do
except looking for `hasNextPage` & `hasPreviousPage`. If you were still using
those, just replace your test with the presence of next`or`previous` directly.
**If your are using custom plugins, you will have to update some signatures.**
## 🚨Breaking changes
[🚨 Remove deprecated attributes for pagination and routes](https://github.com/phenomic/phenomic/commit/fe68e8c94db3054d68582f4cbb68b86e63eb6b2c)
by @MoOx
[🐛 🚨 `@phenomic/plugin-transform-json`: support array by passing all js on as data (+use a partial version is accessible)](https://github.com/phenomic/phenomic/commit/84e3abd928779a734779e1b6a61eb9006cb28e05)
by @MoOx
Previously, using JSON files that were array was broken. We were spreading JSON
like if it was an object. We adjusted the behavior that might affect `partial`
(when you fetch list via queries) if you had a "partial" entry in your JSON
(edge case). Reach us on our community tools if you struggle updating.
[🚨 `@phenomic/plugin-transform-markdown`: upgrade to gray-matter@3](https://github.com/phenomic/phenomic/commit/cba0e43521c98d7bf789e7bf472abb141c1f84e1)
by @MoOx
If you are using something else than JSON, YAML of JavaScript in your
front-matter, please open an issue so we can improve the situation so we can
work on allowing `engine` option
https://www.npmjs.com/package/gray-matter#optionsengines
[🚨 `@phenomic/core`: `collect` method for plugin should now be `collectFile`.](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
[🚨 `@phenomic/core`: many plugin methods have their signature that have been updated](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
Please check flow definitions until docs is online (major change is that config
is not send since plugin receive it when it's created). All signatures for
plugin have been adjusted. Please take a look if you are a plugin author. See
https://github.com/phenomic/phenomic/blob/954fbe16f20a51af90cbd6a25502da1426e4bdc5/flow-typed/phenomic.js#L159-L202
## ✨ New features and improvements
[✨ `@phenomic/*`: we can now configure every plugins from phenomic config.](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
See last item of this list to see an example ;)
[✨ `@phenomic/core`: support `baseUrl` option in configuration](https://github.com/phenomic/phenomic/commit/edfefa9488c656a21a01d7c691bd9629de975449)
by @MoOx
You can now send a baseUrl in phenomic configuration. This allow website to work
at a folder level of a domain (eg: http://domain.tld/root/).
```json
{
"baseUrl": "http://mydomain.com/root-of-my-site/“,
"presets": ["@phenomic/preset-react-app"]
}
```
**Note that this will directly be reflected during development for your mental
health! This means you will have to open
`http://localhost:3333/root-of-my-site/`**
[✨ `@phenomic/core`: support .env(.\_)? files for PHENOMIC\_\_ env vars](https://github.com/phenomic/phenomic/commit/62378ca14bc87365b5b2b0448254b64acdce1944)
by @MoOx
Like CRA support `REACT_APP_*` env var to be passed over to your JavaScript
during compilation, you will have access to `PHENOMIC_*` var that you can define
from .env files. We are using https://github.com/motdotla/dotenv hunder the
hood.
[✨ `@phenomic/core`: we added a new plugin api so any plugin can add static or dynamic url on runtime (`resolveURLs`)](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
[✨ `@phenomic/core`: `renderStatic` is now not limited to a single plugin. Multiples plugins (those that have a `resolveURLs` can now render static files).](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
[✨ `@phenomic/api-client`: `import fetchRestApi from "@phenomic/api-client/lib/fetch";` to fetch phenomic api directly.](https://github.com/phenomic/phenomic/commit/2d2f806cfee35aa6fa21d88ba5465bb37dad8119)
by @MoOx
This method is mostly for plugin developers. Calling this method should be made
with `import query from "@phenomic/api-client/lib/query”;`. Be careful to use
this method wisely as it won’t be magically pre-rendered for all end point
unless a plugin handle the static rendering of the resource.
[✨ `@phenomic/plugin-bundler-webpack`: respect `baseUrl` option](https://github.com/phenomic/phenomic/commit/edfefa9488c656a21a01d7c691bd9629de975449)
by @MoOx
[✨ `@phenomic/plugin-bundler-webpack`: inject NODE*ENV + PHENOMIC*\* env var (PHENOMIC_ENV & PHENOMIC_APP_BASENAME for now)](https://github.com/phenomic/phenomic/commit/edfefa9488c656a21a01d7c691bd9629de975449)
by @MoOx
[✨ `@phenomic/plugin-renderer-react`: expose enhanced Link component that respect `baseUrl` option](https://github.com/phenomic/phenomic/commit/edfefa9488c656a21a01d7c691bd9629de975449)
by @MoOx
[✨ `@phenomic/plugin-rss-feed`: this is now a thing and can generate multiples feed](https://github.com/phenomic/phenomic/commit/4584963559c0ef9e71612e709b14b9006085ffed)
by @MoOx
Example of the config for Phenomic website
```json
{
"baseUrl": "http://phenomic.io/",
"presets": ["@phenomic/preset-react-app"],
"plugins": [
[
"@phenomic/plugin-rss-feed",
{
"feeds": {
"feed.xml": {
"feedOptions": {
"title": "Phenomic.io",
"description": "Phenomic news"
},
"query": { "path": "news", "limit": 20 }
}
}
}
]
]
}
```
📝 Various minor docs improvements by @getDanArias
================================================
FILE: website/content/blog/2018-04-07-v1.0.0-beta.2.md
================================================
---
title: 1.0.0-beta.2
tag_name: v1.0.0-beta.2
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.2
author: MoOx
prerelease: true
---
# Stable 1.0.0, we are almost there!
This release is probably the penultimate before the stable release. It brings us
2 majors things:
- 🎉 For React users, 2 methods, supported via the new `withInitialProps` HOC,
allows you to consume any kind of data (not just Phenomic API but any kind of
REST APIs, GraphQL APIs for CMS etc) via `static async getInitialProps()`.
This API, inspired by Next.js is not alone as it comes with another new method
for the pre-rendering step, called `static async getAllPossibleUrls()`.
- 💪 We adjusted 2 transform plugins (markdown and asciidoc) so you can directly
pass to those the [unified](https://unifiedjs.github.io) plugins you want to
use.
This release is an important step for us as it brings us our missing pieces to
be happy with Phenomic current state. Stay tuned for the final release, that
will be done at the same time as we will publish documentations on the website.
🤩 We also created a new
[react-app-blog](https://github.com/phenomic/phenomic/tree/master/examples/react-app-blog)
example that you can use as a good starting point to create any site (not only a
blog - and we plan to push more examples when we will hit stable 1.0.0). This
starter includes some pages, some posts, and the usage of our new fresh API to
create pages from github data (but you can just use this and replace with any
kind of API) to generate client side and static generated pages from those data!
For the architecture, we used something simple, with a few components for
header/footer with differents layouts etc. We also included a standard error
page (used for 404). For the styling, we didn't wanted to do something too
opinionated and also something too old school (CSS in dedicated files since we
all love CSS-in-JS), so we took an simple approach in the middle, with a CSS
style tags per components. This allows CSS lover to just extract the CSS in
files, and CSS-in-JS lovers to easily convert in places the styles. Remember
that we have
[plenty of examples to know how to handle CSS via any kind of solutions](https://github.com/phenomic/phenomic/tree/master/examples).
You will find a visual preview at the end of this post.
## Details
[⚠️ `@phenomic/plugin-renderer-react`: `createContainer` is now `withPhenomicApi`(you will get a warning until you update your import)](https://github.com/phenomic/phenomic/commit/a4e12968f9d8d871e82e24d14c5b11cd4d1b6f59)
by @MoOx Not a breaking change yet, but will be during stable 1.0.0 release.
[🐛 `@phenomic/plugin-collector-files`: fix edge case when you request an index file with an id (db was not correctly filled)](https://github.com/phenomic/phenomic/commit/a8648fcf5de98d21024d5853f56b7f9cdf08859f)
by @MoOx
[🐛 `@phenomic/core`: fix edge case when you request an empty id (for `index`)](https://github.com/phenomic/phenomic/commit/17f830a6a4a35956ec67d665b9e6036932c2bb70)
by @MoOx
[🐛 `@phenomic/core`: fix time log between pre-rendering and after build hook](https://github.com/phenomic/phenomic/commit/4888896f4614e2cf45130358adde771ccd1dbf5e)
by @MoOx
[🐛 `@phenomic/plugin-transform-markdown`: code is now highlighted without failing if language is not recognized](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[🚨`@phenomic/plugin-transform-markdown`: remark/rehype plugins order have been changed a bit](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx This should only affect you if you were relying on (previously broken)
code highlight.
[🚨/✨ `@phenomic/plugin-transform-asciidoc`: plugin have been update to work like markdown.](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx Previously we never tested this plugin on a real project so we are not
sure it has ever worked correctly 😁.
[✨ `@phenomic/plugin-transform-markdown`: you can now specifiy options for highlighting language unsupported by default](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/plugin-transform-markdown`: you can now choose between json/html mode for the rendering via `output` option](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/plugin-transform-markdown`: new `plugins` option to replace unified/remark/rehype plugins](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/plugin-transform-asciidoc`: you can now choose between json/html mode for the rendering via `output` option](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/plugin-transform-asciidoc`: new `plugins` option to replace unified/remark/rehype plugins](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/helpers-transform`: new package that exposes stuff shared across transform plugin](https://github.com/phenomic/phenomic/commit/dd24918679b4acb5316b261bf3e032f8f305263c)
by @MoOx
[✨ `@phenomic/plugin-renderer-react`: `withInitialProps` HOC that supports `static async getInitialProps({pathname, params})` and `static async getAllPossibleUrls({path})`](https://github.com/phenomic/phenomic/commit/a4e12968f9d8d871e82e24d14c5b11cd4d1b6f59)
by @MoOx This allows to generate pages with any source of data (fetch from any
kind of REST, Grapql APIs). Inspired by Next.js.\
You can check our [example of usage in our react-app-blog example](https://github.com/phenomic/phenomic/commit/955abe1bf398109188587f2f30395352cdb7fb2a#diff-bd62372cd295cbc2187ac3152a4745bcR24)
[✨ `@phenomic/plugin-renderer-react`: `withPhenomicApi` HOC (previously named `createContainer`)](https://github.com/phenomic/phenomic/commit/a4e12968f9d8d871e82e24d14c5b11cd4d1b6f59)
by @MoOx
[🎉 examples/react-app-blog: a sweet starter to discover phenomic with react and make a blog in a few minutes](https://github.com/phenomic/phenomic/commit/4e52d7c409c422d01856af24b9845c2cb4ee621c)
by @MoOx
## Preview of the homepage of the new react-app-blog example
[](https://github.com/phenomic/phenomic/tree/master/examples/react-app-blog)
================================================
FILE: website/content/blog/2018-05-22-v1.0.0-beta.3.md
================================================
---
title: 1.0.0-beta.3
tag_name: v1.0.0-beta.3
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.3
author: MoOx
prerelease: true
---
# Hopefully, the last beta
We are very close to our final and stable release for v1. Why we didn't ship
this version already? Some people like to move fast & break things. But we
wanted to have a correct design for the v1 so future majors version won't break
too much things.
What we did for v0.x was an experiment and we learned a lot of things by running
this in production on moderate websites. We have spent a lot of brain energy to
make a scalable & flexible solution with a small API surface.
We have designed an architecture that follow React way of thinking, by offering
a [centralized lifecycle](/en/packages/core/docs/writing-plugins/). With that in
mind we have adjusted our goal and make React & Webpack, 2 core pieces of v0.x,
first class plugins in our v1.x. This opens up lot of nice things to support
React or Webpack alternatives.
## Documentation is a work in progress 🎉
First thing to celebrate, we started to work on our website! You can now find
[documentation for the core](/en/packages/core/docs/) and the
[react preset tutorial](/en/packages/preset-react-app/docs/)! More things will
follow!
## 2 small breaking changes
Below you will find 2 small breaking changes, **very easy to adjust** (that will
probably consist of adding `content` in front of all your current existing query
to our content api or to adjust your configuration).
[🚨 `@phenomic/core`: `content` options now supports multiples entries and globs ](https://github.com/phenomic/phenomic/commit/05ef940603981bb9971b02234a31e601d29067f7)
(+
[fixup](https://github.com/phenomic/phenomic/commit/c79b572fa9c54cf88419dac1f6367e3cd5a5c0ef))
by @MoOx
**All your previous queries won't work with this breaking change** but don't
worry, it's very easy to adjust your code.
We are sorry to add a breaking change now, but it's for the better.
**Solution 1 (recommended)**: You will have to add "content/" in front of all
your `path` in your queries. Why? It's for being more explicit and also be able
to support multiples sources (multiples folders) to avoid duplicate names
without a weird configuration. The upgrade is pretty easy.
For example
```js
const HomeContainer = withPhenomicApi(Home, props => ({
posts: query({
path: "posts",
}),
}));
```
Will become
```js
const HomeContainer = withPhenomicApi(Home, props => ({
posts: query({
path: "content/posts",
}),
}));
```
**Solution 2 (for lazy people)**: You can keep the previous behavior very easily
by using this value for `content` option:
`"": {root: "content", globs: ["**/*"]}`. You can throw that in your
`package.json` in a `phenomic` like this:
```json
"phenomic": {
"content": {
"": {root: "content", globs: ["**/*"]}
},
"presets": ["@phenomic/preset-react-app"]
}
```
[🚨 `@phenomic/plugin-rss-feed`: now lookup in `content/posts` by default. ](https://github.com/phenomic/phenomic/commit/05ef940603981bb9971b02234a31e601d29067f7)
by @MoOx
To get previous behavior back, just use this configuration (adjust to match
yours):
```json
"phenomic": {
"presets": ["@phenomic/preset-react-app"],
"plugins": [
[
"@phenomic/plugin-rss-feed",
{
"feeds": {
"feed.xml": {
"query": {
"path": "content/posts"
}
}
}
}
]
]
},
```
## Bugfixes
[🐛 `@phenomic/plugin-renderer-react`: Handle scroll like it should (to top or to the hash if any) ](https://github.com/phenomic/phenomic/commit/d4824c531073e31fa1b74f45bbdaf7db1ba642e3)
by @MoOx
[🐛`phenomic/plugin-collector-files`: correctly clean extensions from filename for id (not only md|json but all extensions by the plugin loaded at runtime) ](https://github.com/phenomic/phenomic/commit/b924d0bca097ba31e9f38c0c0a35c68fa98865ae)
by @MoOx
## Tons of small improvements
As we started to actively working on our documentation, we have added tons of
small improvements.
[✨ `@phenomic/plugin-renderer-react`: add render + callback option to createApp/renderApp for custom rendering ](https://github.com/phenomic/phenomic/commit/ce083d92f7abced22dbc8a2884649a92f47cdf41)
by @MoOx
This commit allows you to use a custom render() function. This way to render the
app is required by some solutions that needs a custom wrapper for styles
pre-rendering (eg: react-native-web).
[🎉 examples/react-native-web-app ](https://github.com/phenomic/phenomic/commit/dd9d19f6e3a5dba60e7262311c8eb060d8661070)
by @MoOx
[✨ `@phenomic/core`: add socketPort option (and switch to 3334 since 1415 can be used by dbstar) ](https://github.com/phenomic/phenomic/commit/645c89977f955b619c7bb9018f08f0d3259a379a)
by @MoOx
[✨`@phenomic/core`: Improve error shown from database access ](https://github.com/phenomic/phenomic/commit/4df49e34e6eeef33e0676f5293933d67db8daa3c)
by @MoOx
[✨ `@phenomic/core`: Improve error message from database not found entry ](https://github.com/phenomic/phenomic/commit/fc729aa0dee61d2fc81b5b294f583f705bf40bf6)
by @MoOx
[🔥 Add a new helper to extract meta from body nodes (title + headings list) ](https://github.com/phenomic/phenomic/commit/da0d4da4d5a39c865dd68d78a14ee3533adcb943)
(+
[fixup](https://github.com/phenomic/phenomic/commit/1b68eff0c6a0e299da3e3c7a9c897cc4338525aa))
by @MoOx
This helper is used in `@phenomic/plugin-transform-markdown` and
`@phenomic/plugin-transform-asciidoc` to **automatically add a `title` meta**
even if you don't have frontmatter. Pretty cool for files that you don't
control. This helper also returns a list of headings in your content, which is
pretty convenient to make a **table of content** at the top of you page or in a
sidebar.
[✨ `@phenomic/plugin-transform-markdown`: add title fallback extracted from markdown body if no title is in the frontmatter + add a list of markdown headings ](https://github.com/phenomic/phenomic/commit/3f35a51dc09f5a00cb2ad3d268d820563addbcab)
(+
[fixup](https://github.com/phenomic/phenomic/commit/1b68eff0c6a0e299da3e3c7a9c897cc4338525aa))
by @MoOx
[✨ `@phenomic/plugin-transform-asciidoc`: add title fallback extracted from markdown body if no title is in the frontmatter + add a list of markdown headings ](https://github.com/phenomic/phenomic/commit/3f35a51dc09f5a00cb2ad3d268d820563addbcab)
(+
[fixup](https://github.com/phenomic/phenomic/commit/1b68eff0c6a0e299da3e3c7a9c897cc4338525aa))
by @MoOx
[✨ `@phenomic/plugin-transform-json`: add title fallback ](https://github.com/phenomic/phenomic/commit/3f35a51dc09f5a00cb2ad3d268d820563addbcab)
by @MoOx
[✨ `@phenomic/core`: better display in case of error during start/build ](https://github.com/phenomic/phenomic/commit/ef32bb098a9a561aa483d2267a355c20f3a69beb)
by @MoOx
[✨ `@phenomic/core`: add options to sort db results ](https://github.com/phenomic/phenomic/commit/a1f869ab5669083073dcdb310a1c86bfa87b213b)
by @MoOx
This feature is pretty awesome and allows you to add custom order to your query.
As a good example, we wanted to sort our showcase with the following algorithm:
- Sites with a flag `curated` first
- Sites with many tags
- Sites with tags "blog" at the end.
In order to do so, we have introduced this option and we hope you will like it.
You can check out the
[documentation for `db.sortFunctions`](/en/packages/core/docs/configuration/#dbsortfunctions)
and take a look to the
[one we use for the showcase](https://github.com/phenomic/phenomic/blob/801c2ad9720cb17cb599597f0dc1e020e1b581b9/website/phenomic.config.js#L32-L52).
[✨ `@phenomic/cli`: add preview command ](https://github.com/phenomic/phenomic/commit/88c10b94c26830b2c2397da2fc2477f6175e5626)
by @MoOx
[✨ `@phenomic/core`: add preview command to build & serve results ](https://github.com/phenomic/phenomic/commit/c2e0ecc9c7d6d75b4817eb7551dc690e4280081f)
by @MoOx
Now you can run
```console
phenomic preview
```
This will build and serve the website, to mimic production (as you will have the
pre-rendered files and the client side reconciliation).
================================================
FILE: website/content/blog/2018-10-27-v1.0.0-beta.4.md
================================================
---
title: 1.0.0-beta.4
tag_name: v1.0.0-beta.4
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.4
author: MoOx
prerelease: true
---
This is a minor beta that only brings the following:
- Add `PHENOMIC_APP_BASEURL` env variable (entire `baseUrl` option as a string)
(in
[3799fa8](https://github.com/phenomic/phenomic/commit/3799fa8571c7162d92b724a1dcb5d4aade009dde)
by @MoOx)
- `@phenomic/plugin-rss-feed`: fail with a http 500 if rss feed fail to be
generated (in
[26c8d95](https://github.com/phenomic/phenomic/commit/26c8d959625a51d030859e0bbb8d991cb4301079)
by @MoOx)
- `@phenomic/plugin-bundler-webpack`: Make root for App.js configurable (in
[78ecd47](https://github.com/phenomic/phenomic/commit/78ecd47dda0fa0d9ed586c3054a82c5df3bb9577)
by @airtonix)
- `@phenomic/plugin-renderer-react`: fix issues with class attributes (coming
from markdown) (in
[927aea2](https://github.com/phenomic/phenomic/commit/927aea249c8b279fd178dc9b5aa2a809e83c7151)
by @MoOx)
- Internal refactoring by @MoOx
Website has been a WIP for a few month now, mostly due to a break @MoOx took
from his keyboard.
Stable 1.0.0 is missing a change for the database engine that is currently
causing performance issues _during development_ as soon as you get a hundred of
pages. All efforts are currently on this improvement.
## For Reason users
- Upgrade `bs-platform` to 4.x and `reason-react` to 0.5.x (in
[6067bc9](https://github.com/phenomic/phenomic/commit/6067bc9c94b0cc525829739d5cb9c8076cdc4599),
[1e4de9a](https://github.com/phenomic/phenomic/commit/1e4de9ad1e126854e0c5e1908da42635ae80768b)
and
[086c0af](https://github.com/phenomic/phenomic/commit/086c0aff5ded9466210560708bd20e000c1e02bb)
by @MoOx)
================================================
FILE: website/content/blog/2018-11-26-v1.0.0-beta.5.md
================================================
---
title: 1.0.0-beta.5
tag_name: v1.0.0-beta.5
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.5
author: MoOx
prerelease: true
---
🚨
[We upgraded webpack from v3 to v4](https://github.com/phenomic/phenomic/commit/7405e56f1dfa0bd404bcbfcc64d0bb5c9fa8a680).
So this release might be a breaking change if you use a custom webpack. If you
use webpack without custom config, you should not have any problem. Note that
you could still use v3 webpack plugin if you don’t rely on the react-app preset
and specifying the webpack beta.3 plugin version.
⚠️
[We removed react-hot-loader](https://github.com/phenomic/phenomic/commit/e268c6adf3851d785b507f6588175d81af4720c6)
We decided to do, like CRA & Next.js, to not include react-hot-loader for now.
Previous version of phenomic could create infinite loop in case of an error in a
react component…. It’s not stable enough & it’s not going to be better in the
future, when React hooks will land as a stable feature.
---
Beside this small update, we are working on a react + reason + graphql example
😋 and also a huge improvement on the content API!
================================================
FILE: website/content/blog/2018-12-08-v1.0.0-beta.6.md
================================================
---
title: 1.0.0-beta.6
tag_name: v1.0.0-beta.6
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.6
author: MoOx
prerelease: true
---
## Erratum
Check out [beta.7](../v1.0.0-beta.7/) which includes bugfixes related to this
release.
## 🚨 Breaking change
- [Upgrade from babel 6 to babel 7](https://github.com/phenomic/phenomic/commit/bb0ce41b4fde26fbe4230601f3c39a6a442e873e)
([+fixup](https://github.com/phenomic/phenomic/commit/09525f2058788030132026050a7cf55cab61527a)).
⚠️ If you were using phenomic without any custom babel config, this update
should be transparent for you.
- Reason users: you will night to replace `*.js` by `*.bs.js` for some files Eg:
`import { createContainer } from "@phenomic/preset-react-app/lib/es6/src/phenomicPresetReactApp.js";`
to
`import { createContainer } from "@phenomic/preset-react-app/lib/es6/src/phenomicPresetReactApp.bs.js";`
## 😋 Fixes
- [plugin-bundler-webpack: Fix: Add apollo support (defined as external dependency to avoid SSR issues with in memory cache)](https://github.com/phenomic/phenomic/commit/7b7afcb797ea4c991cfed0bc71f9afa8b218afa4)
- [plugin-renderer-react: Fix: provide same props for getInitialProps during SSR and CSR (pathname+params)](https://github.com/phenomic/phenomic/commit/b4fb5d826dc23a282a7eb82674c8f0fd13da8320).
We previously send too many props during SSR to `getInitialProps()`, different
from CSR)
- [plugin-renderer-react: fix issue with "class" prop generated from markdown in BodyRenderer](https://github.com/phenomic/phenomic/commit/80157cb0d443667adf8db6372b9143b844756e03)
## 👍 Improvements
- [core: Failing URLs during static pre-rendering do not crash the entire build anymore](https://github.com/phenomic/phenomic/commit/cd75f861db108a5e37a8a6f45b1d2ae7a2fc0f11)
- [core: Better error reporting about errors like `window is not defined` during static build with a tip on how to fix it](https://github.com/phenomic/phenomic/commit/94ae4f71b1dfbc7f335c2253b022ec6562ca9707)
- [core: CLI output is now more sweet](https://github.com/phenomic/phenomic/commit/9656d92de1a8a7c469e62a2931c70df0e8cca2a5).
Here is a before/after.

- [core: avoid deprecated Buffer warning](https://github.com/phenomic/phenomic/commit/22ff8f904443b42c4b861a587fab0b7db134aa88)
- [plugin-bundler-webpack: Hide annoying warning `Critical dependency: the request of a dependency is an expression`](https://github.com/phenomic/phenomic/commit/931f60f157fb6f7e926b80639a1550bdb779e00a)
- [plugin-bunder-webpack: errors/warnings are now rendered using native webpack output](https://github.com/phenomic/phenomic/commit/73399f13c06f132a123735b25274b8009efdb3f5)
- [plugin-bundler-webpack: development mode is now showing "minimal" output by default](https://github.com/phenomic/phenomic/commit/389346045df23b216f81ed5ca17b5bb6c83e9af8)
- [plugin-bundler-webpack: cache is now enabled for babel-loader](https://github.com/phenomic/phenomic/commit/31530cdc8980adb667357198d9df1472da2f7784)
- [plugin-bundler-webpack: allow config to be exported as es6 (export default)](https://github.com/phenomic/phenomic/commit/629fd542b6b17ff3aaefe3bd1de346b472e156b0)
## 🥳 Internal
- Refactoring of webpack bundler plugin in order to prepare future SSR rendering
enabled in dev mode
- Reason code (generated as javascript) used in the core codebase (experimental)
- Multiple other minors improvements...
================================================
FILE: website/content/blog/2018-12-09-v1.0.0-beta.7.md
================================================
---
title: 1.0.0-beta.7
tag_name: v1.0.0-beta.7
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.7
author: MoOx
prerelease: true
---
Quick release for issues related with beta.6
## 💥 Fixes
- [plugin-bundler-webpack: Add missing `@babel/core` dependency](https://github.com/phenomic/phenomic/commit/ebc95abeb0f6ff1f61795a66708d0a68dc429819)
- [babel-preset: fix config to work even in non-static or non production](https://github.com/phenomic/phenomic/commit/c3d16873daec4349ddc76d8a688affcdc91d507a)
================================================
FILE: website/content/blog/2018-12-20-v1.0.0-beta.8.md
================================================
---
title: 1.0.0-beta.8
tag_name: v1.0.0-beta.8
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.8
author: MoOx
prerelease: true
---
Minor update to provide some fixes:
- [@phenomic/plugin-bundler-webpack: (fix) put "react-native" as external, like react-native-web](https://github.com/phenomic/phenomic/commit/cc22c5d856905104ba15ee56ab74e54051dd6a12)
- [@phenomic/cli: Add missing peer dep](https://github.com/phenomic/phenomic/commit/7885367d5301aa539dc33e51e8a2be7c5c5cef70)
- [@phenomic/core: remove "bs-platform" as a core dependency](https://github.com/phenomic/phenomic/commit/31f52bf165838fc60f2c929c4f2f608d06c21d81)
================================================
FILE: website/content/blog/2019-01-18-v10.0-beta.9.md
================================================
---
title: 1.0.0-beta.9
tag_name: v1.0.0-beta.9
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.9
author: MoOx
prerelease: true
---
## 💥 (Minor) Changes
- [`@phenomic/plugin-transform-markdown`: stop converting `tags` case automatically](https://github.com/phenomic/phenomic/commit/6bd15881c200d8305120f03a1675a1cc10dbd497)
- [`@phenomic/plugin-transform-asciidoc`: stop converting `tags` case automatically](https://github.com/phenomic/phenomic/commit/ce0d3f92129f8e11bc088e162255b016bfcd2328)
## 💪 Fixes
- [`@phenomic/plugin-collector-files`: fix "draft skipped for production" feature](https://github.com/phenomic/phenomic/commit/81768df67c1718ba2e5ea89e760cbedc52277472)
================================================
FILE: website/content/blog/2019-03-15-v1.0.0-beta.10.md
================================================
---
title: 1.0.0-beta.10
tag_name: v1.0.0-beta.10
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.10
author: MoOx
prerelease: true
---
Minor release to add support for
[React Hooks](https://reactjs.org/docs/hooks-intro.html)!
## 💪 Fixes
- [`@phenomic/plugin-renderer-react`: Add support for react hooks](https://github.com/phenomic/phenomic/commit/cccee0e9)
by @MoOx
- [`@phenomic/plugin-transform-asciidoc`: Remove unused imports](https://github.com/phenomic/phenomic/commit/dc1513a8)
by @DanielRuf
- [`@phenomic/plugin-transform-asciidoc`: fix tags spacing according to markdown behavior, for consitency accross format](https://github.com/phenomic/phenomic/commit/03d8a769)
by @MoOx
- various minor docs improvements by @MoOx, @drazik & @nalanirojas25
================================================
FILE: website/content/blog/2019-03-24-v1.0.0-beta.11.md
================================================
---
title: 1.0.0-beta.11
tag_name: v1.0.0-beta.11
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0-beta.11
author: MoOx
prerelease: true
---
## 💪 Fixes
- [`@phenomic/plugin-bundler-webpack`: Fix Styled components FOUC with v4](https://github.com/phenomic/phenomic/commit/1cf635b)
by @Jokinen
- Internals changes to ensure bs-platform 5 compatibility by @MoOx
================================================
FILE: website/content/blog/2019-05-28-v1.0.0
================================================
---
title: 1.0.0
tag_name: v1.0.0
link: https://github.com/phenomic/phenomic/releases/tag/v1.0.0
author: MoOx
prerelease: true
---
Without noize, 1.0.0 is out.
## 💥 Reason User Change
- [`@phenomic/plugin-renderer-react`: Update ReasonReact JSX to version 3](https://github.com/phenomic/phenomic/commit/b3f49c4)
by @arecvlohe
================================================
FILE: website/content/showcase/entry/anthonydugois.com__polynomic.md
================================================
---
title: Polynomic
url: http://anthonydugois.com/polynomic/
source: https://github.com/anthonydugois/polynomic
showcaseTags:
- docs
- open-source
---
================================================
FILE: website/content/showcase/entry/ced.photo.md
================================================
---
title: CeD photo
url: https://www.ced.photo
source: https://github.com/xuopled/ced.photo
showcaseTags:
- blog
- business
---
Ced.photo is a portfolio of a french passionate photographer and videomaker.
================================================
FILE: website/content/showcase/entry/cpp.daynhauhoc.com.md
================================================
---
title: Learn C++ (Vietnamese)
url: http://cpp.daynhauhoc.com/
source: https://github.com/thangngoc89/dnh-cpp/
showcaseTags:
- learning
---
================================================
FILE: website/content/showcase/entry/cssnano.co.md
================================================
---
title: cssnano
url: http://cssnano.co/
source: https://github.com/ben-eb/cssnano/tree/master/docs
showcaseTags:
- docs
- open-source
---
================================================
FILE: website/content/showcase/entry/duxxie.nl.md
================================================
---
title: Duxxie
url: https://duxxie.nl
showcaseTags:
- business
- multi-languages
---
================================================
FILE: website/content/showcase/entry/haywirez.com.md
================================================
---
title: Haywirez
url: https://haywirez.com
showcaseTags:
- blog
- learning
---
Uses a custom markdown parser to render react components in posts.
================================================
FILE: website/content/showcase/entry/istanbul.js.org.md
================================================
---
title: Istanbul JS
url: http://istanbul.js.org/
source: https://github.com/istanbuljs/istanbuljs.github.io
showcaseTags:
- docs
- open-source
---
================================================
FILE: website/content/showcase/entry/kevin940726.github.io.md
================================================
---
title: Kai Hao
url: https://kevin940726.github.io
source: https://github.com/kevin940726/kevin940726.github.io
showcaseTags:
- blog
---
================================================
FILE: website/content/showcase/entry/khoanguyen.me.md
================================================
---
title: Khoa Nguyen's Blog
url: https://khoanguyen.me/
source: https://github.com/thangngoc89/blog
showcaseTags:
- blog
---
================================================
FILE: website/content/showcase/entry/meetfranz.com.md
================================================
---
title: Franz
url: https://meetfranz.com
showcaseTags:
- docs
- community
- open-source
- business
---
================================================
FILE: website/content/showcase/entry/nhakhoaphuocbinh.com.md
================================================
---
title: Phước Bình Dental Clinic
url: https://nhakhoaphuocbinh.com/
source: https://github.com/thangngoc89/nhakhoaphuocbinh
showcaseTags:
- business
---
================================================
FILE: website/content/showcase/entry/postcss.org.md
================================================
---
title: PostCSS
url: http://postcss.org/
source: https://github.com/postcss/postcss.org
showcaseTags:
- docs
- open-source
---
================================================
FILE: website/content/showcase/entry/putaindecode.io.md
================================================
---
title: Putain de code !
url: http://putaindecode.io/
source: https://github.com/putaindecode/putaindecode.io
showcaseTags:
- open-source
- community
- learning
- multi-languages
---
================================================
FILE: website/content/showcase/entry/slashgear.github.io.md
================================================
---
title: Slashgear Blog
url: https://slashgear.github.io
showcaseTags:
- blog
---
================================================
FILE: website/content/showcase/entry/stylelint.io.md
================================================
---
title: Stylelint
url: http://stylelint.io/
source: https://github.com/stylelint/stylelint.io
showcaseTags:
- docs
- open-source
---
================================================
FILE: website/content/showcase/entry/www.acrowithbrian.com.md
================================================
---
title: Brian Cruikshank Acro
url: https://www.acrowithbrian.com/
source: https://github.com/brianrc/acrowithbrian-site
showcaseTags:
- event
- blog
- learning
- business
---
================================================
FILE: website/content/showcase/entry/www.asimkt.com.md
================================================
---
title: Asim K T Portfolio
url: https://www.asimkt.com/
source: https://github.com/asimkt/portfolio
showcaseTags:
- blog
---
Portfolio site of Asim K T, A front end developer from Bangalore, India. An open
source, sleek and simple design with minimal colors.
================================================
FILE: website/content/showcase/entry/www.boscnegre-vacances.com.md
================================================
---
title: Bosc Nègre Vacances
url: https://www.boscnegre-vacances.com
source: https://github.com/boscnegre-vacances/boscnegre-vacances.github.io
showcaseTags:
- blog
- business
- multi-languages
---
Official wesite of Bosc-Nègre, an holiday village with 23 charming cottages in
the "Perigord Noir". (Dordogne, France)
================================================
FILE: website/content/showcase/entry/www.codepreneur.io.md
================================================
---
title: codepreneur.io
url: https://www.codepreneur.io/
source: https://github.com/codepreneur/site
showcaseTags:
- blog
---
================================================
FILE: website/content/showcase/submit.md
================================================
---
title: Submit a website/app made with Phenomic to the Showcase
---
To submit your site, you just need to
[create a text file](https://github.com/phenomic/phenomic/new/master/website/content/showcase/entry/).
🚀 Screenshots will be taken automatically!
You should be able to submit this file as a
[pull request](https://help.github.com/articles/creating-a-pull-request/) via
GitHub interface.
Please name the file as the domain of you website. If your website is in a
folder, replace `/` by 2 underscores (`__`).
Eg:
- `http://some.where/` => `some.where.md`
- `https://www.somewhere.else/` => `www.somewhere.else.md`
- `https://www.somewhere.else/right/here` =>
`www.somewhere.else__right__here.md`
For the content of the file, you must use the following format:
```md
---
title: My super title
url: http://url-of-the-website/app
source: https://github.com/url/of-the-source-(optional-if-relevant)
showcaseTags:
- docs
- community
- open-source
- event
- blog
- learning
- business
- multi-languages
- # Choose what you need in that list only! Ask on our chat if you are not sure :)
---
A description and technical detail here (optional)
```
================================================
FILE: website/defaults.css
================================================
html,
body {
height: 100%;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
#PhenomicRoot {
display: flex;
min-height: 100%;
}
/* workaround react-native-web absolute positining
which creates lags when scrolling */
#PhenomicRoot > div {
position: relative !important;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
}
.phenomic-Markdown {
font-size: 18px;
line-height: 1.65;
color: #525f7f;
}
.phenomic-Markdown h1,
.phenomic-Markdown h2,
.phenomic-Markdown h3,
.phenomic-Markdown h4,
.phenomic-Markdown h5,
.phenomic-Markdown h6 {
position: relative;
color: #32325d;
}
.phenomic-Markdown .phenomic-HeadingAnchor {
position: absolute;
top: 0;
bottom: 0;
left: -32px;
text-align: center;
padding-left: 10px;
padding-right: 10px;
width: 20px;
text-decoration: none;
opacity: 0.1;
transition: opacity 0.2s;
}
.phenomic-Markdown h1:hover .phenomic-HeadingAnchor,
.phenomic-Markdown h2:hover .phenomic-HeadingAnchor,
.phenomic-Markdown h3:hover .phenomic-HeadingAnchor,
.phenomic-Markdown h4:hover .phenomic-HeadingAnchor,
.phenomic-Markdown h5:hover .phenomic-HeadingAnchor,
.phenomic-Markdown h6:hover .phenomic-HeadingAnchor {
opacity: 1;
}
.phenomic-Markdown a {
color: #006bf6;
}
.phenomic-Markdown img {
max-width: 100%;
}
.phenomic-Markdown code {
font-family: monospace;
}
================================================
FILE: website/highlights-theme.css
================================================
.editor {
padding: 10px 16px;
border: 1px solid #11171c;
border-radius: 6px;
overflow-x: auto;
font-size: 14px;
line-height: 22px;
font-family: Menlo, Monaco, Consolas, Courier New, monospace;
}
/*
Code below has been generated with the following command:
npx atom-syntax-theme-to-highlights-css --clipboard https://github.com/simurai/duotone-dark-sea-syntax
More details at https://github.com/MoOx/atom-syntax-theme-to-highlights-css
*/
.editor {
color: #88b4e7;
background-color: hsl(210, 20%, 20%);
}
.editor .line.cursor-line {
background-color: rgba(52, 68, 85, 0.26);
}
.editor .invisible {
color: #88b4e7;
}
.editor .cursor {
border-color: #52ffc5;
border-left-width: 2px;
}
.editor .selection .region {
background-color: #344455;
}
.editor .bracket-matcher .region {
border-bottom: 1px solid #52ffc5;
}
.editor .invisible-character {
color: #303f4f;
-webkit-font-smoothing: antialiased;
}
.editor .indent-guide {
color: #303f4f;
}
.editor .wrap-guide {
background-color: #303f4f;
}
.editor .find-result .region.region.region,
.editor .current-result .region.region.region {
border-radius: 0px;
background-color: rgba(82, 255, 197, 0.16);
transition: border-color 0.4s;
}
.editor .find-result .region.region.region {
border: 2px solid transparent;
}
.editor .current-result .region.region.region {
border: 2px solid #52ffc5;
transition-duration: 0.1s;
}
.editor .gutter .line-number {
color: #586f89;
-webkit-font-smoothing: antialiased;
}
.editor .gutter .line-number.git-line-removed:before {
bottom: -3px;
}
.editor .gutter .line-number.git-line-removed:after {
content: "";
position: absolute;
left: 0px;
bottom: 0px;
width: 25px;
border-bottom: 1px dotted rgba(224, 82, 82, 0.5);
pointer-events: none;
}
.editor .gutter .line-number.cursor-line {
color: #88b4e7;
background-color: #232d39;
}
.editor .gutter .line-number.cursor-line-no-selection {
background-color: transparent;
}
.editor .gutter .line-number .icon-right {
color: #88b4e7;
}
.editor .gutter .line-number.folded,
.editor .gutter .line-number:after,
.editor .fold-marker:after {
color: #88b4e7;
}
.uno-1 {
color: #d6e9ff;
}
.uno-2 {
color: #88b4e7;
}
.uno-3 {
color: #5d8cc0;
}
.uno-4 {
color: #586f89;
}
.uno-5 {
color: #444c55;
}
.duo-1 {
color: #34febb;
}
.duo-2 {
color: #32ae85;
}
.duo-3 {
color: #42675a;
}
.syntax--source {
color: #88b4e7;
}
.syntax--html.syntax--elements,
.syntax--entity,
.syntax--tag,
.syntax--function-call {
color: #d6e9ff;
}
.syntax--attribute-name,
.syntax--character.syntax--escape {
color: #5d8cc0;
}
.syntax--support {
color: #586f89;
}
.syntax--variable {
color: #5d8cc0;
}
.syntax--string,
.syntax--constant,
.syntax--storage.syntax--type {
color: #34febb;
}
.syntax--keyword,
.syntax--storage {
color: #32ae85;
}
.syntax--punctuation,
.syntax--bracket,
.syntax--brace {
color: #444c55;
}
.syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--comment {
color: #586f89;
font-style: italic;
}
.syntax--bold {
font-weight: bold;
}
.syntax--italic {
font-style: italic;
}
.syntax--c .syntax--parens,
.syntax--c .syntax--block {
color: #88b4e7;
}
.syntax--c .syntax--parens .syntax--punctuation,
.syntax--c .syntax--block .syntax--punctuation,
.syntax--c .syntax--parens .syntax--bracket,
.syntax--c .syntax--block .syntax--bracket,
.syntax--c .syntax--parens .syntax--brace,
.syntax--c .syntax--block .syntax--brace {
color: #444c55;
}
.syntax--c .syntax--parens .syntax--string .syntax--punctuation,
.syntax--c .syntax--block .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--c .syntax--comment {
color: #42675a;
}
.syntax--source.syntax--clojure .syntax--expression {
color: #34febb;
}
.syntax--source.syntax--clojure .syntax--expression .syntax--punctuation {
color: #444c55;
}
.syntax--source.syntax--clojure .syntax--symbol {
color: #88b4e7;
}
.syntax--source.syntax--clojure .syntax--vector {
color: #586f89;
}
.syntax--coffee.syntax--source {
color: #586f89;
}
.syntax--source.syntax--cs .syntax--meta {
color: #586f89;
}
.syntax--source.syntax--cs .syntax--method {
color: #88b4e7;
}
.syntax--css.syntax--source {
color: #444c55;
}
.syntax--css.syntax--support.syntax--property-name {
color: #5d8cc0;
}
.syntax--css.syntax--attribute-name.syntax--id,
.syntax--css.syntax--attribute-name.syntax--class,
.syntax--css.syntax--attribute-name.syntax--parent-selector {
color: #d6e9ff;
}
.syntax--css.syntax--unit {
color: #32ae85;
}
.syntax--css.syntax--function {
color: #42675a;
}
.syntax--css.syntax--punctuation.syntax--terminator {
color: #42675a;
}
.syntax--css.syntax--at-rule {
color: #d6e9ff;
}
.syntax--css.syntax--at-rule .syntax--keyword.syntax--punctuation {
color: inherit;
}
.syntax--gfm {
color: #d6e9ff;
}
.syntax--gfm .syntax--punctuation,
.syntax--gfm .syntax--bracket,
.syntax--gfm .syntax--brace {
color: #444c55;
}
.syntax--gfm .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--gfm .syntax--link {
color: #88b4e7;
}
.syntax--gfm.syntax--markup {
color: #88b4e7;
}
.syntax--gfm.syntax--markup.syntax--bold {
font-weight: bold;
}
.syntax--gfm.syntax--markup.syntax--italic {
font-style: italic;
}
.syntax--gfm.syntax--markup.syntax--strike {
color: #444c55;
text-decoration: line-through;
}
.syntax--gfm.syntax--markup.syntax--raw {
color: #34febb;
}
.syntax--gfm.syntax--markup.syntax--raw .syntax--support,
.syntax--gfm.syntax--markup.syntax--code .syntax--support {
color: #586f89;
}
.syntax--gfm.syntax--comment {
color: #586f89;
}
.syntax--gfm.syntax--comment.syntax--quote {
color: #88b4e7;
}
.syntax--gfm.syntax--table {
color: #34febb;
}
.syntax--gfm.syntax--table .syntax--border,
.syntax--gfm.syntax--table .syntax--pipe {
color: #444c55;
}
.syntax--gfm.syntax--variable,
.syntax--gfm.syntax--entity {
color: #34febb;
}
.syntax--gfm.syntax--support {
color: #32ae85;
}
.syntax--gfm.syntax--heading-1,
.syntax--gfm.syntax--heading-2,
.syntax--gfm.syntax--heading-3 {
color: #34febb;
}
.syntax--gfm.syntax--heading-4,
.syntax--gfm.syntax--heading-5,
.syntax--gfm.syntax--heading-6 {
color: #32ae85;
}
.syntax--haskell.syntax--source {
color: #88b4e7;
}
.syntax--haskell.syntax--source .syntax--punctuation,
.syntax--haskell.syntax--source .syntax--bracket,
.syntax--haskell.syntax--source .syntax--brace {
color: #444c55;
}
.syntax--haskell.syntax--source .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--html.syntax--meta {
color: #444c55;
}
.syntax--html.syntax--embedded .syntax--meta,
.syntax--html.syntax--doctype,
.syntax--html.syntax--text {
color: #586f89;
}
.syntax--html .syntax--string .syntax--id {
color: #34febb;
}
.syntax--jade.syntax--text,
.syntax--jade .syntax--constant.syntax--name.syntax--attribute.syntax--tag {
color: #586f89;
}
.syntax--jade .syntax--meta.syntax--control.syntax--flow {
color: #88b4e7;
}
.syntax--jade .syntax--attribute-name.syntax--id {
color: #34febb;
}
.syntax--java .syntax--method {
color: #88b4e7;
}
.syntax--java .syntax--method .syntax--punctuation,
.syntax--java .syntax--method .syntax--bracket,
.syntax--java .syntax--method .syntax--brace {
color: #444c55;
}
.syntax--java .syntax--method .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--java .syntax--dereference {
color: #586f89;
}
.syntax--js.syntax--delimiter {
color: #444c55;
}
.syntax--js.syntax--source {
color: #88b4e7;
}
.syntax--js.syntax--source .syntax--punctuation,
.syntax--js.syntax--source .syntax--bracket,
.syntax--js.syntax--source .syntax--brace {
color: #444c55;
}
.syntax--js.syntax--source .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--json .syntax--string {
color: #88b4e7;
}
.syntax--json .syntax--string .syntax--punctuation {
color: #444c55;
}
.syntax--json .syntax--value > .syntax--string {
color: #34febb;
}
.syntax--json .syntax--value > .syntax--string .syntax--punctuation {
color: #444c55;
}
.syntax--json .syntax--value .syntax--constant {
color: #32ae85;
}
.syntax--less.syntax--variable:first-child {
color: #88b4e7;
}
.syntax--less .syntax--mixin {
color: #32ae85;
}
.syntax--mediawiki {
color: #d6e9ff;
}
.syntax--mediawiki .syntax--punctuation,
.syntax--mediawiki .syntax--bracket,
.syntax--mediawiki .syntax--brace {
color: #444c55;
}
.syntax--mediawiki .syntax--string .syntax--punctuation {
color: #42675a;
}
.syntax--mediawiki .syntax--wiki-link {
color: #88b4e7;
}
.syntax--mediawiki .syntax--heading {
color: #34febb;
}
.syntax--mediawiki .syntax--function-call {
color: #32ae85;
}
.syntax--mediawiki .syntax--value {
color: #34febb;
}
.syntax--mediawiki .syntax--fix_this_later {
color: #88b4e7;
}
.syntax--mediawiki .syntax--pipe,
.syntax--mediawiki .syntax--link,
.syntax--mediawiki .syntax--tag {
color: #444c55;
}
.syntax--php .syntax--string-contents {
color: #34febb;
}
.syntax--sass .syntax--at-rule .syntax--at-rule,
.syntax--sass .syntax--at-rule .syntax--at-rule > .syntax--punctuation {
color: #d6e9ff;
}
.syntax--sass .syntax--mixin + .syntax--function,
.syntax--sass .syntax--include + .syntax--function {
color: #32ae85;
}
.syntax--sass.syntax--property-value {
color: #34febb;
}
.syntax--sass.syntax--property-value .syntax--function {
color: #88b4e7;
}
.syntax--sass.syntax--property-value .syntax--punctuation {
color: #444c55;
}
.syntax--sass.syntax--variable.syntax--parameter.syntax--url {
color: #34febb;
}
.syntax--sass.syntax--class,
.syntax--sass.syntax--parent-selector-suffix {
color: #d6e9ff;
}
.syntax--scss .syntax--at-rule .syntax--at-rule,
.syntax--scss .syntax--at-rule .syntax--at-rule > .syntax--punctuation {
color: #d6e9ff;
}
.syntax--scss .syntax--mixin + .syntax--function,
.syntax--scss .syntax--include + .syntax--function {
color: #32ae85;
}
.syntax--scss.syntax--property-value {
color: #34febb;
}
.syntax--scss.syntax--property-value .syntax--function {
color: #88b4e7;
}
.syntax--scss.syntax--property-value .syntax--punctuation {
color: #444c55;
}
.syntax--scss.syntax--variable.syntax--parameter.syntax--url {
color: #34febb;
}
.syntax--scss.syntax--class,
.syntax--scss.syntax--parent-selector-suffix {
color: #d6e9ff;
}
.syntax--slim.syntax--meta {
color: #444c55;
}
.syntax--slim.syntax--text {
color: #586f89;
}
.syntax--slim .syntax--string .syntax--id {
color: #34febb;
}
.syntax--stylus .syntax--function .syntax--name {
color: #32ae85;
}
.syntax--tex .syntax--other {
color: #32ae85;
}
.syntax--tex .syntax--reference {
color: #88b4e7;
}
.syntax--plain .syntax--text {
color: #d6e9ff;
}
.syntax--yaml .syntax--tag {
color: #88b4e7;
}
.syntax--yaml .syntax--constant {
color: #32ae85;
}
.syntax--yaml .syntax--punctuation {
color: #444c55;
}
================================================
FILE: website/modules/url-to-slug.js
================================================
// @flow
export default url =>
url
.replace(/https?:\/\//, "")
.replace(/\/$/, "")
.replace(/\//g, "_");
================================================
FILE: website/package.json
================================================
{
"private": true,
"name": "website",
"version": "1.0.0",
"repository": "https://github.com/phenomic/phenomic.git",
"scripts": {
"prepare": "svgr --no-dimensions --out-dir svgs svgs",
"releases-as-markdown": "babel-node --config-file ../babel.config.js upward scripts/releases-as-markdown.js",
"showcase-screenshots": "babel-node --config-file ../babel.config.js upward scripts/showcase-screenshots.js",
"optim": "imageoptim --jpeg-mini --image-alpha --quit --directory dist",
"start": "phenomic start",
"prebuild": "yarn showcase-screenshots",
"build": "phenomic build",
"pretest": "yarn showcase-screenshots",
"test": "yarn build",
"predeploy": "yarn test && (yarn optim || echo \"optim skipped because of failure\")",
"deploy": "./scripts/deploy.sh"
},
"dependencies": {
"@phenomic/cli": "^1.0.0",
"@phenomic/core": "^1.0.0",
"@phenomic/preset-react-app": "^1.0.0",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-ga": "^2.0.0",
"react-helmet": "^5.0.0",
"react-native-web": "^0.9.0",
"react-router": "^3.2.0",
"react-topbar-progress-indicator": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"cross-fetch": "^2.2.3",
"gray-matter": "^3.0.0",
"image-optim": "^3.0.0",
"imageoptim-cli": "^1.15.4",
"mkdirp": "^0.5.1",
"puppeteer": "^1.1.1",
"rimraf": "^2.6.1",
"simple-json-fetch": "^1.0.1",
"svgr": "^1.9.1"
},
"screenshotsSize": {
"large": {
"width": 1366,
"height": 768
},
"small": {
"width": 360,
"height": 640
}
},
"eslintConfig": {
"rules": {
"react/prop-types": 0,
"react-native/no-inline-styles": 0
}
}
}
================================================
FILE: website/phenomic.config.js
================================================
// @flow
module.exports = {
baseUrl: "https://phenomic.io/",
content: {
content: ["**/*"],
packages: {
root: "../packages",
globs: ["*/package.json", "*/docs/**/*.md"],
},
},
presets: ["@phenomic/preset-react-app"],
plugins: [
[
"@phenomic/plugin-rss-feed",
{
feeds: {
"feed.xml": {
feedOptions: {
title: "Phenomic.io",
description: "Phenomic news",
},
query: {
path: "content/blog",
limit: 20,
},
},
},
},
],
],
db: {
sortFunctions: {
showcase: (a, b) => {
if (a.data.curated && !b.data.curated) return -1;
if (!a.data.curated && b.data.curated) return 1;
// more tags first
if (a.data.showcaseTags.length < b.data.showcaseTags.length) return 1;
if (a.data.showcaseTags.length > b.data.showcaseTags.length) return -1;
// blog last
if (
a.data.showcaseTags.indexOf("blog") === -1 &&
b.data.showcaseTags.indexOf("blog") > -1
) {
return -1;
}
return 0;
},
},
},
};
================================================
FILE: website/public/.nojekyll
================================================
================================================
FILE: website/public/CNAME
================================================
phenomic.io
================================================
FILE: website/public/browserconfig.xml
================================================
#ffffff
================================================
FILE: website/public/site.webmanifest
================================================
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
================================================
FILE: website/scripts/deploy.sh
================================================
#!/usr/bin/env bash
GIT_DEPLOY_REPO=${GIT_DEPLOY_REPO:-$(node -e 'process.stdout.write(require("./package.json").repository)')}
cd dist && \
$(npm bin)/rimraf .git && \
git init && \
git add . && \
git commit -m "Deploy to GitHub Pages" && \
git push --force "${GIT_DEPLOY_REPO}" master:gh-pages
================================================
FILE: website/scripts/releases-as-markdown.js
================================================
// @flow
import fs from "fs";
import path from "path";
import "cross-fetch/polyfill";
import jsonFetch from "simple-json-fetch";
(async function() {
try {
const releases = (await jsonFetch(
"https://api.github.com/repos/phenomic/phenomic/releases",
)).json;
releases.forEach(release => {
// skip pre 1.x
if (
release.tag_name.startsWith("v0.") ||
release.tag_name.startsWith("0.")
)
return;
const date = release.published_at.slice(0, "YYYY-MM-DD".length);
const md = `---
title: ${release.name || release.tag_name}
tag_name: ${release.tag_name}
link: ${release.html_url}
author: ${release.author.login}
prerelease: ${release.prerelease}
---
${release.body}
`;
const filename = path.join(
__dirname,
"..",
"content",
"blog",
date + "-" + release.tag_name + ".md",
);
fs.writeFileSync(filename, md);
});
} catch (e) {
console.error("❌ " + e.message);
}
})();
================================================
FILE: website/scripts/showcase-screenshots.js
================================================
// @flow
import { resolve, join } from "path";
import fs from "fs";
import mkdirp from "mkdirp";
import grayMatter from "gray-matter";
import puppeteer from "puppeteer";
import optimizer from "image-optim";
import urlToSlug from "../modules/url-to-slug";
import { screenshotsSize } from "../package.json";
const cacheDir = resolve(__dirname, "..", ".screenshots");
const showcaseDir = resolve(__dirname, "..", "content", "showcase", "entry");
const screenshotsLocation = resolve(
__dirname,
"..",
"public",
"showcase",
"entry",
);
const showcasesFiles = fs
.readdirSync(showcaseDir)
.filter(file => !file.startsWith("."));
const listTmp = [];
showcasesFiles.forEach(file => {
const showcaseFile = fs.readFileSync(join(showcaseDir, file), {
encoding: "utf-8",
});
const showcase = grayMatter(showcaseFile);
listTmp.push({ file, ...showcase.data });
});
// console.log(listTmp);
// process.exit(1);
const list = listTmp; // .slice(0, 2); // for tests
mkdirp.sync(cacheDir);
mkdirp.sync(screenshotsLocation);
const screenshots = list.reduce((screenshots, { file, url }) => {
const filename = urlToSlug(url);
return [
...screenshots,
{
file,
url,
jpgLocation: join(screenshotsLocation, filename + "-large.jpg"),
...screenshotsSize.large,
},
{
file,
url,
jpgLocation: join(screenshotsLocation, filename + "-small.jpg"),
...screenshotsSize.small,
},
];
}, []);
const optimizeScreenshot = async ({ url, jpgLocation }) => {
return optimizer
.optimize(jpgLocation)
.then(() => console.log("📦 ", url, "optimized"));
};
(async () => {
const browser = await puppeteer.launch({
// netlify fails to run puppeteer
// https://github.com/GoogleChrome/puppeteer/issues/1321#issuecomment-378361236
args: ["--disable-dev-shm-usage"],
});
for (const s in screenshots) {
const { file, url, jpgLocation, width, height } = screenshots[s];
try {
// skip if jpeg exist
fs.readFileSync(jpgLocation);
} catch (e) {
try {
console.log("👉 Visiting ", url);
const page = await browser.newPage();
await page.goto(url);
if (
(await page.$("#PhenomicRoot")) === null &&
(await page.$("#phenomic")) === null &&
(await page.$("#statinamic")) === null // back to the future
) {
console.error("⚠️ ", url, "Website seems not to run phenomic");
console.error("🚒 tip: git rm " + join(showcaseDir, file));
} else {
console.log("📷 ", url, "Taking screenshot", width, height);
await page.setViewport({ width, height });
await page.screenshot({
path: jpgLocation,
type: "jpeg",
quality: 40,
});
await optimizeScreenshot({ url, jpgLocation });
console.log("📸 ", url, width, height);
}
} catch (e) {
console.error("🚨 ", url, e.message);
}
}
}
await browser.close();
})();
================================================
FILE: website/webpack.config.js
================================================
// @flow
import defaultWebpackConfig from "@phenomic/plugin-bundler-webpack/lib/webpack.config.js"; // eslint-disable-line
export default (config: PhenomicConfig) => {
const webpackConfig = defaultWebpackConfig(config);
return {
...webpackConfig,
resolve: {
...webpackConfig.resolve,
alias: {
...webpackConfig.resolve.alias,
"react-native$": "react-native-web",
},
},
performance: {
hints: false,
},
};
};