* fix: allow liquidMethodMissing to return any supported value type
* Update src/drop/drop.ts
Co-authored-by: Jun Yang <[email protected]>
---------
Co-authored-by: Jun Yang <[email protected]>
* fix: only render the first 'else' template in the case of multiples
* fix: empty else block and cases with when conditions
* fix: don't render elsif after else
* chore: Update src/tags/unless.ts
* chore: Update src/tags/if.ts
* chore: Update src/tags/case.ts
---------
Co-authored-by: Jun Yang <[email protected]>
* fix: rely on equal for computing contains
This change allows contains to be computed using the toValue of the items in the array.
Before this change if I had an array of "Drop" `contains` would not match against the value.
* Apply suggestions from code review
Co-authored-by: Jun Yang <[email protected]>
---------
Co-authored-by: Jun Yang <[email protected]>
* feat(filters): add array sum filter
* docs(filters): array sum filter
* docs: update versoin number in source/filters/sum.md
---------
Co-authored-by: Jun Yang <[email protected]>
As written, the strftime module's `getSuffix` method (responsible for
returning a date's ordinal string) works correctly for all dates in a
month _except_ 11, 12, and 13.
The existing code would return a string based on the last digit of the
date. In American English, these three dates use the `th` suffix rather
than `st`, `nd`, or `rd`.
This refactor/bug fix draws inspiration from Rails' ActiveSupport
ordinal inflector:
https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.rb
The Ruby code above is designed to work with any number, so the bug fix
to this library is simpler.
The test suite is also updated with additional examples to verify the
correctness of these changes.
Once #615 is merged, the build script should work on macOS just as well as it does on Ubuntu and with this GitHub Actions matrix we can keep ensuring that it continues to work as it should.
This should help anyone looking to test their changes they made to LiquidJS via the Playground site also provided in the repository.
I have also added basic information on where the Playground is and how to run it in general.
* fix: sed invocations to work out of the box on macOS
These fixes make the sed invocations run on macOS but I am not sure if they will break the GNU sed invocations in return…
* fix: add macOS branches to the shell scripts
The sed command line was difficult (impossible?) to be made portable so I just added macOS conditions.
* Prototype the solution using an alias
It seems that this will not work because I keep getting "sedi: command not found".
* fix: use a Bash function instead of an alias to run sed portably
This seems to work on my local so let's see if it runs in the CI on GitHub.
* fix: use 2 spaces like the original scripts did
Not sure why VS Code went with 4.
* fix: use sedi for the build-changelog `1i\` part as well
I am curious if Ubuntu will handle the newline…
* fix: sed invocations to work out of the box on macOS
These fixes make the sed invocations run on macOS but I am not sure if they will break the GNU sed invocations in return…
* fix: add macOS branches to the shell scripts
The sed command line was difficult (impossible?) to be made portable so I just added macOS conditions.
* Prototype the solution using an alias
It seems that this will not work because I keep getting "sedi: command not found".
* fix: use a Bash function instead of an alias to run sed portably
This seems to work on my local so let's see if it runs in the CI on GitHub.
* fix: use 2 spaces like the original scripts did
Not sure why VS Code went with 4.
* fix: use sedi for the build-changelog `1i\` part as well
I am curious if Ubuntu will handle the newline…
* Add support for the Jekyll sample filter
See https://jekyllrb.com/docs/liquid/filters
I am sorting the array randomly and then picking the first N items or all items if there is no sample limit.
* Add tests for `push`
I thought `push` was broken because it doesn't work on the Playground but that's not the case. Here are the tests to prove it. Taken from the `concat` tests.
* Remove the sample experiment
This got in from another branch lol.
* Recommend the build:dist command over the whole build
This one works for me locally whereas build:docs is reporting some issues.
* Return the full `build` command and explain how to use `commitlint` to workshop the message
I am working on a PR to make `build` run on macOS because it is a part of the pre-commit hook anyway so all contributors should make it work for them.
I have also shown how to check your messages against `commitlint` from the CLI because it is faster than using the VS Code GUI.
* Add support for the Jekyll sample filter
See https://jekyllrb.com/docs/liquid/filters
I am sorting the array randomly and then picking the first N items or all items if there is no sample limit.
* Remove incorrect spaces before parens
Typo and copy-paste meet
* docs: add echo and liquid tags chinese translation
* Update docs/source/zh-cn/tags/echo.md
Co-authored-by: Jun Yang <[email protected]>
* Update docs/source/zh-cn/tags/echo.md
Co-authored-by: Jun Yang <[email protected]>
* Update docs/source/zh-cn/tags/echo.md
Co-authored-by: Jun Yang <[email protected]>
* Update Liquid.md
* Update Liquid.md
Co-authored-by: Jun Yang <[email protected]>
- `relativeReference` is enabled by default, set to `false` to disable
- Referenced files are still constrained within root/partias/layouts
- fix: relative filenames are not constrained (which allows arbitrary filesystem read)
Example Usage:
{% render "../foo/bar.html" %}
Note:
../foo/bar.html' should also be within `partials` (or `root` if `partials` not set)
* fix: spelling
* fix: respect param order for reversed
* docs: add for-reversed order details
* perf: improve performance by 4x by simplified parseFile
BREAKING CHANGES:
- previously deprecated `getTemplate()` and `getTemplateSync()` not no longer supported
- `opts` no longer support dynamic set in `parseFile()`, `renderFile()` arguments
* perf: parse filenames in parse() insteadof render()
* docs: update description of LiquidJS
Co-authored-by: harttle <[email protected]>
- previously deprecated `getTemplate()` and `getTemplateSync()` not no longer supported
- `opts` no longer support dynamic set in `parseFile()`, `renderFile()` arguments
* fix: enumerate Promise<array> (e.g. in {% for ... %})
Previously, a Promise of an array was not being enumerated in
{% for %}, for example. This is misleading since the library
handles promises elsewhere (e.g. if you {% assign x = promiseArray %}
and then {% for v in x %}, it worked just fine.
This PR makes Promises of arrays handled by changing toEnumerable
to handle then-ables. This affects other iterators, too, e.g. tablerow,
so I put in a test for that as well.
In this diff I fixed es modules distribution for bundlers.
Before we had two problems
- bundlers use "module" field to find es module build
- bundlers cannot use provided es module with node target
In this diff I addressed both of them. Now "main" and "module" fields
points to "node" specific versions. "browser" field provides aliases
with browser compatible builds.
All modern browsers support both "module" and "browser" fields.
simply remove unused dependencies fixes this issue, but I removed
all package-lock.json / yarn.lock since the demo should always be
in sync with the codebase
BREAKING CHANGE: ship to Node.js 8, the dist/liquid.cjs.js (main) nolonger
supports Node.js 6, other bundles are also provided via dist/liquid.esm.js, dist/liquid.js (ES5 umd) and liquid.min.js (minified ES5 umd)
A simple, expressive and safe [Shopify][shopify/liquid] / GitHub Pages compatible template engine in pure JavaScript.
**The purpose of this repo** is to provide a standard Liquid implementation for the JavaScript community so that [Jekyll sites](https://jekyllrb.com), [GitHub Pages](https://pages.github.com/) and [Shopify templates](https://themes.shopify.com/) can be ported to Node.js without pain.
This is a liquid implementation for both Node.js and browsers. Website: <http://harttle.github.io/liquidjs/>, Live Demo: <https://jsfiddle.net/6u40xbzs/>
* [Documentation][doc]
* Please star [LiquidJS on GitHub][github]!
* Financial support via [GitHub Sponsors](https://github.com/sponsors/harttle).
* Fully compatible to [shopify][shopify/liquid], with all [tags][tags] and [filters][filters] implemented
* Support layout(extend) and include syntax
* In pure JavaScript with Promise-based API
## What's it like?
**Differences**
Basically there're two types of Liquid syntax: tags enclosed by `{% %}` and outputs enclosed by `{{ }}`. A Liquid template looks like:
Though being compatible with [Ruby Liquid](https://github.com/shopify/liquid) is one of our priorities, there're still certain differences. You may need some configuration to get it compatible in these senarios:
* Dynamic file locating (enabled by default), that means layout/partial names are treated as variables in liquidjs. See [#51](https://github.com/harttle/liquidjs/issues/51).
* Truthy and Falsy. All values except `undefined`, `null`, `false` are truthy, whereas in Ruby Liquid all except `nil` and `false` are truthy. See [#26](https://github.com/harttle/liquidjs/pull/26).
* Number Rendering. Since JavaScript do not distinguish `float` and `integer`, we cannot either convert between them nor render regarding to their type. See [#59](https://github.com/harttle/liquidjs/issues/59).
* [.to_liquid()](https://github.com/Shopify/liquid/wiki/Introduction-to-Drops) is replaced by `.toLiquid()`
* [.to_s()](https://www.rubydoc.info/gems/liquid/Liquid/Drop) is replaced by JavaScript `.toString()`
[A live demo](https://liquidjs.com/playground.html) is also available and here's a [quick tutorial](https://liquidjs.com/tutorials/intro-to-liquid.html) for Liquid syntax.
For more details, refer to the [Setup Guide][setup].
```javascript
varengine=newLiquid({
root:path.resolve(__dirname,'views/'),// dirs to lookup layouts/includes
extname:'.liquid'// the extname used for layouts/includes, defaults ""
});
engine.renderFile("hello.liquid",{name:'alice'})
.then(console.log)// outputs "Alice"
## Who's Using LiquidJS?
// which is equivalent to:
engine
.renderFile("hello",{name:'alice'})
.then(console.log)// outputs "Alice"
```
- [Eleventy](https://www.11ty.dev/): Eleventy, a simpler static site generator.
- [Opensense](https://www.opensense.com/): The smarter way to send email.
- [Directus](https://docs.directus.io/): an instant REST+GraphQL API and intuitive no-code data collaboration app for any SQL database.
- [Semgrep](https://github.com/returntocorp/semgrep): Lightweight static analysis for many languages.
- [Rock](https://www.rockrms.com/): An open source CMS, Relationship Management System (RMS) and Church Management System (ChMS) all rolled into one.
- [Mitosis](https://github.com/BuilderIO/mitosis): Write components once, run everywhere. Compiles to React, Vue, Qwik, Solid, Angular, Svelte, and more.
- [Pattern Lab](https://patternlab.io/): a frontend workshop environment that helps you build, view, test, and showcase your design system's UI components.
- [Builder.io](https://www.builder.io/m/developers): the first and only headless CMS with a visual editor that lets you drag and drop with your components, directly within your current site or app. Completely API-driven, for cleaner code and simpler workflows.
- [Microsoft Power Pages](https://learn.microsoft.com/en-us/power-pages/introduction): a secure, enterprise-grade, low-code software as a service (SaaS) platform for creating, hosting, and administering modern external-facing business websites.
- [Azure API Management developer portal](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-developer-portal): an automatically generated, fully customizable website with the documentation of your APIs.
- [WISMOlabs](https://wismolabs.com/): Post Purchase Experience platform for eCommerce retailers enhancing customer satisfaction by using LiquidJS to provide customizable post-purchase experiences through programmable email, SMS, order tracking pages, and webhooks.
## Use with Express.js
Feel free to create a PR or contact me to add your use case into this list!
```javascript
// register liquid engine
app.engine('liquid',engine.express());
app.set('views','./views');// specify the views directory
app.set('view engine','liquid');// set to default
```
## Financial Support
[Here](demo/express/)'s an Express demo. When used with Express.js,
Express [`views`][express-views] will be included when looking up
partials(includes and layouts).
If you personally love LiquidJS or it's benefiting your business, please consider financially support us via [GitHub Sponsors](https://github.com/sponsors/harttle). Special thanks to our sponsors!
* block name is optional when there's only one block.
## Options
The full list of options for `Liquid()` is listed as following:
*`root` is a directory or an array of directories to resolve layouts and includes, as well as the filename passed in when calling `.renderFile()`.
If an array, the files are looked up in the order they occur in the array.
Defaults to `["."]`
*`extname` is used to lookup the template file when filepath doesn't include an extension name. Eg: setting to `".html"` will allow including file by basename. Defaults to `""`.
*`cache` indicates whether or not to cache resolved templates. Defaults to `false`.
*`dynamicPartials`: if set, treat `<filepath>` parameter in `{%include filepath %}`, `{%layout filepath%}` as a variable, otherwise as a literal value. Defaults to `true`.
*`strictFilters` is used to enable strict filter existence. If set to `false`, undefined filters will be rendered as empty string. Otherwise, undefined filters will cause an exception. Defaults to `false`.
*`strictVariables` is used to enable strict variable derivation.
If set to `false`, undefined variables will be rendered as empty string.
Otherwise, undefined variables will cause an exception. Defaults to `false`.
*`trimTagRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`.
*`trimTagLeft` is similiar to `trimTagRight`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
*`trimOutputRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`.
*`trimOutputLeft` is similiar to `trimOutputRight`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
*`tagDelimiterLeft` and `tagDelimiterRight` are used to override the delimiter for liquid tags.
*`outputDelimiterLeft` and `outputDelimiterRight` are used to override the delimiter for liquid outputs.
*`greedy` is used to specify whether `trim*Left`/`trim*Right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`.
## Register Filters
```javascript
// Usage: {{ name | uppper }}
engine.registerFilter('upper',v=>v.toUpperCase())
```
Filter arguments will be passed to the registered filter function, for example:
*`parse`: Read tokens from `remainTokens` until your end token.
*`render`: Combine scope data with your parsed tokens into HTML string.
See existing tag implementations here: <https://github.com/harttle/liquidjs/tree/master/src/builtin/tags>
## Plugin API
A pack of tags or filters can be encapsulated into a **plugin**, which will be typically installed via npm.
```javascript
engine.plugin(require('./some-plugin'));
// some-plugin.js
module.exports=function(Liquid){
// here `this` refers to the engine instance
// `Liquid` provides facilities to implement tags and filters
this.registerFilter('foo',x=>x);
}
```
Plugin List:
* To add your plugin, contact me or simply send a PR.
## Contribute Guidelines
This repo uses [eslint](https://eslint.org/) to check code style, [semantic-release](https://github.com/semantic-release/semantic-release) to generate changelog and publish to npm and Github Releases.
* Code Style: <https://github.com/standard/eslint-config-standard>, `npm run lint` to check locally.
Only the latest major version is supported with security updates. It can be changed if many people are relying on a specific version for some reason. If this is the case, welcome to file an issue.
## Reporting a Vulnerability
Please contact yangjvn@126.com to report a vulnerability or change request.
- If the vulnerability in question affects common use cases, it will be treated as a bug and fixed very soon (typically within 1 week).
- Otherwise, it'll be scheduled in the same priority of feature request (which is lower than bugs).
- If the request is declined, you'll receive a reply email anyway (most likely there will be a discussion).
<p>Lorem ipsum dolor sit amet, falli detraxit facilisis sit ex. Nec vidit nihil ut, vis utamur definitionem in. Ancillae phaedrum ut eos. Ne eam errem cotidieque.
</p>
<p>
Sit amet vitae referrentur ad, oportere necessitatibus vituperatoribus vim ne. Audiam quaeque nusquam ei eos, mel ex adhuc prompta complectitur. Decore voluptua cotidieque vel ei, veri novum persecuti te sea. Nisl novum sea cu. Dicta delicatissimi ut est. Et has eripuit impedit mediocrem.
</p>
<p>
Eu vim evertitur argumentum, pro legendos iudicabit voluptatibus ne. Ne alii nullam deserunt duo, vis no animal verterem. Ne quo veniam euripidis. Pri discere mentitum vituperatoribus ne. Meliore corrumpit vim at, has ea admodum convenire.
</p>
<p>
Ne mea alii detraxit electram, his ne epicurei gloriatur consetetur. Ex pro aeque omnes appareat, possit integre accommodare eu quo. Qui in porro molestiae, no sit equidem petentium patrioque, omnes voluptaria vim te. Odio quot rebum ad sed, ei sale reque inani sea.
</p>
<p>
At mea vidit petentium, mei lorem pertinacia signiferumque ne. Per eu dicam postea probatus, sea pericula accusamus omittantur ad. Id mei munere ullamcorper. Oportere ocurreret cu vel. Pri ne dicant soluta graecis, duis ponderum corrumpit sed eu, pro ei rebum vivendum.
</p>
<p>
Eum ea exerci sententiae constituam, ut lorem putant volutpat pro. Vix ex iudicabit salutatus principes, pri nisl erat ut, ne cum persius verterem phaedrum. Vix mundi vitae eu. Vel summo vocent albucius in. Qui omnis partem possim ex, wisi doctus efficiantur cu has. Aperiri denique ea pri, cum dissentias signiferumque eu. Per posse dissentiet necessitatibus id, omnis eleifend te mel.
</p>
<p>
Phaedrum erroribus adolescens ut nec, duo mutat viris id. In tale purto dolores sit, ei consul inermis est, his ea movet expetenda. Cibo scribentur id eam, per an quem iracundia, has erat zril solet eu. Falli fierent ne cum, eam placerat facilisis suscipiantur te. Id quo dicat tractatos definiebas, est copiosae splendide id.
</p>
<p>
Constituto neglegentur qui ne, eum ne putent phaedrum, no quod nominati consulatu per. Mei cu accusam principes interesset, vim fugit abhorreant eu, ludus feugait an sed. Clita expetendis definitionem has in, meis pericula no mea, soluta nemore cotidieque eos cu. Summo populo signiferumque pri eu, eum no labores democritum posidonium, pro ignota adipisci in. Tollit molestie id mei.
</p>
<p>
Ipsum impetus et eam, ei his epicuri instructior. Impedit ullamcorper vim an. Impedit ullamcorper vim an. Et eum senserit sententiae reprimique, quem detracto sententiae at sed, no inermis ocurreret rationibus sea pericula no.
@@ -381,7 +381,7 @@ This works for any library, not just `react-router-dom`.
## Importing a Component
This project setup supports ES6 modules thanks to Webpack.<br>
While you can still use `require()` and `module.exports`, we encourage you to use [`import` and `export`](http://exploringjs.com/es6/ch_modules.html) instead.
While you can still use `require()` and `module.exports`, we encourage you to use [`import` and `export`](https://exploringjs.com/es6/ch_modules.html) instead.
For example:
@@ -414,7 +414,7 @@ class DangerButton extends Component {
exportdefaultDangerButton;
```
Be aware of the [difference between default and named exports](http://stackoverflow.com/questions/36795819/react-native-es-6-when-should-i-use-curly-braces-for-import/36796281#36796281). It is a common source of mistakes.
Be aware of the [difference between default and named exports](https://stackoverflow.com/questions/36795819/react-native-es-6-when-should-i-use-curly-braces-for-import/36796281#36796281). It is a common source of mistakes.
We suggest that you stick to using default imports and exports when a module only exports a single thing (for example, a component). That’s what you get when you use `export default Button` and `import Button from './Button'`.
@@ -422,15 +422,15 @@ Named exports are useful for utility modules that export several functions. A mo
Learn more about ES6 modules:
- [When to use the curly braces?](http://stackoverflow.com/questions/36795819/react-native-es-6-when-should-i-use-curly-braces-for-import/36796281#36796281)
- [When to use the curly braces?](https://stackoverflow.com/questions/36795819/react-native-es-6-when-should-i-use-curly-braces-for-import/36796281#36796281)
Instead of downloading the entire app before users can use it, code splitting allows you to split your code into small chunks which you can then load on demand.
This project setup supports code splitting via [dynamic `import()`](http://2ality.com/2017/01/import-operator.html#loading-code-on-demand). Its [proposal](https://github.com/tc39/proposal-dynamic-import) is in stage 3. The `import()` function-like form takes the module name as an argument and returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which always resolves to the namespace object of the module.
This project setup supports code splitting via [dynamic `import()`](https://2ality.com/2017/01/import-operator.html#loading-code-on-demand). Its [proposal](https://github.com/tc39/proposal-dynamic-import) is in stage 3. The `import()` function-like form takes the module name as an argument and returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which always resolves to the namespace object of the module.
Here is an example:
@@ -476,7 +476,7 @@ You can also use it with `async` / `await` syntax if you prefer it.
### With React Router
If you are using React Router check out [this tutorial](http://serverless-stack.com/chapters/code-splitting-in-create-react-app.html) on how to use code splitting with it. You can find the companion GitHub repository [here](https://github.com/AnomalyInnovations/serverless-stack-demo-client/tree/code-splitting-in-create-react-app).
If you are using React Router check out [this tutorial](https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html) on how to use code splitting with it. You can find the companion GitHub repository [here](https://github.com/AnomalyInnovations/serverless-stack-demo-client/tree/code-splitting-in-create-react-app).
Also check out the [Code Splitting](https://reactjs.org/docs/code-splitting.html) section in React documentation.
@@ -602,7 +602,7 @@ This project setup minifies your CSS and adds vendor prefixes to it automaticall
Support for new CSS features like the [`all` property](https://developer.mozilla.org/en-US/docs/Web/CSS/all), [`break` properties](https://www.w3.org/TR/css-break-3/#breaking-controls), [custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables), and [media query ranges](https://www.w3.org/TR/mediaqueries-4/#range-context) are automatically polyfilled to add support for older browsers.
You can customize your target support browsers by adjusting the `browserslist` key in `package.json` accoring to the [Browserslist specification](https://github.com/browserslist/browserslist#readme).
You can customize your target support browsers by adjusting the `browserslist` key in `package.json` according to the [Browserslist specification](https://github.com/browserslist/browserslist#readme).
For example, this:
@@ -671,7 +671,7 @@ This works in CSS too:
}
```
Webpack finds all relative module references in CSS (they start with `./`) and replaces them with the final paths from the compiled bundle. If you make a typo or accidentally delete an important file, you will see a compilation error, just like when you import a non-existent JavaScript module. The final filenames in the compiled bundle are generated by Webpack from content hashes. If the file content changes in the future, Webpack will give it a different name in production so you don’t need to worry about long-term caching of assets.
Webpack finds all relative module references in CSS (they start with `./`) and replaces them with the final paths from the compiled bundle. If you make a typo or accidentally delete an important file, you will see a compilation error, just like when you import a nonexistent JavaScript module. The final filenames in the compiled bundle are generated by Webpack from content hashes. If the file content changes in the future, Webpack will give it a different name in production so you don’t need to worry about long-term caching of assets.
Please be advised that this is also a custom feature of Webpack.
@@ -755,7 +755,7 @@ The `public` folder is useful as a workaround for a number of less common cases:
- You need a file with a specific name in the build output, such as [`manifest.webmanifest`](https://developer.mozilla.org/en-US/docs/Web/Manifest).
- You have thousands of images and need to dynamically reference their paths.
- You want to include a small script like [`pace.js`](http://github.hubspot.com/pace/docs/welcome/) outside of the bundled code.
- You want to include a small script like [`pace.js`](https://github.hubspot.com/pace/docs/welcome/) outside of the bundled code.
- Some library may be incompatible with Webpack and you have no other option but to include it as a `<script>` tag.
Note that if you add a `<script>` that declares global variables, you also need to read the next section on using them.
@@ -813,7 +813,7 @@ Now you are ready to use the imported reactstrap components within your componen
Sometimes you might need to tweak the visual styles of Bootstrap (or equivalent package).<br>
As of `[email protected]` you can import `.scss` files. This makes it possible to use a package's built-in Sass variables for global style preferences.
To customize Bootstrap, create a file called `src/custom.scss` (or similar) and import the Bootstrap source stylesheet. Add any overrides _before_ the imported file(s). You can reference [Bootstrap's documentation](http://getbootstrap.com/docs/4.1/getting-started/theming/#css-variables) for the names of the available variables.
To customize Bootstrap, create a file called `src/custom.scss` (or similar) and import the Bootstrap source stylesheet. Add any overrides _before_ the imported file(s). You can reference [Bootstrap's documentation](https://getbootstrap.com/docs/4.1/getting-started/theming/#css-variables) for the names of the available variables.
```scss
// Override default variables before the import
@@ -1138,7 +1138,7 @@ To tell the development server to proxy any unknown requests to your API server
This way, when you `fetch('/api/todos')` in development, the development server will recognize that it’s not a static asset, and will proxy your request to `http://localhost:4000/api/todos` as a fallback. The development server will **only** attempt to send requests without `text/html` in its `Accept` header to the proxy.
Conveniently, this avoids [CORS issues](http://stackoverflow.com/questions/21854516/understanding-ajax-cors-and-security-considerations) and error messages like this in development:
Conveniently, this avoids [CORS issues](https://stackoverflow.com/questions/21854516/understanding-ajax-cors-and-security-considerations) and error messages like this in development:
```
Fetch API cannot load http://localhost:4000/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
@@ -1150,7 +1150,7 @@ The `proxy` option supports HTTP, HTTPS and WebSocket connections.<br>
If the `proxy` option is **not** flexible enough for you, alternatively you can:
- [Configure the proxy yourself](#configuring-the-proxy-manually)
- Enable CORS on your server ([here’s how to do it for Express](http://enable-cors.org/server_expressjs.html)).
- Enable CORS on your server ([here’s how to do it for Express](https://enable-cors.org/server_expressjs.html)).
- Use [environment variables](#adding-custom-environment-variables) to inject the right server host and port into your app.
### "Invalid Host Header" Errors After Configuring Proxy
@@ -1324,7 +1324,7 @@ When you run `npm test`, Jest will launch in the watch mode. Every time you save
The watcher includes an interactive command-line interface with the ability to run all tests, or focus on a search pattern. It is designed this way so that you can keep it open and enjoy fast re-runs. You can learn the commands from the “Watch Usage” note that the watcher prints after every run:
@@ -1373,7 +1373,7 @@ This test mounts a component and makes sure that it didn’t throw during render
When you encounter bugs caused by changing components, you will gain a deeper insight into which parts of them are worth testing in your application. This might be a good time to introduce more specific tests asserting specific expected output or behavior.
If you’d like to test components in isolation from the child components they render, we recommend using [`shallow()` rendering API](http://airbnb.io/enzyme/docs/api/shallow.html) from [Enzyme](http://airbnb.io/enzyme/). To install it, run:
If you’d like to test components in isolation from the child components they render, we recommend using [`shallow()` rendering API](https://airbnb.io/enzyme/docs/api/shallow.html) from [Enzyme](https://airbnb.io/enzyme/). To install it, run:
@@ -1412,9 +1412,9 @@ it('renders without crashing', () => {
});
```
Unlike the previous smoke test using `ReactDOM.render()`, this test only renders `<App>` and doesn’t go deeper. For example, even if `<App>` itself renders a `<Button>` that throws, this test will pass. Shallow rendering is great for isolated unit tests, but you may still want to create some full rendering tests to ensure the components integrate correctly. Enzyme supports [full rendering with `mount()`](http://airbnb.io/enzyme/docs/api/mount.html), and you can also use it for testing state changes and component lifecycle.
Unlike the previous smoke test using `ReactDOM.render()`, this test only renders `<App>` and doesn’t go deeper. For example, even if `<App>` itself renders a `<Button>` that throws, this test will pass. Shallow rendering is great for isolated unit tests, but you may still want to create some full rendering tests to ensure the components integrate correctly. Enzyme supports [full rendering with `mount()`](https://airbnb.io/enzyme/docs/api/mount.html), and you can also use it for testing state changes and component lifecycle.
You can read the [Enzyme documentation](http://airbnb.io/enzyme/) for more testing techniques. Enzyme documentation uses Chai and Sinon for assertions but you don’t have to use them because Jest provides built-in `expect()` and `jest.fn()` for spies.
You can read the [Enzyme documentation](https://airbnb.io/enzyme/) for more testing techniques. Enzyme documentation uses Chai and Sinon for assertions but you don’t have to use them because Jest provides built-in `expect()` and `jest.fn()` for spies.
Here is an example from Enzyme documentation that asserts specific output, rewritten to use Jest matchers:
All Jest matchers are [extensively documented here](http://facebook.github.io/jest/docs/en/expect.html).<br>
Nevertheless you can use a third-party assertion library like [Chai](http://chaijs.com/) if you want to, as described below.
All Jest matchers are [extensively documented here](https://facebook.github.io/jest/docs/en/expect.html).<br>
Nevertheless you can use a third-party assertion library like [Chai](https://chaijs.com/) if you want to, as described below.
Additionally, you might find [jest-enzyme](https://github.com/blainekasten/enzyme-matchers) helpful to simplify your tests with readable matchers. The above `contains` code can be written more simply with jest-enzyme.
@@ -1462,7 +1462,7 @@ import 'jest-enzyme';
We recommend that you use `expect()` for assertions and `jest.fn()` for spies. If you are having issues with them please [file those against Jest](https://github.com/facebook/jest/issues/new), and we’ll fix them. We intend to keep making them better for React, supporting, for example, [pretty-printing React elements as JSX](https://github.com/facebook/jest/pull/1566).
However, if you are used to other libraries, such as [Chai](http://chaijs.com/) and [Sinon](http://sinonjs.org/), or if you have existing code using them that you’d like to port over, you can import them normally like this:
However, if you are used to other libraries, such as [Chai](https://chaijs.com/) and [Sinon](https://sinonjs.org/), or if you have existing code using them that you’d like to port over, you can import them normally like this:
```js
importsinonfrom'sinon';
@@ -1509,7 +1509,7 @@ Similarly, `fit()` lets you focus on a specific test without running any other t
Jest has an integrated coverage reporter that works well with ES6 and requires no configuration.<br>
Run `npm test -- --coverage` (note extra `--` in the middle) to include a coverage report like this:
- [`TestUtils.renderIntoDocument()`](https://facebook.github.io/react/docs/test-utils.html#renderintodocument) ([a shortcut](https://github.com/facebook/react/blob/34761cf9a252964abfaab6faf74d473ad95d1f21/src/test/ReactTestUtils.js#L83-L91) for the above)
- [`mount()`](http://airbnb.io/enzyme/docs/api/mount.html) in [Enzyme](http://airbnb.io/enzyme/index.html)
- [`mount()`](https://airbnb.io/enzyme/docs/api/mount.html) in [Enzyme](https://airbnb.io/enzyme/index.html)
In contrast, **jsdom is not needed** for the following APIs:
- [`shallow()`](http://airbnb.io/enzyme/docs/api/shallow.html) in [Enzyme](http://airbnb.io/enzyme/index.html)
- [`shallow()`](https://airbnb.io/enzyme/docs/api/shallow.html) in [Enzyme](https://airbnb.io/enzyme/index.html)
Finally, jsdom is also not needed for [snapshot testing](http://facebook.github.io/jest/blog/2016/07/27/jest-14.html).
Finally, jsdom is also not needed for [snapshot testing](https://facebook.github.io/jest/blog/2016/07/27/jest-14.html).
### Snapshot Testing
Snapshot testing is a feature of Jest that automatically generates text snapshots of your components and saves them on the disk so if the UI output changes, you get notified without manually writing any assertions on the component output. [Read more about snapshot testing.](http://facebook.github.io/jest/blog/2016/07/27/jest-14.html)
Snapshot testing is a feature of Jest that automatically generates text snapshots of your components and saves them on the disk so if the UI output changes, you get notified without manually writing any assertions on the component output. [Read more about snapshot testing.](https://facebook.github.io/jest/blog/2016/07/27/jest-14.html)
### Editor Integration
@@ -1735,7 +1735,7 @@ Usually, it’s hard to see these states without running a sample app or some ex
Create React App doesn’t include any tools for this by default, but you can easily add [Storybook for React](https://storybook.js.org) ([source](https://github.com/storybooks/storybook)) or [React Styleguidist](https://react-styleguidist.js.org/) ([source](https://github.com/styleguidist/react-styleguidist)) to your project. **These are third-party tools that let you develop components and see all their states in isolation from your app**.


You can also deploy your Storybook or style guide as a static app. This way, everyone in your team can view and review different states of UI components without starting a backend server or creating an account in your app.
@@ -1820,7 +1820,7 @@ following in their [`src/index.js`](src/index.js) file:
```js
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
```
@@ -1854,7 +1854,7 @@ following into account:
1. Service workers [require HTTPS](https://developers.google.com/web/fundamentals/getting-started/primers/service-workers#you_need_https),
although to facilitate local testing, that policy
[does not apply to `localhost`](http://stackoverflow.com/questions/34160509/options-for-testing-service-workers-via-http/34161385#34161385).
[does not apply to `localhost`](https://stackoverflow.com/questions/34160509/options-for-testing-service-workers-via-http/34161385#34161385).
If your production web server does not support HTTPS, then the service worker
registration will fail, but the rest of your web app will remain functional.
@@ -1970,7 +1970,7 @@ serve -h
You don’t necessarily need a static server in order to run a Create React App project in production. It works just as fine integrated into an existing dynamic one.
Here’s a programmatic example using [Node](https://nodejs.org/) and [Express](http://expressjs.com/):
Here’s a programmatic example using [Node](https://nodejs.org/) and [Express](https://expressjs.com/):
```javascript
constexpress=require('express');
@@ -2018,7 +2018,7 @@ If you’re using [Apache HTTP Server](https://httpd.apache.org/), you need to c
It will get copied to the `build` folder when you run `npm run build`.
If you’re using [Apache Tomcat](http://tomcat.apache.org/), you need to follow [this Stack Overflow answer](https://stackoverflow.com/a/41249464/4878474).
If you’re using [Apache Tomcat](https://tomcat.apache.org/), you need to follow [this Stack Overflow answer](https://stackoverflow.com/a/41249464/4878474).
Now requests to `/todos/42` will be handled correctly both in development and in production.
@@ -2029,7 +2029,7 @@ service worker navigation routing can be configured or disabled by
[`eject`ing](#npm-run-eject) and then modifying the
and [`navigateFallbackWhitelist`](https://github.com/GoogleChrome/sw-precache#navigatefallbackwhitelist-arrayregexp)
options of the `SWPreachePlugin` [configuration](../config/webpack.config.prod.js).
options of the `SWPrecachePlugin` [configuration](../config/webpack.config.prod.js).
When users install your app to the homescreen of their device the default configuration will make a shortcut to `/index.html`. This may not work for client-side routers which expect the app to be served from `/`. Edit the web app manifest at [`public/manifest.json`](public/manifest.json) and change `start_url` to match the required URL scheme, for example:
@@ -2043,7 +2043,7 @@ By default, Create React App produces a build assuming your app is hosted at the
To override this, specify the `homepage` in your `package.json`, for example:
```js
"homepage":"http://mywebsite.com/relativepath",
"homepage":"https://example.com/relativepath",
```
This will let Create React App correctly infer the root path to use in the generated HTML file.
@@ -2068,7 +2068,7 @@ If you are not using the HTML5 `pushState` history API or not using client-side
"homepage":".",
```
This will make sure that all the asset paths are relative to `index.html`. You will then be able to move your app from `http://mywebsite.com` to `http://mywebsite.com/relativepath` or even `http://mywebsite.com/relative/path` without having to rebuild it.
This will make sure that all the asset paths are relative to `index.html`. You will then be able to move your app from `https://example.com` to `https://example.com/relativepath` or even `https://example.com/relative/path` without having to rebuild it.
### Customizing Environment Variables for Arbitrary Build Environments
@@ -2077,7 +2077,7 @@ You can create an arbitrary build environment by creating a custom `.env` file a
For example, to create a build environment for a staging environment:
1. Create a file called `.env.staging`
1. Set environment variables as you would any other `.env` file (e.g. `REACT_APP_API_URL=http://api-staging.example.com`)
1. Set environment variables as you would any other `.env` file (e.g. `REACT_APP_API_URL=https://api-staging.example.com`)
@@ -2268,14 +2268,14 @@ You can configure a custom domain with GitHub Pages by adding a `CNAME` file to
Your CNAME file should look like this:
```
mywebsite.com
example.com
```
#### Notes on client-side routing
GitHub Pages doesn’t support routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`). This is because when there is a fresh page load for a url like `http://user.github.io/todomvc/todos/42`, where `/todos/42` is a frontend route, the GitHub Pages server returns 404 because it knows nothing of `/todos/42`. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions:
GitHub Pages doesn’t support routers that use the HTML5 `pushState` history API under the hood (for example, React Router using `browserHistory`). This is because when there is a fresh page load for a url like `https://user.github.io/todomvc/todos/42`, where `/todos/42` is a frontend route, the GitHub Pages server returns 404 because it knows nothing of `/todos/42`. If you want to add a router to a project hosted on GitHub Pages, here are a couple of solutions:
- You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `hashHistory` for this effect, but the URL will be longer and more verbose (for example, `http://user.github.io/todomvc/#/todos/42?_k=yknaj`). [Read more](https://reacttraining.com/react-router/web/api/Router) about different history implementations in React Router.
- You could switch from using HTML5 history API to routing with hashes. If you use React Router, you can switch to `hashHistory` for this effect, but the URL will be longer and more verbose (for example, `https://user.github.io/todomvc/#/todos/42?_k=yknaj`). [Read more](https://reacttraining.com/react-router/web/api/Router) about different history implementations in React Router.
- Alternatively, you can use a trick to teach GitHub Pages to handle 404 by redirecting to your `index.html` page with a special redirect parameter. You would need to add a `404.html` file with the redirection code to the `build` folder before deploying your project, and you’ll need to add code handling the redirect parameter to `index.html`. You can find a detailed explanation of this technique [in this guide](https://github.com/rafrex/spa-github-pages).
#### Troubleshooting
@@ -2317,7 +2317,7 @@ MyDirectory in /tmp/build_1234/src
It means you need to ensure that the lettercase of the file or directory you `import` matches the one you see on your filesystem or on GitHub.
This is important because Linux (the operating system used by Heroku) is casesensitive. So `MyDirectory` and `mydirectory` are two distinct directories and thus, even though the project builds locally, the difference in case breaks the `import` statements on Heroku remotes.
This is important because Linux (the operating system used by Heroku) is case-sensitive. So `MyDirectory` and `mydirectory` are two distinct directories and thus, even though the project builds locally, the difference in case breaks the `import` statements on Heroku remotes.
##### "Could not find a required file."
@@ -2442,7 +2442,7 @@ We recommend deleting `node_modules` in your project and running `npm install` (
It is reported that installing Watchman 4.7.0 or newer fixes the issue. If you use [Homebrew](http://brew.sh/), you can run these commands to update it:
It is reported that installing Watchman 4.7.0 or newer fixes the issue. If you use [Homebrew](https://brew.sh/), you can run these commands to update it:
```
watchman shutdown-server
@@ -2466,7 +2466,7 @@ If you are completely sure that you didn't terminate the process, consider [addi
### `npm run build` fails on Heroku
This may be a problem with casesensitive filenames.
This may be a problem with case-sensitive filenames.
Please refer to [this section](#resolving-heroku-deployment-errors).
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.