diff --git a/docs/404.md b/docs/404.md new file mode 100644 index 000000000..75ed8f44c --- /dev/null +++ b/docs/404.md @@ -0,0 +1,7 @@ +# 404 Not Found + +Oops, the page you requested cannot be found. + +The URL may be misspelled or the page you're looking for is no longer available. + +Go to the [home page](https://mithril.js.org). diff --git a/docs/changelog.md b/docs/changelog.md index 790de1804..88b379430 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -25,6 +25,7 @@ Official change log for Mithril.js PSA: changes to [`mithril/stream`](stream.md) are now specified in this changelog. I've also moved the old stream changelog into this file [here](#mithril-stream-change-log). +- Updated web design, fixed most obvious UX, UI, and design flaws, fixed obviously incorrect content [@tbreuss](https://github.com/tbreuss) - Added `m.Fragment = "["` for an easier time with JSX setups. ([#2744](https://github.com/MithrilJS/mithril.js/pull/2744) [@dead-claudia](https://github.com/dead-claudia)) - Reduced package download size substantially by removing the archive of previous releases' documentation. ([#2561](https://github.com/MithrilJS/mithril.js/pull/2561) [@cztomsik](https://github.com/cztomsik)) - Improved error messages in multiple places. ([#2536](https://github.com/MithrilJS/mithril.js/pull/2536) [@dead-claudia](https://github.com/dead-claudia)) diff --git a/docs/code-of-conduct.md b/docs/code-of-conduct.md index 5c392e9bd..ea308da15 100644 --- a/docs/code-of-conduct.md +++ b/docs/code-of-conduct.md @@ -4,7 +4,7 @@ Code of Conduct Covenant for contributors to the Mithril.js project # Contributor Covenant Code of Conduct -## Our Pledge +### Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and @@ -13,7 +13,7 @@ size, disability, ethnicity, gender identity and expression, level of experience nationality, personal appearance, race, religion, or sexual identity and orientation. -## Our Standards +### Our Standards Examples of behavior that contributes to creating a positive environment include: @@ -35,7 +35,7 @@ advances * Other conduct which could reasonably be considered inappropriate in a professional setting -## Our Responsibilities +### Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in @@ -47,7 +47,7 @@ that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. -## Scope +### Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of @@ -56,7 +56,7 @@ address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. -## Enforcement +### Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [contact@claudiameadows.dev](mailto:contact@claudiameadows.dev?subject=Mithril%20Code%20of%20Conduct). All @@ -71,7 +71,7 @@ members of the project's leadership. As a general policy, we generally do not disclose any particular action taken in accordance with this Code of Conduct beyond those who need to know. -## Attribution +### Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] diff --git a/docs/contributing.md b/docs/contributing.md index d6b7c74ba..af2dab86a 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -3,36 +3,34 @@ Contribution guide for Mithril.js --> # Contributing FAQs +Contribution guide for Mithril.js. + - [How do I go about contributing ideas or new features?](#how-do-i-go-about-contributing-ideas-or-new-features?) - [How should I report bugs?](#how-should-i-report-bugs?) - [How do I send a pull request?](#how-do-i-send-a-pull-request?) - [I'm submitting a PR. How do I run tests?](#i'm-submitting-a-pr-how-do-i-run-tests?) -- [How do I build Mithril.js?](#how-do-i-build-mithril?) +- [How do I build Mithril.js?](#how-do-i-build-mithriljs?) - [Is there a style guide?](#is-there-a-style-guide?) -- [How do I embed live previews in docs?](#how-do-I-embed-live-previews-in-docs?) +- [How do I embed live previews in docs?](#how-do-i-embed-live-previews-in-docs?) - [Why do tests mock the browser APIs?](#why-do-tests-mock-the-browser-apis?) -- [Why does Mithril.js use its own testing framework and not Mocha/Jasmine/Tape?](#why-does-mithril-use-its-own-testing-framework-and-not-mochajasminetape?) -- [Why doesn't the Mithril.js codebase use ES6 via Babel or Bublé? Would a PR to upgrade be welcome?](#why-doesn't-the-mithril-codebase-use-es6-via-babel-or-bublé?-would-a-pr-to-upgrade-be-welcome?) -- [Why doesn't the Mithril.js codebase use trailing semi-colons? Would a PR to add them be welcome?](#why-doesn't-the-mithril-codebase-use-trailing-semi-colons?-would-a-pr-to-add-them-be-welcome?) -- [Why does the Mithril.js codebase use a mix of `instanceof` and `typeof` checks instead of `Object.prototype.toString.call`, `Array.isArray`, etc? Would a PR to refactor those checks be welcome?](#why-does-the-mithril-codebase-use-a-mix-of-instanceof-and-typeof-checks-instead-of-objectprototypetostringcall,-arrayisarray,-etc?-would-a-pr-to-refactor-those-checks-be-welcome?) -- [What should I know in advance when attempting a performance related contribution?](#What-should-I-know-in-advance-when-attempting-a-performance-related-contribution?) +- [Why does Mithril.js use its own testing framework and not Mocha/Jasmine/Tape?](#why-does-mithriljs-use-its-own-testing-framework-and-not-mochajasminetape?) +- [Why doesn't the Mithril.js codebase use ES6 via Babel or Bublé? Would a PR to upgrade be welcome?](#why-doesn't-the-mithriljs-codebase-use-es6-via-babel-or-bublé?-would-a-pr-to-upgrade-be-welcome?) +- [Why doesn't the Mithril.js codebase use trailing semi-colons? Would a PR to add them be welcome?](#why-doesn't-the-mithriljs-codebase-use-trailing-semi-colons?-would-a-pr-to-add-them-be-welcome?) +- [Why does the Mithril.js codebase use a mix of `instanceof` and `typeof` checks instead of `Object.prototype.toString.call`, `Array.isArray`, etc? Would a PR to refactor those checks be welcome?](#why-does-the-mithriljs-codebase-use-a-mix-of-instanceof-and-typeof-checks-instead-of-objectprototypetostringcall,-arrayisarray,-etc?-would-a-pr-to-refactor-those-checks-be-welcome?) +- [What should I know in advance when attempting a performance related contribution?](#what-should-i-know-in-advance-when-attempting-a-performance-related-contribution?) - [Do you all accept donations?](#do-you-all-accept-donations?) -## How do I go about contributing ideas or new features? +### How do I go about contributing ideas or new features? Create an [issue thread on GitHub](https://github.com/MithrilJS/mithril.js/issues/new) to suggest your idea so the community can discuss it. If the consensus is that it's a good idea, the fastest way to get it into a release is to send a pull request. Without a PR, the time to implement the feature will depend on the bandwidth of the development team and its list of priorities. - - -## How should I report bugs? +### How should I report bugs? Ideally, the best way to report bugs is to provide a small snippet of code where the issue can be reproduced (via jsfiddle, jsbin, a gist, etc). Even better would be to submit a pull request with a fix and tests. If you don't know how to test your fix, or lint or whatever, submit anyways, and we can help you. - - -## How do I send a pull request? +### How do I send a pull request? To send a pull request: @@ -45,80 +43,58 @@ To send a pull request: - push your changes to your fork - submit a pull request (go to the pull requests tab in GitHub, click the green button and select your feature branch) - - -## I'm submitting a PR. How do I run tests? +### I'm submitting a PR. How do I run tests? After having run `npm install` (a one-time operation), run `npm run test` from the command line to run all tests. While testing, you can modify a test to use `o.only(description, test)` instead of `o(description, test)` if you wish to run only a specific test to speed up your debugging experience. Don't forget to remove the `.only` after you're done! - - -## How do I build Mithril.js? +### How do I build Mithril.js? If all you're trying to do is run examples in the codebase, you don't need to build Mithril.js, you can just open the various html files and things should just work. To generate the bundled file for testing, run `npm run dev` from the command line. To generate the minified file, run `npm run build`. - - -## Is there a style guide? +### Is there a style guide? Yes, there's an `eslint` configuration, but it's not strict about formatting at all. If your contribution passes `npm run lint`, it's good enough for a PR (and it can still be accepted even if it doesn't pass). Spacing and formatting inconsistencies may be fixed after the fact, and we don't want that kind of stuff getting in the way of contributing. - - -## How do I embed live previews in docs? +### How do I embed live previews in docs? Any code tag marked as `js` and not `javascript` will automatically be wrapped in a live Flems preview. - - -## Why do tests mock the browser APIs? +### Why do tests mock the browser APIs? Most notoriously, because it's impossible to test the router and some side effects properly otherwise. Also, mocks allow the tests to run under Node.js without requiring heavy dependencies like PhantomJS/ChromeDriver/JSDOM. Another important reason is that it allows us to document browser API quirks via code, through the tests for the mocks. - - -## Why does Mithril.js use its own testing framework and not Mocha/Jasmine/Tape? +### Why does Mithril.js use its own testing framework and not Mocha/Jasmine/Tape? Mainly to avoid requiring dependencies. `ospec` is customized to provide only essential information for common testing workflows (namely, no spamming ok's on pass, and accurate noiseless errors on failure) - - -## Why doesn't the Mithril.js codebase use ES6 via Babel or Bublé? Would a PR to upgrade be welcome? +### Why doesn't the Mithril.js codebase use ES6 via Babel or Bublé? Would a PR to upgrade be welcome? Being able to run Mithril.js' raw source code in all supported browsers is a requirement for all browser-related modules in this repo. In addition, transpiled code is generally much bulkier. - - -## Why doesn't the Mithril.js codebase use trailing semi-colons? Would a PR to add them be welcome? +### Why doesn't the Mithril.js codebase use trailing semi-colons? Would a PR to add them be welcome? I don't use them. Adding them means the semi-colon usage in the codebase will eventually become inconsistent. Besides, [we aren't the only one who've decided to drop the semicolon](https://standardjs.com/#who-uses-javascript-standard-style). (We don't use Standard, though.) - - -## Why does the Mithril.js codebase use a mix of `instanceof` and `typeof` checks instead of `Object.prototype.toString.call`, `Array.isArray`, etc? Would a PR to refactor those checks be welcome? +### Why does the Mithril.js codebase use a mix of `instanceof` and `typeof` checks instead of `Object.prototype.toString.call`, `Array.isArray`, etc? Would a PR to refactor those checks be welcome? Mithril.js avoids peeking at objects' [[class]] string for performance considerations. Many type checks are seemingly inconsistent, weird or convoluted because those specific constructs demonstrated the best performance profile in benchmarks compared to alternatives. Type checks are generally already irreducible expressions and having micro-modules for type checking subroutines would add maintenance overhead. - - -## What should I know in advance when attempting a performance related contribution? +### What should I know in advance when attempting a performance related contribution? You should be trying to reduce the number of DOM operations or reduce algorithmic complexity in a hot spot. Anything else is likely a waste of time. Specifically, micro-optimizations like caching array lengths, caching object property values and inlining functions won't have any positive impact in modern JavaScript engines. Keep object properties consistent (i.e. ensure the data objects always have the same properties and that properties are always in the same order) to allow the engine to keep using JIT'ed structs instead of hashmaps. Always place null checks first in compound type checking expressions to allow the JavaScript engine to optimize to type-specific code paths. Prefer for loops over Array methods and try to pull conditionals out of loops if possible. - - -## Do you all accept donations? +### Do you all accept donations? Yes, we do, over at [our OpenCollective page](https://opencollective.com/mithriljs). We don't actively seek donations, but they are very much appreciated and are used to support development and related expenses. Both one-time and recurring donations are accepted. diff --git a/docs/framework-comparison.md b/docs/framework-comparison.md index 1612baa4c..bdd7b6110 100644 --- a/docs/framework-comparison.md +++ b/docs/framework-comparison.md @@ -5,7 +5,7 @@ Detailed comparison between Mithril.js and other popular frameworks # Framework comparison - [Why not X?](#why-not-insert-favorite-framework-here?) -- [Why use Mithril.js?](#why-use-mithril?) +- [Why use Mithril.js?](#why-use-mithriljs?) - [React](#react) - [Angular](#angular) - [Vue](#vue) diff --git a/docs/installation.md b/docs/installation.md index 07ac4db89..3816f0580 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -4,7 +4,7 @@ Instructions on how to install Mithril.js # Installation -- [CDN and online playground](#cdn) +- [CDN and online playground](#cdn-and-online-playground) - [npm](#npm) - [Quick start with Webpack](#quick-start-with-webpack) diff --git a/docs/integrating-libs.md b/docs/integrating-libs.md index a4d7fd63b..9c3555183 100644 --- a/docs/integrating-libs.md +++ b/docs/integrating-libs.md @@ -6,7 +6,7 @@ How you can integrate a third party library into a Mithril.js application, using Integration with third party libraries or vanilla JavaScript code can be achieved via [lifecycle methods](lifecycle-methods.md). -## noUiSlider Example +### noUiSlider Example ```javascript /** NoUiSlider wrapper component */ @@ -70,7 +70,7 @@ m.mount(document.body, Demo) [Live Demo](https://flems.io/#0=N4IgZglgNgpgziAXAbVAOwIYFsZJAOgAsAXLKEAGhAGMB7NYmBvEAXwvW10QICsEqdBk2J4A9ACoJAAgBytAKoQAylAgATGACdpAdy0YADoe3S6WQ-RHSJYgDpowAVzTViEetNUbtACgCU0sAO0tIAbhg6cGqaWg4h0lowxE5aaEEJofTUSRiMiNLOru70vmFotJqBwemhdWJi0gCSaBDuGGoAXjDSAMxa6tKGkcQAntJqAEbShNowmXXRPjoAvNIVSt6x+DkweTBlFZr46rRYFBm1dYvEIwUADBQL1wZoAOYwBcBYEGgPF1gMAAPAoARnu91Yz2krH80KW21KAHInIZ1PskRcim4PGgyh0nPBqtDQuVKjB8HliFo4Ph6ABhQgYd4HCJQQlwZD3AC6cKu12kWHwSXUBl0AWhsIW7AW9CSWFoYU+hRcONKxP5oQa0npsGZqL6AyGI3GU2knnlio68Ji2hO8GptFGEv5Mv5YQgMF0BWxJTxGoFiWSqXSWF8SPUEDCSL51yhtXj8YckhkABEYArpEZDGYzpY0NZbA5fbjpOmFQFLqFYMRpHBCLRdFtTGswB04PNajXwgSemt7vFakkUmkq3UPV6faq-ZWaoHhyHBeHKcZMSSl0jDGvNQKw0jJk5iMR6NvA4G52fA2MTAV94fj2hT5eBdk1NQANZT4q42fry-1xtm1WaQAEIAKbW04h3S942fOo3Tg0JwKA6QAH5pDsEB0zgR1xiAzDpAKTD6VyRgvEgzC-2kWMz38J5oLrBsIOWaQADJWKXICLgvS8GSZFkvzVPEwgDRC2UJaQ1jCKjYLPWF6MvPctwucSYBo651JhBJE0HIUFRcYhfFOagnBwBh8EmSpRguctaD5NgOBATAcDwHY4AEGh6EYZgeDYbkqDUNB3wQFBOBcngKicCAEW0SgQFScgeBIYhDDgRAGhcQx3zeHYzjESLosggABUEACZ8FBfB7jESMcK0CAD0YfLaCimKtHwfg4uvbgQDgHIIEMUR2DCnqCratyPISvBktS9KxEy7LcqwZrWuKsqKqqmroupBrDxgFbCuWCautGEw8Bw0ZYAcka8B+YhCHq8gqCmpKj1mjK0CynLzDEO6HugEqNoANl+tp-qgDqPO687+sGvzWCAA) -## Bootstrap FullCalendar Example +### Bootstrap FullCalendar Example ```javascript /** FullCalendar wrapper component */ diff --git a/docs/jsx.md b/docs/jsx.md index 10df264f8..561cec3d0 100644 --- a/docs/jsx.md +++ b/docs/jsx.md @@ -6,8 +6,8 @@ Explanation, examples, and build notes on how to use JSX in your Mithril.js-base - [Description](#description) - [Setup](#setup) -- [Production build](#production-build) - [Using Babel with Webpack](#using-babel-with-webpack) +- [Production build](#production-build) - [Differences with React](#differences-with-react) - [JSX vs hyperscript](#jsx-vs-hyperscript) - [Tips and Tricks](#tips-and-tricks) diff --git a/docs/keys.md b/docs/keys.md index 6ac6b7e89..3c0c6e107 100644 --- a/docs/keys.md +++ b/docs/keys.md @@ -6,7 +6,7 @@ Documentation on the special "key" attribute in Mithril.js, which tracks vnodes' - [What are keys?](#what-are-keys?) - [Key restrictions](#key-restrictions) -- [Linking model data in lists of views](#linking-model-data-to-views) +- [Linking model data in lists of views](#linking-model-data-in-lists-of-views) - [Keeping collections of animated objects glitch-free](#keeping-collections-of-animated-objects-glitch-free) - [Reinitializing views with single-child keyed fragments](#reinitializing-views-with-single-child-keyed-fragments) - [Common gotchas](#common-gotchas) @@ -438,7 +438,7 @@ users.map(function(user) { }) ``` -The first binds the key to the `User` component, but the outer fragment created by `users.map(...)` is entirely unkeyed. Wrapping a keyed element this way doesn't work, and the result could be anything ranging from extra requests each time the list is changed to inner form inputs losing their state. The resulting behavior would similar to the [post list's broken example](#linking-model-data-to-views), but without the issue of state corruption. +The first binds the key to the `User` component, but the outer fragment created by `users.map(...)` is entirely unkeyed. Wrapping a keyed element this way doesn't work, and the result could be anything ranging from extra requests each time the list is changed to inner form inputs losing their state. The resulting behavior would similar to the [post list's broken example](#linking-model-data-in-lists-of-views), but without the issue of state corruption. The second binds it to the `.wrapper` element, ensuring the outer fragment *is* keyed. This does what you likely wanted to do all along, and removing a user won't pose any issues with the state of other user instances. diff --git a/docs/layout.html b/docs/layout.html index 3e0fe4cd6..363019412 100644 --- a/docs/layout.html +++ b/docs/layout.html @@ -4,41 +4,48 @@ Mithril.js - - + + -
-
- -

Mithril [archive-docs]

- -
-
-
-
- [body] -
- License: MIT. © Leo Horie. -
-
- - - + +
+
+
+

[archive-docs]

+ +
+ +
+
+
+
[body]
+
+ +
+
+ + + diff --git a/docs/migration-v02x.md b/docs/migration-v02x.md index 8681c0f9f..6e512f634 100644 --- a/docs/migration-v02x.md +++ b/docs/migration-v02x.md @@ -736,7 +736,7 @@ var Component = { var Component = { onremove: function() { // ... - } + }, view: function() { // ... } @@ -753,7 +753,7 @@ In addition, requests no longer have `m.startComputation`/`m.endComputation` sem The `data` parameter has now been split into `params`, query parameters interpolated into the URL and appended to the request, and `body`, the body to send in the underlying XHR. -In v0.2.x, you would use a `dataType: "jsonp"` to initiate a JSONP request. In v2.x, you now use [`m.jsonp`](jsonp.md), which carries mostly the same API as `m.request` without the XHR-related parts. +In v0.2.x, you would use a `dataType: "jsonp"` to initiate a JSONP request. In v2.x, you now use `m.jsonp`, which carries mostly the same API as `m.request` without the XHR-related parts. ### v0.2.x @@ -849,7 +849,7 @@ var greetAsync = function() { greetAsync() .then(function(value) {return value + " world"}) - .then(function(value) {console.log(value)}) //logs "hello world" after 1 second + .then(function(value) {console.log(value)}) // logs "hello world" after 1 second ``` ### v2.x @@ -865,7 +865,7 @@ var greetAsync = function() { greetAsync() .then(function(value) {return value + " world"}) - .then(function(value) {console.log(value)}) //logs "hello world" after 1 second + .then(function(value) {console.log(value)}) // logs "hello world" after 1 second ``` --- diff --git a/docs/nav-guides.md b/docs/nav-guides.md index cbf5da9ad..bbe3781c2 100644 --- a/docs/nav-guides.md +++ b/docs/nav-guides.md @@ -2,11 +2,9 @@ - [Introduction](index.md) - [Installation](installation.md) - [Tutorial](simple-application.md) - - [Learning Resources](learning-mithril.md) - [Getting Help](support.md) - Resources - [JSX](jsx.md) - - [ES6+ on legacy browsers](es6.md) - [Animation](animation.md) - [Testing](testing.md) - [Examples](examples.md) @@ -19,12 +17,11 @@ - [Keys](keys.md) - [Autoredraw system](autoredraw.md) - Social - - [Mithril.js Jobs](https://github.com/MithrilJS/mithril.js/wiki/JOBS) - [How to contribute](contributing.md) - - [Credits](credits.md) - [Code of Conduct](code-of-conduct.md) + - [Credits](credits.md) - Misc - [Framework comparison](framework-comparison.md) + - [ES6+ on legacy browsers](es6.md) + - [Learning Resources](learning-mithril.md) - [Change log/Migration](changelog.md) - - [v1 Documentation](https://mithril.js.org/archive/v1.1.7/) - - [v0.2 Documentation](https://mithril.js.org/archive/v0.2.5/) diff --git a/docs/nav-methods.md b/docs/nav-methods.md index 6d15f06eb..1384730d9 100644 --- a/docs/nav-methods.md +++ b/docs/nav-methods.md @@ -11,6 +11,7 @@ - [m.trust](trust.md) - [m.fragment](fragment.md) - [m.redraw](redraw.md) + - [m.censor](censor.md) - Optional - [Stream](stream.md) - Tooling diff --git a/docs/recent-changes.md b/docs/recent-changes.md index 3f940959b..f6f73e455 100644 --- a/docs/recent-changes.md +++ b/docs/recent-changes.md @@ -37,7 +37,7 @@ Recast the global reads to all be guarded with `typeof`, so that if they aren't #### [Add a `m.Fragment = "["` utility for JSX users. (@dead-claudia)](https://github.com/MithrilJS/mithril.js/pull/2744) The title says it all, and the diff's obvious. Resolves https://github.com/MithrilJS/mithril.js/issues/2640 and probably others. - + ### Patch Changes #### [Enable --minimize-semver-change for pr-release (@JAForbes)](https://github.com/MithrilJS/mithril.js/pull/2769) @@ -198,7 +198,7 @@ Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.4.2 to 4.7.6. Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.20. Commits. ded9bc6 Bump to v4.17.20. 63150ef Documentation fixes. #### [Bump minimist from 1.2.0 to 1.2.3 (@dependabot[bot])](https://github.com/MithrilJS/mithril.js/pull/2627) -Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.3. Commits. 6457d74 1.2.3. 38a4d1c even more aggressive checks for protocol pollution. +Bumps [minimist](https://github.com/minimistjs/minimist) from 1.2.0 to 1.2.3. Commits. 6457d74 1.2.3. 38a4d1c even more aggressive checks for protocol pollution. #### [Update installation.md (@purefan)](https://github.com/MithrilJS/mithril.js/pull/2608) Offer to install mithril as a webpack plugin. Just makes my life easier by not having to include mithril in every one of my js files. @@ -261,7 +261,7 @@ Recast the global reads to all be guarded with `typeof`, so that if they aren't #### [Add a `m.Fragment = "["` utility for JSX users. (@dead-claudia)](https://github.com/MithrilJS/mithril.js/pull/2744) The title says it all, and the diff's obvious. Resolves https://github.com/MithrilJS/mithril.js/issues/2640 and probably others. - + ### Patch Changes #### [Enable --minimize-semver-change for pr-release (@JAForbes)](https://github.com/MithrilJS/mithril.js/pull/2769) @@ -422,7 +422,7 @@ Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.4.2 to 4.7.6. Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.20. Commits. ded9bc6 Bump to v4.17.20. 63150ef Documentation fixes. #### [Bump minimist from 1.2.0 to 1.2.3 (@dependabot[bot])](https://github.com/MithrilJS/mithril.js/pull/2627) -Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.3. Commits. 6457d74 1.2.3. 38a4d1c even more aggressive checks for protocol pollution. +Bumps [minimist](https://github.com/minimistjs/minimist) from 1.2.0 to 1.2.3. Commits. 6457d74 1.2.3. 38a4d1c even more aggressive checks for protocol pollution. #### [Update installation.md (@purefan)](https://github.com/MithrilJS/mithril.js/pull/2608) Offer to install mithril as a webpack plugin. Just makes my life easier by not having to include mithril in every one of my js files. diff --git a/docs/releasing.md b/docs/releasing.md index 28cd52f4c..b7bf7e610 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -14,7 +14,7 @@ pr-release handles the following: - Creating github releases - Rollbacks -## For contributors +### For contributors Contributors should create their feature branch targetting the default branch `next`. When this branch is merged `pr-release` will either generate or update a release PR from `next` to `main`. @@ -24,7 +24,7 @@ Contributors who have permissions should add the correct semver label to their P If you do not have permissions, the maintainer will set the label on your behalf. -## Changelog +### Changelog There are two changelogs in the Mithril.js project @@ -33,13 +33,13 @@ There are two changelogs in the Mithril.js project In future we may collapse these into a single file, the separation is due to the fact the `changelog.md` predates the `release.md` file. -## For maintainers +### For maintainers Whenever a new feature branch is opened, a reviewing maintainer should add the correct semver label to their PR (`major` | `minor` | `patch`). If no label is set, `patch` is assumed. If a `major` or `minor` feature branch is merged but no labels were set, you can still go back and edit the semver labels. On label change the release pr will automatically be regenerated and will recalculate the semver version. -## Updating mithril.js.org +### Updating mithril.js.org Fixes to documentation can land whenever, updates to the site are built and published via `scripts/update-docs.js`. diff --git a/docs/stream.md b/docs/stream.md index da1eac403..8e39af84b 100644 --- a/docs/stream.md +++ b/docs/stream.md @@ -462,7 +462,7 @@ Pending streams can be created by calling `stream()` with no parameters. var pending = stream() ``` -If a stream is dependent on more than one stream, any of its parent streams is in a pending state, the dependent streams is also in a pending state, and does not update its value. +If a stream is dependent on more than one stream and any of its parent streams is in a pending state, the dependent stream is also in a pending state, and does not update its value. ```javascript var a = stream(5) @@ -558,13 +558,13 @@ console.log(serialized) // logs 123 Unlike libraries like Knockout, Mithril.js streams do not trigger re-rendering of templates. Redrawing happens in response to event handlers defined in Mithril.js component views, route changes, or after [`m.request`](request.md) calls resolve. -If redrawing is desired in response to other asynchronous events (e.g. `setTimeout`/`setInterval`, websocket subscription, 3rd party library event handler, etc), you should manually call [`m.redraw()`](redraw.md) +If redrawing is desired in response to other asynchronous events (e.g. `setTimeout`/`setInterval`, websocket subscription, 3rd party library event handler, etc.), you should manually call [`m.redraw()`](redraw.md). --- ### What is Fantasy Land -[Fantasy Land](https://github.com/fantasyland/fantasy-land) specifies interoperability of common algebraic structures. In plain english, that means that libraries that conform to Fantasy Land specs can be used to write generic functional style code that works regardless of how these libraries implement the constructs. +[Fantasy Land](https://github.com/fantasyland/fantasy-land) specifies interoperability of common algebraic structures. In plain English, that means that libraries that conform to Fantasy Land specs can be used to write generic functional style code that works regardless of how these libraries implement the constructs. For example, say we want to create a generic function called `plusOne`. The naive implementation would look like this: @@ -574,7 +574,7 @@ function plusOne(a) { } ``` -The problem with this implementation is that it can only be used with a number. However it's possible that whatever logic produces a value for `a` could also produce an error state (wrapped in a Maybe or an Either from a library like [Sanctuary](https://github.com/sanctuary-js/sanctuary) or [Ramda-Fantasy](https://github.com/ramda/ramda-fantasy)), or it could be a Mithril.js stream, or a [flyd](https://github.com/paldepind/flyd) stream, etc. Ideally, we wouldn't want to write a similar version of the same function for every possible type that `a` could have and we wouldn't want to be writing wrapping/unwrapping/error handling code repeatedly. +The problem with this implementation is that it can only be used with a number. However it's possible that whatever logic produces a value for `a` could also produce an error state (wrapped in a Maybe or an Either from a library like [Sanctuary](https://github.com/sanctuary-js/sanctuary) or [Ramda-Fantasy](https://github.com/ramda/ramda-fantasy)), or it could be a Mithril.js stream, a [Flyd](https://github.com/paldepind/flyd) stream, etc. Ideally, we wouldn't want to write a similar version of the same function for every possible type that `a` could have and we wouldn't want to be writing wrapping/unwrapping/error handling code repeatedly. This is where Fantasy Land can help. Let's rewrite that function in terms of a Fantasy Land algebra: diff --git a/docs/style.css b/docs/style.css index 5d359b9e0..eaf192f99 100644 --- a/docs/style.css +++ b/docs/style.css @@ -1,68 +1,113 @@ -body {background:white;-webkit-text-size-adjust: 100%;} +body {color:#181818;background:white;-webkit-text-size-adjust:100%;line-height:1.6;margin:0;} body,table,h5 {font-weight:normal;font-size:16px;font-family:'Open Sans',sans-serif;} -body>header,body>main {margin: auto;max-width:1000px;} -header section {position:absolute;width:250px;} -nav a {border-left:1px solid #ddd;padding:0 10px;} -nav a:first-child {border:0;padding-left:0;} -main {margin-bottom:100px;} -main section {margin-left:270px;} +table {font-size:15px;} + +/* layout */ +.container {height:100vh;display:flex;} +.container-left {overflow-y:scroll;width:284px;border-right:1px solid rgba(0, 0, 0, 0.07)} +.container-left::-webkit-scrollbar {width:4px;} +.container-left::-webkit-scrollbar-thumb {background:transparent;border-radius:4px;} +.container-left:hover::-webkit-scrollbar-thumb {background:rgba(136,136,136,0.4);} +.container-left:hover::-webkit-scrollbar-track {background:rgba(136,136,136,0.1);} +.container-right {overflow-y:scroll;width:auto;flex:1;display:flex;flex-direction:column;scroll-behavior:smooth;} +header {margin:20px 24px;} +article {margin:0 24px;} +nav.main {margin-bottom:20px;white-space:nowrap;} +nav.main a {border-left:1px solid #ddd;padding:0 10px;font-weight:bold;} +nav.main a:first-child {border:0;padding-left:0;} +nav.main a:last-child {padding-right:0;} +main {margin:20px auto 0 auto;width:100%;max-width:860px;flex-grow:1;} +footer {color:rgba(0,0,0,0.4);font-size:0.95em;margin:45px auto 0 auto;width:100%;max-width:860px;flex-grow:0;flex-shrink:0;} +footer section {margin:0 24px;padding:24px 0;border-top:1px solid #ddd;} +footer a {color:inherit;text-decoration:underline;} +footer span {white-space:nowrap;} +nav.sidebar {margin:0 24px;} +nav.sidebar ul {margin:0;padding:0;z-index:1;} +nav.sidebar ul li {list-style:none;margin:0 0 13px;padding:0;display:block;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;} +nav.sidebar ul li:last-child {border-bottom:0;} +nav.sidebar ul ul {margin:0 0 2px;padding:0;} +nav.sidebar ul ul li {border:0;margin-bottom:0;} +nav.sidebar ul ul ul {margin:0 0 2px;padding:0 0 0 12px;} +nav.sidebar ul ul ul ul {display:none;} +nav.sidebar ul strong + ul {border-left:3px solid #1e5799;margin-left:1.25px;} +.container-right h1 + hr {display:none;} +.logo {color:#010002;} +.logo:hover {text-decoration:none;} +#archive-docs {appearance:none;color:rgba(0,0,0,0.4);background-color:transparent;border:none;padding:0;margin:0;font-family:inherit;font-size:16px;cursor:inherit;line-height:inherit;outline:none;} +#archive-docs::-ms-expand {display:none;} +.hamburger {display:none;font-size:42px;line-height:1;padding:16px;position:fixed;right:0;top:0;z-index:32;} +.hamburger:hover {text-decoration:none;} +.hamburger span {display:block;width:24px;height:3px;margin-bottom:3px;position:relative;background:#1e5799;border-radius:3px;} +.hamburger span:last-child {margin-bottom:0;} +.version-selector {display:inline;position:relative;} +.version-selector-current {border-bottom: 1px dotted rgba(0,0,0,0.25);} +.version-selector-archive {position:absolute;padding:0.5em 1em 0.5em 0.5em;top:1.3em;left:-0.5em;height:auto;background:#f6f6f6;opacity:0;transition:opacity 0.5s;visibility:hidden;} +.version-selector-link {display:block;} +.version-selector:hover .version-selector-archive {opacity:1;visibility:visible;} + +/* content */ p {margin:0 0 15px;} -pre,code {background:#eee;font-family:monospace;font-size:14px;} -pre {border-left:3px solid #1e5799;overflow:auto;padding:10px 20px;margin:20px 0;} -code {border:1px solid #ddd;display:inline-block;margin:0 0 1px;padding:5px 3px;white-space:pre;} -pre code {border:0;margin:0;padding:0;} +pre,code {background:#f6f6f6;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:14px;} +pre {border-left:3px solid #1e5799;overflow:auto;padding:10px 20px;margin:15px 0 22.5px 0;} +p + pre {margin-top:22.5px;} +code {outline:1px solid #f0f0f0;display:inline-block;margin:0;padding:0 1px;white-space:pre;line-height:1.3;} +p code {white-space:pre-wrap;overflow-wrap:anywhere;} +pre code {border:0;outline:0;margin:0;padding:0;} table {border-collapse:collapse;margin:0 0 30px;width:100%;} tbody tr:nth-child(odd) {background:#fafafa;} -thead tr,tbody tr:nth-child(even) {background:#f3f3f3;} -tr {border-bottom:1px solid #eee;} +tbody tr:nth-child(even) {background:#f4f4f4;} +thead tr {background:#f1f1f1;border-bottom:1px solid #e9e9e9;} +tbody tr {border-bottom:1px solid #eee;} th {text-align:left;} th,td {padding:3px 10px;vertical-align:top;} +td:not(:last-child) code {border:none;outline:none;background-color:transparent;padding:0;font-size:14px;} +td:last-child code {background-color:white;} +td:last-child a code {background-color:inherit;} a {color:#1e5799;text-decoration:none;} a:hover {text-decoration:underline;} +h1 a code,h2 a code,h3 a code,li a code,td a code,p a:not(.a-with-code-only) code {background:inherit;outline:inherit;display:inherit;margin:inherit;padding:inherit;white-space:inherit;line-height:inherit;font-family:inherit;font-size:inherit;} +p a.a-with-code-only code {outline-color:#3c73ba4a;background-color:#f3f3f5;} +p a.a-with-code-only:hover code {outline-color:#6ea7e9;} hr {border:0;border-bottom:1px solid #ddd;margin:30px 0;} +ol {padding-left:1.125em;} +ul {padding-left:1em;} -/* Headings */ +/* headings */ h1,h2,h3,h4,h5 {position:relative} -h1 {font-size:24px;margin:0 0 15px;} +h1 {font-size:28px;margin:0 0 15px;} h2 {font-size:22px;margin:45px 0 15px;} h3 {font-size:20px;margin:45px 0 15px;} h4 {font-size:18px;margin:30px 0 15px;} h5 {font-weight:bold;margin:15px 0 15px;} -h1 img {vertical-align:middle;width:20px;} +h1 img {vertical-align:middle;width:28px;} h1 small {font-size:16px;} h2 a,h3 a,h4 a,h5 a, h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover, h2 a:active,h3 a:active,h4 a:active,h5 a:active, -h2 a:visited,h3 a:visited,h4 a:visited,h5 a:visited {color:#000;text-decoration:none;} -h2::before,h3::before,h4::before,h5::before {content:"#";position:absolute;left:-20px;visibility:hidden;} -h2:hover::before,h3:hover::before,h4:hover::before,h5:hover::before {visibility:visible;} +h2 a:visited,h3 a:visited,h4 a:visited,h5 a:visited {color:#000000;text-decoration:none;} +h2::before,h3::before,h4::before,h5::before,h6::before {content:"#";position:absolute;left:-0.8em;visibility:hidden;} +h2:hover::before,h3:hover::before,h4:hover::before,h5:hover::before,h6:hover::before {visibility:visible;} #signature + p code {padding:3px 10px;} -h1 + ul {margin:40px 0 0 -270px;padding:0;position:absolute;width:250px;z-index:1;} -h1 + ul + hr {display:none;} -h1 + ul li {list-style:none;margin:0;padding:0;} -h1 + ul li:last-child {border-bottom:0;} -h1 + ul ul {margin:0 0 2px;padding:0 0 0 15px;} -h1 + ul ul li {border:0;} -h1 + ul strong + ul {border-left:3px solid #1e5799;} - -.hamburger {display:none;} @keyframes grow { from {transform:scaleX(0)} to {transform:scaleX(100%)} } -@media (max-width: 767px) { - .hamburger {display:block;font-size:30px;padding:0 10px;position:fixed;right:0;top:0;z-index:2;} - .hamburger:hover {text-decoration:none;} - main section {margin:0;} - header section {margin:0 0 20px;position:static;width:auto;} - h1 + ul {background:#eee;border:1px solid #ccc;box-sizing:border-box;display:none;height:100%;margin:0;overflow:auto;padding:20px;position:fixed;right:0;top:0;width:100%;z-index:1} - h1 + ul + hr {display:block;} - .navigating h1 + ul {display:block;} +@media (max-width:767px) { + .hamburger {display:block;} + nav.sidebar {background:#eee;border:1px solid #ccc;box-sizing:border-box;display:none;height:100%;margin:0;overflow:auto;padding:20px;position:fixed;right:0;top:0;width:100%;z-index:31} + nav.sidebar ul ul ul ul {display:block;} + .navigating nav.sidebar {display:block;} .navigating {overflow:hidden;} + .container {display:flex;flex-direction:column;} + .container-left {border-right:none;width:auto;overflow-y:visible;} + .container-right {overflow-y:visible;} + header {border-bottom:1px solid #ccc;} + nav.sidebar {display:none;} } -@media (max-width: 1024px) { + +@media (max-width:1024px) { table,table tbody,table tr,table th,table td {display:block;} table thead {display:none;} table td:before {display:inline-block;font-style:italic;font-weight:bold;padding:0 10px 0 0;width:100px;} @@ -84,9 +129,11 @@ h1 + ul strong + ul {border-left:3px solid #1e5799;} #vue ~ table td:nth-child(1):before {content:"Vue:";} #comparisons ~ table td:nth-child(2):before {content:"Mithril:";} } + @media print { - nav,h1 + ul {display:none;} - main section {margin:0;} + nav {display:none;} + div,header,footer,main,article,section, footer section {display:block;margin:0;padding:0;} + header {border:none;} } /* prism theming */ @@ -95,11 +142,15 @@ h1 + ul strong + ul {border-left:3px solid #1e5799;} .token.selector,.token.attr-name,.token.string,.token.builtin {color:#690;} .token.atrule,.token.attr-value,.token.punctuation,.token.keyword {color:#1e5799;} .token.regex,.token.important {color:#e90;} +.token.operator {background-color:#f9f9f9;} +code[class*=language-], pre[class*=language-] {text-shadow:none;} +pre[class*=language-] {margin:15px 0 22.5px 0;font-size:14px;background-color:#f9f9f9;} +p + pre[class*=language-] {margin-top:22.5px;} /* flems theming */ -.flems main { margin: 0; max-width: auto; } -.flems { margin: 20px 0; max-height: 400px; } -.flems .runtime { border: 1px solid #ddd; } -@media (max-width: 500px) { - .flems { min-height: calc(100vw * 1.3); } +.flems main {margin:0;max-width:auto;} +.flems {margin:20px 0;max-height:400px;} +.flems .runtime {border:1px solid #ddd;} +@media (max-width:500px) { + .flems {min-height:calc(100vw * 1.3);} } diff --git a/docs/support.md b/docs/support.md index 025dd144c..af37141cd 100644 --- a/docs/support.md +++ b/docs/support.md @@ -4,4 +4,4 @@ Where to find help with problems related to Mithril.js # Getting Help -Mithril.js has an active & welcoming community on [Zulip](https://mithril.zulipchat.com/), or feel free to ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/mithril.js) using the `mithril.js` tag. +Mithril.js has an active and welcoming community on [Zulip](https://mithril.zulipchat.com/), or feel free to ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/mithril.js) using the `mithril.js` tag. diff --git a/package-lock.json b/package-lock.json index f2c2a525e..46518c1d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -309,9 +309,9 @@ } }, "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "dependencies": { "lodash": "^4.17.14" @@ -1954,7 +1954,7 @@ "node_modules/istanbul/node_modules/async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", "dev": true }, "node_modules/istanbul/node_modules/esprima": { @@ -2502,9 +2502,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -4066,9 +4066,9 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "requires": { "lodash": "^4.17.14" @@ -5321,7 +5321,7 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", "dev": true }, "esprima": { @@ -5741,9 +5741,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" diff --git a/render/hyperscript.js b/render/hyperscript.js index 26ff753e3..0015b26eb 100644 --- a/render/hyperscript.js +++ b/render/hyperscript.js @@ -38,7 +38,7 @@ function execSelector(state, vnode) { vnode.tag = state.tag vnode.attrs = {} - if (!isEmpty(state.attrs) && !isEmpty(attrs)) { + if (!isEmpty(state.attrs)) { var newAttrs = {} for (var key in attrs) { diff --git a/render/tests/test-hyperscript.js b/render/tests/test-hyperscript.js index 59751f44a..fcf69d25d 100644 --- a/render/tests/test-hyperscript.js +++ b/render/tests/test-hyperscript.js @@ -580,6 +580,15 @@ o.spec("hyperscript", function() { o(nodeB.attrs.className).equals("b") o(nodeB.attrs.a).equals("b") }) + o("handles shared empty attrs (#2821)", function() { + var attrs = {} + + var nodeA = m(".a", attrs) + var nodeB = m(".b", attrs) + + o(nodeA.attrs.className).equals("a") + o(nodeB.attrs.className).equals("b") + }) o("doesnt modify passed attributes object", function() { var attrs = {a: "b"} m(".a", attrs) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index c6e1584ae..2ed9dca51 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -90,12 +90,31 @@ async function getArchiveDirs() { return dirs.reverse(); } +function filterVersions(versions) { + const majorVersions = ["v0"]; + return versions.filter((version) => { + if (version.includes("-rc.")) { + return false + } + const [major] = version.split(".") + if (!majorVersions.includes(major)) { + majorVersions.push(major) + return true + } + return false + }) +} + async function archiveDocsSelect() { - const archiveDirs = await getArchiveDirs() - var options = archiveDirs - .map((ad) => ``) + const archiveDirs = filterVersions(await getArchiveDirs()) + const currentVersion = archiveDirs.shift() + const links = archiveDirs + .map((ad) => `${ad}`) .join("") - return `` + return `
+ ${currentVersion} +
${links}
+
` } function encodeHTML (str) { @@ -111,7 +130,7 @@ function encodeHTML (str) { } function extractMetaDescription(markdown) { - var match = markdown.match(metaDescriptionRegExp) + const match = markdown.match(metaDescriptionRegExp) if (match) { return encodeHTML(match[1]) } @@ -120,6 +139,7 @@ function extractMetaDescription(markdown) { class Generator { constructor(opts) { this._version = opts.version + this._versionStamp = Date.now() this._guides = opts.guides this._methods = opts.methods this._layout = opts.layout @@ -140,18 +160,22 @@ class Generator { `${(a + b + c).replace(/\|/g, "|")}` ) - // inject menu + // extract menu + let menu = "" + body = body.replace( /(^# .+?(?:\r?\n){2,}?)(?:(-(?:.|\r|\n)+?)((?:\r?\n){2,})|)/m, (match, title, nav) => { if (!nav) { - return title + src.replace(link, "$1$2**$3**") + "\n\n" + menu = src.replace(link, "$1$2**$3**") + return title + "\n\n" } - return title + src.replace(link, (match, space, li, link) => + menu = src.replace(link, (match, space, li, link) => `${space}${li}**${link}**\n${ nav.replace(/(^|\n)/g, `$1\t${space}`) }` - ) + "\n\n" + ) + return title + "\n\n" } ) @@ -160,6 +184,10 @@ class Generator { path + ((/http/).test(path) ? extension : ".html") ) + menu = menu.replace(/(\]\([^\)]+)(\.md)/gim, (match, path, extension) => + path + ((/http/).test(path) ? extension : ".html") + ) + const markedHtml = marked(body) const title = body.match(/^#([^\n\r]+)/i) || [] @@ -173,13 +201,20 @@ class Generator { // update version result = result.replace(/\[version\]/g, this._version) + result = result.replace(/\[version-stamp\]/g, this._versionStamp) + + // insert parsed Menu + result = result.replace(/\[nav\]/, marked(menu)) // insert parsed HTML result = result.replace(/\[body\]/, markedHtml) - + // insert meta description result = result.replace(/\[metaDescription\]/, metaDescription) + // current year + result = result.replace(/\[currentYear\]/, new Date().getFullYear()) + // fix anchors const anchorIds = new Map()