47 |
48 | )
49 | }
50 |
--------------------------------------------------------------------------------
/docs/components/tracking.html.jsx:
--------------------------------------------------------------------------------
1 | export default ({ environment }) => {
2 | let isProduction = environment === "production"
3 |
4 | let scriptBody = `
5 | (function(f, a, t, h, o, m){
6 | a[h]=a[h]||function(){
7 | (a[h].q=a[h].q||[]).push(arguments)
8 | };
9 | o=f.createElement('script'),
10 | m=f.getElementsByTagName('script')[0];
11 | o.async=1; o.src=t; o.id='fathom-script';
12 | m.parentNode.insertBefore(o,m)
13 | })(document, window, 'https://cdn.usefathom.com/tracker.js', 'fathom');
14 | fathom('set', 'siteId', 'FOEDUFMD');
15 | fathom('trackPageview');
16 | `
17 |
18 | let script = {
19 | __html: scriptBody,
20 | }
21 |
22 | if (isProduction) {
23 | return
24 | } else {
25 | return null
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/concepts.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "concepts",
5 | title: "Concepts",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Concepts
11 |
12 | ## Static
13 |
14 | It bears repeating that Charge uses React and JSX to generate static HTML on the _server-side_. It does not render the pages on the client-side in the browser. Charge is especially useful for building small websites where it wouldn’t make sense to serve React to the browser in order to render a simple page.
15 |
16 | ## Files
17 |
18 | How your files are handled depends on what type of file it is. Most files will simply be copied from `source` to `target` without being changed at all. Templates, JavaScripts, and stylesheets will be processed and then written to the `target` directory.
19 |
20 | ## Entrypoints
21 |
22 | Many build systems or asset pipelines have a concept of “entrypoints” or “bundles”. You configure the build system to take many files from different sources and combine them together into one file, which is then referenced in your HTML. For a simple website there might be one bundle for your JavaScript and one bundle for your stylesheet. For a more complex website there might be multiple bundles of each type.
23 |
24 | Charge doesn’t really have this concept, or at least there isn’t any configuration around it. Every file is potentially a “bundle” and how files should be combined together is automatically inferred by figuring out what is a “dependency”.
25 |
26 | ## Dependencies
27 |
28 | A dependency is any file that is imported into another file. Let’s use JavaScript files as an example.
29 |
30 | If you have `index.js` and `dependency.js` and they don’t reference each other in any way, then they will both be copied over and show up in the `target` directory. But if `index.js` imports `dependency.js`, then `dependency.js` is inferred to be a dependency, which means it will be treated differently in two ways:
31 |
32 | 1. `dependency.js` will be bundled/included into `index.js`
33 | 2. `dependency.js` will not be copied over into the `target` directory
34 |
35 | This should probably be what you would expect to happen. It should fit your mental model of how build systems work. The only difference here is that other systems require you to explicitly configure what is an “entrypoint” and what is a dependency, whereas Charge analyzes the files to automatically figure this out for you.
36 |
37 | ## Clean URLs
38 |
39 | Clean URLs are when the `.html` extensions are dropped from URLs for aesthetic or functional reasons. The `.html` extensions are now commonly considered superfluous. If you have a file named `/projects.html` it’s now understood and generally preferred that the URL `domain.com/projects` would serve that file.
40 |
41 | Charge does not have a particular opinion about whether you use Clean URLs or not. The development server will serve the right files regardless of if you use URLs with `.html` extensions or without.
42 |
43 | However, it’s important to note that “clean URLs” is a deployment and/or hosting concern. That means when you build your site for deployment, Charge does not do anything to try and support clean URLs, because Charge can’t know where you plan to deploy the static site and how they might or might not handle clean URLs. It’s up to you to deploy your site using a service that supports the URL structure you want.
44 |
45 | The section on [Deployment][deployment] also covers clean URLs to save you some time identifying the right place to host your site.
46 |
47 | [deployment]: /deployment
48 |
--------------------------------------------------------------------------------
/docs/data-files.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "data-files",
5 | title: "Data files",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Data files
11 |
12 | Data files are a way of providing structured data to your pages in order to simplify building your site.
13 |
14 | Data files are stored in a `data` folder that must be in the same directory as the `source` folder. They’re siblings. So if the path to `source` is `some/folder/source`, then the path to `data` must be `some/folder/data`.
15 |
16 | Data files are JSON files and the name of the file is the object property you use to access that data. So if you have a data file called `albums.json` then you would access the data from the `props` object passed into your page by calling `props.data.albums`.
17 |
--------------------------------------------------------------------------------
/docs/deployment.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "deployment",
5 | title: "Deployment",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Deployment
11 |
12 | ## Amazon S3
13 |
14 | [Amazon S3][s3] is a great static site host. It supports custom domains, HTTPS, and has a CDN (Amazon CloudFront). It’s not free, but it’s so cheap that it’s effectively free; you’ll probably pay pennies per month. The one downside is that configuring and deploying to S3 is a nightmare.
15 |
16 | I built [Discharge][discharge] as a companion to Charge to simplify and automate configuring and deploying to S3. It synchronizes files, sets up HTTPS, and sets up the CDN.
17 |
18 | S3 supports clean URLs but not implicitly. You have to transform your filenames and remove the extensions _as_ you deploy to S3. Discharge will automatically do that for you if you configure it to.
19 |
20 | ## Netlify
21 |
22 | [Netlify][netlify] is a great place to host a static site for free. It supports custom domains, HTTPS, and has a CDN built in.
23 |
24 | Netlify supports clean URLs (which they call “Pretty URLs”) and have [docs on how to enable them][netlify-docs].
25 |
26 | ## Vercel
27 |
28 | [Vercel][vercel] is another great place to host a static site for free. It supports custom domains, HTTPS, and has a CDN built in.
29 |
30 | ## Heroku
31 |
32 | You can definitely deploy a static site to [Heroku][heroku] but I wouldn’t recommend it. The free dynos will sleep after 30 minutes and stop working entirely if you run out of your monthly “dyno hours” allotment.
33 |
34 | [s3]: https://aws.amazon.com/s3/
35 | [discharge]: https://github.com/brandonweiss/discharge
36 | [netlify]: https://www.netlify.com
37 | [netlify-docs]: https://www.netlify.com/docs/redirects/#trailing-slash
38 | [vercel]: https://vercel.com/
39 | [heroku]: https://www.heroku.com
40 |
--------------------------------------------------------------------------------
/docs/examples.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "examples",
5 | title: "Examples",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Examples
11 |
12 | If you’d like to see everything in practice, check out these sites using Charge.
13 |
14 | * [charge.js.org](https://github.com/brandonweiss/charge/tree/master/docs), the documentation for Charge.
15 | * [brandonweiss.me](https://github.com/brandonweiss/brandonweiss), a personal site.
16 | * [Anti-pattern](https://github.com/brandonweiss/anti-pattern/commit/bf3e91ebb8211a7b22183e165ce8cc287b40b729), a simple blog.
17 |
18 | If you have a site using Charge and the repository is public,
19 | [let me know](mailto:brandon@anti-pattern.com) and I’ll add it to the list.
20 |
--------------------------------------------------------------------------------
/docs/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonweiss/charge/21a8b4a1042009995ace22f5598ad196b3ed8e87/docs/images/favicon.png
--------------------------------------------------------------------------------
/docs/images/logomark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brandonweiss/charge/21a8b4a1042009995ace22f5598ad196b3ed8e87/docs/images/logomark.png
--------------------------------------------------------------------------------
/docs/images/logomark.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/docs/index.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 | import Logotype from "./components/logotype.html.jsx"
3 |
4 | export const meta = {
5 | id: "about",
6 | title: "About",
7 | }
8 |
9 | export const layout = (props) =>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 
18 | 
19 | 
20 | 
21 |
22 | ## What?
23 |
24 | Charge is an opinionated, zero-config static site generator written in JavaScript. It supports a wide variety of common uses and it does it without needing to be configured or customized. It’s fast, it’s simple, and it works the way you probably expect it to. That’s it.
25 |
26 | ## Why?
27 |
28 | Yeah, I know, another static site generator. Let me be clear, I really did not want to make a static site generator. It’s really the very last thing I wanted to do.
29 |
30 | I went on [StaticGen][static-gen] and looked at every JavaScript-based one. I could not find a single one that I thought was simple, well-documented, had the features I needed, was actively maintained, and was designed and worked the way I wanted. So here I am, making a static site generator.
31 |
32 | ## Highlights
33 |
34 | - Zero configuration
35 | - Templating via [JSX][jsx] and [MDX][mdx]
36 | - React renders server-side, _not_ client-side
37 | - Write futuristic JavaScript with [Babel][babel]
38 | - Write futuristic CSS with [PostCSS][postcss]
39 | - Live-reloading development server
40 | - Rebuilds the minimum files necessary
41 | - Dynamic pages (coming soon)
42 | - Stellar documentation ✨
43 |
44 | ## How is Charge different from GatsbyJS?
45 |
46 | [Gatsby][gatsby] is really cool, but it’s very different than Charge, with two particularly large differences.
47 |
48 | Gatsby is configuration over convention. It can be used to build complex web applications, but because of that it can be very difficult to understand how to use it. You’ll need to know how to use Webpack, which personally gives me nightmares. It’s likely that you’ll need to spend time learning other tools and then configuring and tweaking Gatsby before you can use it for your site. Charge is convention over configuration. In fact, it has no configuration, it “just works”.
49 |
50 | Gatsby renders pages client-side. That means it serves React and some related libraries to the browser along with your components in order to render the pages. Routing also happens client-side. Gatsby _can_ render the initial page load server-side, but there’s no way to _not_ serve hundreds of kilobytes of JavaScript to the browser. Charge uses React to render everything server-side. It generates a truly static site.
51 |
52 | More practically, Gatsby is great if you’re building a large, complex website and want lots of control over how you build it. Charge is probably better if you’re building a small website and don’t want to waste time fiddling with configurations and cobbling different tools together.
53 |
54 | ## Blogging
55 |
56 | Charge can be used for blogging, but it’s not a tool specifically _for_ blogging, if that makes sense.
57 |
58 | A blog is really just a set of patterns around how content is displayed. There is typically a list of posts, possibly paginated. Permalink pages. An archive. RSS and JSON feeds. A sitemap. Etc. You can do all of that with Charge, but it doesn’t have any specific patterns or configuration around that, which is what many people are looking for when they want a blog.
59 |
60 | Put another way, if you’re looking to make a simple blog and don’t mind a little work, you can use Charge to build a blog in the same way you can use a static site generator to build any website, but if your blog is complex or you’re looking for something that just works right out of the box then you’d probably want to look for a tool specifically for blogging.
61 |
62 | If you’d like to see what a simple blog with Charge might look like, here’s an [example of a switch from Middleman to Charge][blog-switch].
63 |
64 | [static-gen]: https://www.staticgen.com
65 | [jsx]: https://reactjs.org/docs/introducing-jsx.html
66 | [mdx]: https://github.com/mdx-js/mdx
67 | [babel]: https://babeljs.io
68 | [postcss]: https://postcss.org
69 | [gatsby]: https://www.gatsbyjs.org
70 | [blog-switch]: https://github.com/brandonweiss/anti-pattern/commit/bf3e91ebb8211a7b22183e165ce8cc287b40b729
71 |
--------------------------------------------------------------------------------
/docs/installation.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "installation",
5 | title: "Installation",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Installation
11 |
12 | Install it globally with npm:
13 |
14 | ```shell
15 | ❯ npm install --global @static/charge
16 | ```
17 |
18 | Or add it to your application’s `package.json`:
19 |
20 | ```shell
21 | ❯ npm install --save-dev @static/charge
22 | ```
23 |
24 | **Warning!** The `charge` package on npm is _not_ this package. You must use the scoped package name `@static/charge`.
25 |
--------------------------------------------------------------------------------
/docs/javascripts.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "javascripts",
5 | title: "JavaScripts",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # JavaScripts
11 |
12 | JavaScripts are transformed using [Babel][babel].
13 |
14 | ## Features
15 |
16 | All features from `es2015`, `es2016`, and `es2017` are included via [`@babel/preset-env`][babel-preset-env]. You can see a list of those features in the [ECMAScript compatibility table][ecmascript-compatibility-table].
17 |
18 | ## Importing
19 |
20 | You can import other JavaScripts using the ES6 module syntax.
21 |
22 | ```javascript
23 | // index.js
24 | import something from "./other.js"
25 |
26 | console.log(something)
27 | ```
28 |
29 | ```js
30 | // other.js
31 | export default "something"
32 | ```
33 |
34 | Imported JavaScripts will be treated as dependencies and inlined into the files that import them.
35 |
36 | Make sure you reference dependencies relatively with `./` or `../` to ensure they’re treated as dependencies.
37 |
38 | ### npm packages
39 |
40 | You can `import` npm packages as you would normally expect. It will look for packages in the `node_modules` folder at the root of your project.
41 |
42 | [babel]: https://babeljs.io
43 | [babel-preset-env]: https://babeljs.io/docs/en/babel-preset-env
44 | [ecmascript-compatibility-table]: http://kangax.github.io/compat-table/es2016plus/
45 |
--------------------------------------------------------------------------------
/docs/json.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "json",
5 | title: "JSON",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # JSON
11 |
12 | JSON files can be generated by creating a file with a `.json.js` extension and then exporting a function from it.
13 |
14 | ```javascript
15 | // feed.json.js
16 | export default (props) => {
17 | return {
18 | title: "My blog",
19 | items: [],
20 | }
21 | }
22 | ```
23 |
24 | The function will be passed all the same props a page normally receives. Return a JavaScript object from the exported function and it will be stringified into JSON.
25 |
--------------------------------------------------------------------------------
/docs/layout.html.jsx:
--------------------------------------------------------------------------------
1 | import Main from "./components/main.html.jsx"
2 | import Nav, { navItems } from "./components/nav.html.jsx"
3 | import Pagination from "./components/pagination.html.jsx"
4 | import GitHubLink from "./components/github-link.html.jsx"
5 | import Logomark from "./components/logomark.html.jsx"
6 | import Logo from "./components/logo.html.jsx"
7 | import { resolve as resolveURL } from "url"
8 | import SearchInput from "./components/SearchInput.html.jsx"
9 | import SearchScript from "./components/SearchScript.html.jsx"
10 | import Tracking from "./components/tracking.html.jsx"
11 |
12 | export default ({ children, currentPageID, environment, pages }) => {
13 | let currentPage = pages.find((page) => page.meta.id === currentPageID)
14 | let pageTitle =
15 | currentPageID === "about"
16 | ? "Charge — an opinionated, zero-config static site generator"
17 | : `${currentPage.meta.title} — Charge`
18 | let openGraphTitle = currentPageID === "about" ? "Charge" : `${currentPage.meta.title} — Charge`
19 | let description = "An opinionated, zero-config static site generator"
20 |
21 | let baseURL = "https://charge.js.org"
22 | let url = resolveURL(baseURL, currentPage.path)
23 | if (url.endsWith("/")) {
24 | url = url.slice(0, -1)
25 | }
26 |
27 | return (
28 |
29 |
30 |
31 | {pageTitle}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 | {currentPageID === "about" ? (
65 |
66 |
67 |
68 | ) : (
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | )}
77 |
78 |
{children}
79 |
80 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | )
109 | }
110 |
--------------------------------------------------------------------------------
/docs/pages.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "pages",
5 | title: "Pages",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Pages
11 |
12 | Pages are written in [JSX][jsx] and [MDX][mdx] use React. If you’re used to thinking about React running in the browser, this is different. These pages are server-side rendered not client-side rendered, meaning React is used to generate static HTML files.
13 |
14 | The naming convention is `name.html.jsx` for JSX files and `name.html.mdx` for MDX files. When the site is built the `.jsx` and `.mdx` parts of the extension will be removed.
15 |
16 | ## React
17 |
18 | If you’re new to React I’d recommend reading its [incredible docs](https://reactjs.org/docs/introducing-jsx.html), starting with the section on JSX.
19 |
20 | If you want to see what using JSX to write HTML looks like here are two very simple examples for components/partials and layouts, concepts that are usually built into most static site generators.
21 |
22 | ### Components
23 |
24 | React is inherently a component-based system. Any JSX file can export a component that can be included on another page.
25 |
26 | ```jsx
27 | // index.html.jsx
28 | import Component from "./component.html.jsx"
29 |
30 | export default () => {
31 | return
32 | }
33 | ```
34 |
35 | ```jsx
36 | // component.html.jsx
37 | export default (props) => {
38 | return
{props.message}
39 | }
40 | ```
41 |
42 | ### Layouts
43 |
44 | Layouts are just another way of using React components. If you wrap a component around your content you can use the `children` property to render that content.
45 |
46 | ```jsx
47 | // index.html.jsx
48 | import Layout from "./layout.html.jsx"
49 |
50 | export default () => {
51 | return (
52 |
53 |
Hello!
54 |
55 | )
56 | }
57 | ```
58 |
59 | ```jsx
60 | // layout.html.jsx
61 | export default (props) => {
62 | return (
63 |
64 |
65 | {props.title}
66 |
67 |
68 | {props.children}
69 |
70 | )
71 | }
72 | ```
73 |
74 | ## Markdown
75 |
76 | You can also write pages in Markdown via [MDX][mdx], a clever idea for combining Markdown and [JSX][jsx]. It’s best to read the docs, but you can…
77 |
78 | - Import Markdown into JSX
79 | - Import JSX into Markdown
80 | - Import Markdown into Markdown
81 |
82 | MDX is not the same as JSX, though. For example, there are no expressions. There isn’t a render function either, so there are no props. There are layouts, though.
83 |
84 | A named `layout` export can be used to provide a layout component that will wrap the Markdown. The layout component will receive all the same props any other page would receive.
85 |
86 | ```markdown
87 | // index.html.mdx
88 | import Layout from "./layout.html.jsx"
89 |
90 | export const layout = (props) => (
91 |
92 | {props.children}
93 |
94 | )
95 |
96 | # Heading
97 | ```
98 |
99 | ```jsx
100 | // layout.html.jsx
101 | export default (props) => {
102 | return (
103 |
104 |
105 | {props.title}
106 |
107 |
108 | {props.children}
109 |
110 | )
111 | }
112 | ```
113 |
114 | ### Plugins
115 |
116 | MDX uses [remark](https://github.com/remarkjs/remark) to render Markdown to HTML. remark supports the most common Markdown syntax and features and it provides a plugin system to extend Markdown with less common features.
117 |
118 | If there is a Markdown extension you think would make sense to add to Charge take a look at the [list of remark plugins][remark-plugins], find the one you need, and [open an issue][issue] requesting it to be added.
119 |
120 | Here are the current plugins:
121 |
122 | #### Abbreviations
123 |
124 | Acronyms, initialisms, etc. can be automatically converted to [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr) elements.
125 |
126 | ```plaintext
127 | HTML is great.
128 |
129 | *[HTML]: Hypertext Markup Language
130 | ```
131 |
132 | #### Syntax highlighting
133 |
134 | Syntax highlighting is done via [remark-highlight.js](https://github.com/remarkjs/remark-highlight.js). You can [visually browse](https://highlightjs.org/static/demo/) the various syntax styles (themes) and then [grab the CSS file](https://github.com/highlightjs/highlight.js/tree/master/src/styles) for the one you like.
135 |
136 | The Markdown syntax for highlighting code is “fenced code blocks” with the language name appended to the opening “fence”.
137 |
138 | ```javascript
139 | let foo = "bar"
140 | ```
141 |
142 | There is a [list of supported languages and corresponding aliases](https://github.com/highlightjs/highlight.js/blob/master/docs/css-classes-reference.rst#language-names-and-aliases).
143 |
144 | ## Props
145 |
146 | A set of props will be passed to your pages. The props object looks like this:
147 |
148 | ```jsx
149 | {
150 | data: {},
151 | environment: "development",
152 | pages: [
153 | {
154 | component: ,
155 | meta: {
156 | date: "2019/01/28",
157 | title: "First post!",
158 | },
159 | path: "/first-post",
160 | },
161 | ],
162 | }
163 | ```
164 |
165 | ### Data
166 |
167 | The `data` property will be populated with any data files you create. The section on [data files](/data-files) will explain them.
168 |
169 | ### Environment
170 |
171 | The `environment` property will be either `"development"` or `"production"`, depending on whether you run `serve` or `build`, respectively. This is useful for including certain scripts only in production.
172 |
173 | ### Pages
174 |
175 | The `pages` property will be an array of objects representing the page components of your site (JSX and MDX pages) and will not include regular HTML pages. This is useful for generating sitemaps or other similar dynamic lists of pages.
176 |
177 | Each page object has a `component`, `meta`, and `path` property.
178 |
179 | #### Component
180 |
181 | The `component` property can be used to render the contents of the page. This is useful for creating a page that lists recent blog posts.
182 |
183 | **A warning**: the `component` property of a page object that you’re trying to render will expect you to provide whatever of the common props (`data`, `environment`, and `pages`) that you’re using in that component. If the component you’re trying to render makes use of the `pages` property you will have to provide something for the `pages` prop or it won’t render, but you probably can’t provide the actual `pages` prop as that will create an infinite loop. You should pass an empty array instead, although this will necessarily render something different than you expect.
184 |
185 | A shorter but perhaps more confusing way of explaining it is, you’re not going to be able to use the `component` property of a page object to render a component that itself uses the `pages` property.
186 |
187 | #### Meta
188 |
189 | The `meta` property is populated by exporting a named export from the page with an object of whatever data you need.
190 |
191 | ```markdown
192 | // first-post.html.mdx
193 | export const meta = {
194 | date: "2019/01/28",
195 | title: "First post!"
196 | }
197 |
198 | My first post.
199 | ```
200 |
201 | This is useful for filtering pages, annotating a list of pages, etc.
202 |
203 | #### Path
204 |
205 | The `path` property can be used to link to the page.
206 |
207 | ## Organization
208 |
209 | If you find that you have a lot of layouts and/or components you can organize them into folders. There are no constraints on how you decide to organize your dependencies.
210 |
211 | ## Doctype
212 |
213 | JSX does not support the DOCTYPE declaration used at the top of HTML documents. Just leave it off and it will be prepended to the top of all JSX and MDX files for you.
214 |
215 | ## Whitespace
216 |
217 | JSX eats whitespace, which can be a bit confusing. You might be used to breaking HTML onto multiple lines and them being rendered with a space between them.
218 |
219 | ```html
220 |
221 | First line
222 | second line.
223 |
224 | ```
225 |
226 | You would expect it would render like this.
227 |
228 | ```
229 | First line second line.
230 | ```
231 |
232 | But with JSX it would actually render like this.
233 |
234 | ```
235 | First linesecond line.
236 | ```
237 |
238 | You’ll need to intentionally insert a space like this.
239 |
240 | ```html
241 |
242 | These will be on the same line
243 | {" "}
244 | with a space between them.
245 |
246 | ```
247 |
248 | ## Importing React
249 |
250 | When using JSX you would normally need to import React just like any other module (even if not explicitly using the `React` constant).
251 |
252 | ```jsx
253 | import React from "react"
254 |
255 | export default () => {
256 | return
257 | }
258 | ```
259 |
260 | Charge automatically prepends the import to JSX files for you so you don’t have to!
261 |
262 | ```jsx
263 | export default () => {
264 | return
265 | }
266 | ```
267 |
268 | [jsx]: https://reactjs.org/docs/introducing-jsx.html
269 | [mdx]: https://github.com/mdx-js/mdx
270 | [remark-plugins]: https://github.com/remarkjs/remark/blob/master/doc/plugins.md#list-of-plugins
271 | [issue]: https://github.com/brandonweiss/charge/issues/new
272 |
--------------------------------------------------------------------------------
/docs/stylesheets/atom-one-light.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Atom One Light by Daniel Gamage
4 | Original One Light Syntax theme from https://github.com/atom/one-light-syntax
5 |
6 | base: #fafafa
7 | mono-1: #383a42
8 | mono-2: #686b77
9 | mono-3: #a0a1a7
10 | hue-1: #0184bb
11 | hue-2: #4078f2
12 | hue-3: #a626a4
13 | hue-4: #50a14f
14 | hue-5: #e45649
15 | hue-5-2: #c91243
16 | hue-6: #986801
17 | hue-6-2: #c18401
18 |
19 | */
20 |
21 | .hljs {
22 | display: block;
23 | overflow-x: auto;
24 | padding: 0.5em;
25 | color: #383a42;
26 | background: #fafafa;
27 | }
28 |
29 | .hljs-comment,
30 | .hljs-quote {
31 | color: #a0a1a7;
32 | font-style: italic;
33 | }
34 |
35 | .hljs-doctag,
36 | .hljs-keyword,
37 | .hljs-formula {
38 | color: #a626a4;
39 | }
40 |
41 | .hljs-section,
42 | .hljs-name,
43 | .hljs-selector-tag,
44 | .hljs-deletion,
45 | .hljs-subst {
46 | color: #e45649;
47 | }
48 |
49 | .hljs-literal {
50 | color: #0184bb;
51 | }
52 |
53 | .hljs-string,
54 | .hljs-regexp,
55 | .hljs-addition,
56 | .hljs-attribute,
57 | .hljs-meta-string {
58 | color: #50a14f;
59 | }
60 |
61 | .hljs-built_in,
62 | .hljs-class .hljs-title {
63 | color: #c18401;
64 | }
65 |
66 | .hljs-attr,
67 | .hljs-variable,
68 | .hljs-template-variable,
69 | .hljs-type,
70 | .hljs-selector-class,
71 | .hljs-selector-attr,
72 | .hljs-selector-pseudo,
73 | .hljs-number {
74 | color: #986801;
75 | }
76 |
77 | .hljs-symbol,
78 | .hljs-bullet,
79 | .hljs-link,
80 | .hljs-meta,
81 | .hljs-selector-id,
82 | .hljs-title {
83 | color: #4078f2;
84 | }
85 |
86 | .hljs-emphasis {
87 | font-style: italic;
88 | }
89 |
90 | .hljs-strong {
91 | font-weight: bold;
92 | }
93 |
94 | .hljs-link {
95 | text-decoration: underline;
96 | }
97 |
--------------------------------------------------------------------------------
/docs/stylesheets/index.css:
--------------------------------------------------------------------------------
1 | @import "./modern-normalize.css";
2 | @import "./atom-one-light.css";
3 |
4 | html,
5 | body {
6 | height: 100%;
7 | }
8 |
9 | html {
10 | line-height: 1.5;
11 | }
12 |
13 | body {
14 | background-color: #f7f7f7;
15 | color: #666666;
16 | font-family: "Avenir Next", "Avenir", "Helvetica Neue", Helvetica, Arial, sans-serif;
17 | font-size: 18px;
18 | margin: 0;
19 | display: flex;
20 | }
21 |
22 | a {
23 | color: #ff8e96;
24 | }
25 |
26 | a:hover {
27 | color: #ff0069;
28 | }
29 |
30 | .container {
31 | margin: 0 auto;
32 | max-width: 700px;
33 | }
34 |
35 | code {
36 | background-color: #f2f2f2;
37 | border-radius: 2px;
38 | padding: 0.2em;
39 | }
40 |
41 | .hljs {
42 | background-color: #f2f2f2;
43 | border-radius: 5px;
44 | padding: 1em;
45 | }
46 |
47 | pre code {
48 | display: block;
49 | overflow-x: auto;
50 | }
51 |
52 | @media only screen and (max-width: 799px) {
53 | .desktop {
54 | display: none;
55 | }
56 | }
57 |
58 | @media only screen and (min-width: 800px) {
59 | .mobile {
60 | display: none;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/docs/stylesheets/modern-normalize.css:
--------------------------------------------------------------------------------
1 | /*! modern-normalize | MIT License | https://github.com/sindresorhus/modern-normalize */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * Use a better box model (opinionated).
8 | */
9 |
10 | html {
11 | box-sizing: border-box;
12 | }
13 |
14 | *,
15 | *::before,
16 | *::after {
17 | box-sizing: inherit;
18 | }
19 |
20 | /**
21 | * Use a more readable tab size (opinionated).
22 | */
23 |
24 | :root {
25 | -moz-tab-size: 4;
26 | tab-size: 4;
27 | }
28 |
29 | /**
30 | * 1. Correct the line height in all browsers.
31 | * 2. Prevent adjustments of font size after orientation changes in iOS.
32 | */
33 |
34 | html {
35 | line-height: 1.15; /* 1 */
36 | -webkit-text-size-adjust: 100%; /* 2 */
37 | }
38 |
39 | /* Sections
40 | ========================================================================== */
41 |
42 | /**
43 | * Remove the margin in all browsers.
44 | */
45 |
46 | body {
47 | margin: 0;
48 | }
49 |
50 | /**
51 | * Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
52 | */
53 |
54 | body {
55 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
56 | "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
57 | }
58 |
59 | /* Grouping content
60 | ========================================================================== */
61 |
62 | /**
63 | * Add the correct height in Firefox.
64 | */
65 |
66 | hr {
67 | height: 0;
68 | }
69 |
70 | /* Text-level semantics
71 | ========================================================================== */
72 |
73 | /**
74 | * Add the correct text decoration in Chrome, Edge, and Safari.
75 | */
76 |
77 | abbr[title] {
78 | text-decoration: underline dotted;
79 | }
80 |
81 | /**
82 | * Add the correct font weight in Chrome, Edge, and Safari.
83 | */
84 |
85 | b,
86 | strong {
87 | font-weight: bolder;
88 | }
89 |
90 | /**
91 | * 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
92 | * 2. Correct the odd `em` font sizing in all browsers.
93 | */
94 |
95 | code,
96 | kbd,
97 | samp,
98 | pre {
99 | font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; /* 1 */
100 | font-size: 1em; /* 2 */
101 | }
102 |
103 | /**
104 | * Add the correct font size in all browsers.
105 | */
106 |
107 | small {
108 | font-size: 80%;
109 | }
110 |
111 | /**
112 | * Prevent `sub` and `sup` elements from affecting the line height in all browsers.
113 | */
114 |
115 | sub,
116 | sup {
117 | font-size: 75%;
118 | line-height: 0;
119 | position: relative;
120 | vertical-align: baseline;
121 | }
122 |
123 | sub {
124 | bottom: -0.25em;
125 | }
126 |
127 | sup {
128 | top: -0.5em;
129 | }
130 |
131 | /* Forms
132 | ========================================================================== */
133 |
134 | /**
135 | * 1. Change the font styles in all browsers.
136 | * 2. Remove the margin in Firefox and Safari.
137 | */
138 |
139 | button,
140 | input,
141 | optgroup,
142 | select,
143 | textarea {
144 | font-family: inherit; /* 1 */
145 | font-size: 100%; /* 1 */
146 | line-height: 1.15; /* 1 */
147 | margin: 0; /* 2 */
148 | }
149 |
150 | /**
151 | * Remove the inheritance of text transform in Edge and Firefox.
152 | * 1. Remove the inheritance of text transform in Firefox.
153 | */
154 |
155 | button,
156 | select {
157 | /* 1 */
158 | text-transform: none;
159 | }
160 |
161 | /**
162 | * Correct the inability to style clickable types in iOS and Safari.
163 | */
164 |
165 | button,
166 | [type="button"],
167 | [type="reset"],
168 | [type="submit"] {
169 | -webkit-appearance: button;
170 | }
171 |
172 | /**
173 | * Remove the inner border and padding in Firefox.
174 | */
175 |
176 | button::-moz-focus-inner,
177 | [type="button"]::-moz-focus-inner,
178 | [type="reset"]::-moz-focus-inner,
179 | [type="submit"]::-moz-focus-inner {
180 | border-style: none;
181 | padding: 0;
182 | }
183 |
184 | /**
185 | * Restore the focus styles unset by the previous rule.
186 | */
187 |
188 | button:-moz-focusring,
189 | [type="button"]:-moz-focusring,
190 | [type="reset"]:-moz-focusring,
191 | [type="submit"]:-moz-focusring {
192 | outline: 1px dotted ButtonText;
193 | }
194 |
195 | /**
196 | * Correct the padding in Firefox.
197 | */
198 |
199 | fieldset {
200 | padding: 0.35em 0.75em 0.625em;
201 | }
202 |
203 | /**
204 | * Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers.
205 | */
206 |
207 | legend {
208 | padding: 0;
209 | }
210 |
211 | /**
212 | * Add the correct vertical alignment in Chrome and Firefox.
213 | */
214 |
215 | progress {
216 | vertical-align: baseline;
217 | }
218 |
219 | /**
220 | * Correct the cursor style of increment and decrement buttons in Safari.
221 | */
222 |
223 | [type="number"]::-webkit-inner-spin-button,
224 | [type="number"]::-webkit-outer-spin-button {
225 | height: auto;
226 | }
227 |
228 | /**
229 | * 1. Correct the odd appearance in Chrome and Safari.
230 | * 2. Correct the outline style in Safari.
231 | */
232 |
233 | [type="search"] {
234 | -webkit-appearance: textfield; /* 1 */
235 | outline-offset: -2px; /* 2 */
236 | }
237 |
238 | /**
239 | * Remove the inner padding in Chrome and Safari on macOS.
240 | */
241 |
242 | [type="search"]::-webkit-search-decoration {
243 | -webkit-appearance: none;
244 | }
245 |
246 | /**
247 | * 1. Correct the inability to style clickable types in iOS and Safari.
248 | * 2. Change font properties to `inherit` in Safari.
249 | */
250 |
251 | ::-webkit-file-upload-button {
252 | -webkit-appearance: button; /* 1 */
253 | font: inherit; /* 2 */
254 | }
255 |
256 | /* Interactive
257 | ========================================================================== */
258 |
259 | /*
260 | * Add the correct display in Chrome and Safari.
261 | */
262 |
263 | summary {
264 | display: list-item;
265 | }
266 |
--------------------------------------------------------------------------------
/docs/styling.html.mdx:
--------------------------------------------------------------------------------
1 | import Layout from "./layout.html.jsx"
2 |
3 | export const meta = {
4 | id: "styling",
5 | title: "Styling",
6 | }
7 |
8 | export const layout = (props) =>
9 |
10 | # Styling
11 |
12 | ## Stylesheets
13 |
14 | Stylesheets are not pre-processed. There is no Sass, Stylus, or alternative CSS syntax. You write normal CSS. You can take advantage of new CSS features that don’t have universal browser support via [PostCSS][postcss]. Most of what you might have used a pre-processor for you can do with PostCSS now.
15 |
16 | ### Features
17 |
18 | All Stage 2 and Stage 3 features are enabled. You can see a list of those features in [cssdb][cssdb]. Stage 1 features are considered too experimental to use. The one exception is [Custom Media Queries][custom-media-queries] which is very widely used and seems likely to progress to Stage 2, so that feature is also enabled.
19 |
20 | ### Importing
21 |
22 | You can import other stylesheets using the `@import` at-rule.
23 |
24 | ```css
25 | /* index.css */
26 | @import "./other.css"
27 |
28 | p {
29 | font-size: 16px;
30 | }
31 | ```
32 |
33 | ```css
34 | /* other.css */
35 | a {
36 | font-size: 16px;
37 | }
38 | ```
39 |
40 | Imported stylesheets will be treated as dependencies and inlined into the files that import them.
41 |
42 | Make sure you reference dependencies relatively with `./` or `../` to ensure they’re treated as dependencies.
43 |
44 | #### npm packages
45 |
46 | You can `import` npm packages as you would normally expect. It will look for packages in the `node_modules` folder at the root of your project.
47 |
48 | ## CSS in JS
49 |
50 | Styling components directly in JavaScript is becoming ever more popular. Co-locating styles with the components they’re styling is great ergonomically and avoiding the cascade and the issues it can cause is attractive, so Charge should support this method of styling. The only question is how?
51 |
52 | Ideally there would be one main CSS in JS library, similar to how [PostCSS][postcss] is the de facto standard for CSS post-processing. Unfortunately that’s not the case. There are dozens and dozens of CSS in JS libraries and each of them works differently from one another, both in terms of the interface for styling components and in how to integrate with the library.
53 |
54 | Picking one library to integrate with seems too prescriptive, even for an opinionated framework. But adding multiple libraries and integrating with them all is too complicated and confusing.
55 |
56 | I think the best thing to do at the moment is to punt on the problem and integrate with none of them. For now, Charge is BYOCSSIJS. That means if you want to use a CSS in JS library you’ll have to ensure you’re picking one that hooks into React in such a way that the styles will be correctly applied.
57 |
58 | To help, I’ll try to keep a list of the most popular libraries and whether or not they work. Feel free to help me add to this list!
59 |
60 | ### styled-components ❌
61 |
62 | [styled-components][styled-components] is probably the most popular library but as far as I can tell it doesn’t work with Charge. It combines styles together and inserts them into the `` tag of the document, which in order to work with server-side rendering seems to require a specific integration.
63 |
64 | ### Emotion ✅
65 |
66 | [Emotion][emotion] is probably the second most popular library and it works with Charge! Emotion inserts `