mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Introduced src/ and dist/ folders
This commit is contained in:
parent
c648b764f2
commit
a602f3cd46
2
.gitignore
vendored
2
.gitignore
vendored
@ -16,3 +16,5 @@ coverage
|
||||
.nyc_output
|
||||
yarn.lock
|
||||
*.swp
|
||||
/dist/
|
||||
/test-dist/
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
/taglibs/async/client-reorder-runtime.js
|
||||
/taglibs/async/client-reorder-runtime.min.js
|
||||
/src/taglibs/async/client-reorder-runtime.js
|
||||
/src/taglibs/async/client-reorder-runtime.min.js
|
||||
|
||||
@ -6,5 +6,5 @@ node_js:
|
||||
- "7"
|
||||
language: node_js
|
||||
before_script: "npm i npm@latest -g"
|
||||
script: "npm run test-generate-coverage"
|
||||
after_success: "npm run coveralls"
|
||||
script: "npm run test-ci"
|
||||
after_success: "npm run coveralls"
|
||||
|
||||
980
ROADMAP.md
980
ROADMAP.md
@ -1,979 +1,5 @@
|
||||
# What's Coming in Marko v4?
|
||||
# What's Coming in Marko?
|
||||
|
||||
A lot of exciting things are planned for our v4 release. All of these items have associated issues on GitHub. Please leave any feedback, suggestions, concerns, thumbs up/down on those issues.
|
||||
## Scoped CSS
|
||||
|
||||
If there is something that you think needs to be considered for this release outside of what's in this document, open an issue.
|
||||
|
||||
*We appreciate your time and feedback!*
|
||||
|
||||
## Notable Changes and Improvements
|
||||
|
||||
### Single file components ([#399](https://github.com/marko-js/marko/issues/399))
|
||||
|
||||
Marko now supports combining HTML, rendering logic, client-side behavior and styling into a single file component.
|
||||
|
||||
_src/components/my-counter/index.marko_
|
||||
|
||||
```html
|
||||
<script>
|
||||
// this top-level script tag is automatically
|
||||
// detected as a component due to `module.exports`
|
||||
// `export default` could be used as well
|
||||
module.exports = {
|
||||
onInput(input) {
|
||||
this.state = { count: input.value || 0 };
|
||||
},
|
||||
increment() {
|
||||
this.state.count++;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.count {
|
||||
color:#09c;
|
||||
}
|
||||
.button {
|
||||
background:#fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<span class="count">${state.count}</span>
|
||||
<button class="button" on-click('increment')>
|
||||
increment count
|
||||
</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can easily `require`/`import` a single file component and interact with it using the exported JavaScript API:
|
||||
|
||||
```js
|
||||
var myCounter = require('./src/components/my-counter');
|
||||
|
||||
var component = myCounter.renderSync({
|
||||
value: 10
|
||||
})
|
||||
.appendTo(document.body)
|
||||
.getComponent();
|
||||
|
||||
component.increment();
|
||||
```
|
||||
|
||||
Of course, a single file component can also be embedded in another template as a custom tag:
|
||||
|
||||
```xml
|
||||
<div>
|
||||
<my-counter value=10 />
|
||||
</div>
|
||||
```
|
||||
|
||||
### Virtual DOM support ([#366](https://github.com/marko-js/marko/issues/366))
|
||||
|
||||
Because Marko renders raw HTML strings to a stream on the server, Marko has always been faster than other libraries by an [order of magnitude](https://github.com/patrick-steele-idem/marko-vs-react) when rendering on the server. However although Marko has been _pretty_ fast in the browser, it was a little behind some of our competitors. This was mainly because the output HTML string needed to be parsed into a DOM in order to do DOM diffing/patching.
|
||||
|
||||
That's changed. Marko now supports multiple compilation outputs. Templates compiled for the server will continue to render to an HTML stream/string and templates compiled for the browser will now render to a fast and lightweight virtual DOM tree. The code samples below show how the two different compilation outputs compare:
|
||||
|
||||
_Compiled for HTML output (server-side):_
|
||||
|
||||
```javascript
|
||||
function render(data, out) {
|
||||
var colors = data.colors;
|
||||
|
||||
if (colors && colors.length) {
|
||||
out.w("<ul>");
|
||||
|
||||
marko_forEach(colors, function(color) {
|
||||
out.w("<li class=\"color\">" +
|
||||
marko_escapeXml(color) +
|
||||
"</li>");
|
||||
});
|
||||
|
||||
out.w("</ul>");
|
||||
} else {
|
||||
out.w("<div>No colors!</div>");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_Compiled for VDOM output (browser-side):_
|
||||
|
||||
```javascript
|
||||
var marko_attrs0 = {
|
||||
"class": "color"
|
||||
},
|
||||
marko_node0 = marko_createElement("div", null, 1, marko_const_nextId())
|
||||
.t("No colors!");
|
||||
|
||||
function render(data, out) {
|
||||
var colors = data.colors;
|
||||
|
||||
if (colors && colors.length) {
|
||||
out.be("ul");
|
||||
|
||||
marko_forEach(colors, function(color) {
|
||||
out.e("li", marko_attrs0, 1)
|
||||
.t(marko_str(color));
|
||||
});
|
||||
|
||||
out.ee();
|
||||
} else {
|
||||
out.n(marko_node0);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The VDOM output allows optimizations that were previously not possible:
|
||||
|
||||
- Static subtrees are pulled into variables that are only initialized once and reused for every render
|
||||
- Static attributes that are on dynamic elements are pulled out to static variables
|
||||
- Diffing is skipped when comparing static subtrees
|
||||
|
||||
Our initial benchmarks show a significant improvement in rendering time and we are consistently outperforming React. The independent [morphdom](https://github.com/patrick-steele-idem/morphdom) library has been tweaked to support diffing with both a real DOM and a Marko virtual DOM.
|
||||
|
||||
### Merge in Marko Widgets ([#390](https://github.com/marko-js/marko/issues/390))
|
||||
|
||||
A big part of this release is a shift in focus from Marko being merely a templating language to a complete UI library. As such, we are providing first-class support for components.
|
||||
|
||||
You will no longer need to install `marko-widgets` as an external library, and there is more cohesion between the templates and components/components.
|
||||
|
||||
### Improved component lifecycle methods ([#396](https://github.com/marko-js/marko/issues/396))
|
||||
|
||||
|
||||
- `getInitialState()` ➔ `onInput(input)`
|
||||
- `getComponentConfig()` ➔ `onInput(input)`
|
||||
- `init(config)` ➔ `onMount()`
|
||||
- `getTemplateData(input, state)` ➔ (no longer needed)
|
||||
- `getInitialProps(input)` ➔ (no longer needed)
|
||||
|
||||
|
||||
```js
|
||||
class {
|
||||
onCreate(input) {
|
||||
this.state = {
|
||||
count: 0
|
||||
}
|
||||
this.initialCount = input.
|
||||
}
|
||||
|
||||
onInput(input) {
|
||||
if (input.count) {
|
||||
// if the parent component passes a value
|
||||
// for count, we'll reset our state to that
|
||||
// value
|
||||
this.state.count = input.count;
|
||||
this.initialCount = input.count;
|
||||
}
|
||||
}
|
||||
|
||||
onRender(out) {
|
||||
// Called for every render. This component
|
||||
// may or may not be mounted.
|
||||
// During render we have access to the `out`.
|
||||
console.log('The template is about to be rendered!');
|
||||
}
|
||||
|
||||
onMount() {
|
||||
console.log('The component has mounted!');
|
||||
|
||||
console.log('Count: ' + this.state.count);
|
||||
console.log('Initial count: ' + this.initialCount);
|
||||
}
|
||||
|
||||
onUpdate() {
|
||||
console.log('The DOM has been updated!');
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
console.log('The component is about to be destroyed :(')
|
||||
}
|
||||
|
||||
// Helper methods:
|
||||
|
||||
reset() {
|
||||
this.state.count = this.initialCount;
|
||||
}
|
||||
|
||||
increment() {
|
||||
this.state.count++;
|
||||
}
|
||||
|
||||
decrement() {
|
||||
this.state.count--;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Automatically watch component state object for changes ([#406](https://github.com/marko-js/marko/issues/406))
|
||||
|
||||
**Old:**
|
||||
|
||||
```js
|
||||
{
|
||||
getInitialState(input) {
|
||||
return {
|
||||
count: input.count || 0
|
||||
};
|
||||
}
|
||||
increment() {
|
||||
this.setState('count', this.state.count+1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**New:**
|
||||
|
||||
```js
|
||||
{
|
||||
onInput(input) {
|
||||
this.state = {
|
||||
count: input.count || 0
|
||||
};
|
||||
}
|
||||
increment() {
|
||||
this.state.count++;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In addition, the default state can now be declared:
|
||||
|
||||
```js
|
||||
{
|
||||
state: {
|
||||
count: 0
|
||||
}
|
||||
onInput(input) {
|
||||
this.state = {
|
||||
count: input.count
|
||||
};
|
||||
}
|
||||
increment() {
|
||||
this.state.count++;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: The default state will be deeply cloned and used as the state. Any properties added to `this.state` will override the default state.
|
||||
|
||||
### DOM insertion methods ([#415](https://github.com/marko-js/marko/issues/415))
|
||||
|
||||
Methods for inserting the output of rendering a template into the DOM have been introduced with Marko v4:
|
||||
|
||||
```js
|
||||
// Append to an existing DOM node:
|
||||
require('./template.marko')
|
||||
.renderSync({ name: 'Frank '})
|
||||
.appendTo(document.body);
|
||||
|
||||
// Replace an existing DOM node:
|
||||
require('./template.marko')
|
||||
.renderSync({ name: 'Frank '})
|
||||
.replace(document.getElementById('foo'));
|
||||
```
|
||||
|
||||
## Other Improvements
|
||||
|
||||
### Only diff attributes that are rendered by Marko ([#417](https://github.com/marko-js/marko/issues/417))
|
||||
|
||||
Previously, when diffing the DOM, all of the attributes on a real HTML element node were diffed with all of the attributes on a newly rendered HTML element node. This posed a problem when using Marko with third party libraries, such as animation libraries, that added HTML attributes that should have been left alone. The proposed workaround was to add the `w-preserve-attrs` attribute wherever needed.
|
||||
|
||||
In Marko v4, only the attributes rendered by Marko are ever modified by Marko. Any attributes added by third-party libraries are simply ignored.
|
||||
|
||||
### Allow multiple top-level DOM elements to be bound ([#393](https://github.com/marko-js/marko/issues/393))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<div w-bind>
|
||||
<h1>The current count is, ${data.count}</h1>
|
||||
<button onClick('incrementCount')>Increment Count</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<h1>The current count is, ${data.count}</h1>
|
||||
<button onClick('incrementCount')>Increment Count</button>
|
||||
```
|
||||
|
||||
### Template as entry point for UI components ([#416](https://github.com/marko-js/marko/issues/416))
|
||||
|
||||
**Old:**
|
||||
|
||||
`index.js`
|
||||
```js
|
||||
module.exports = require('marko-widgets').defineComponent({
|
||||
template: require('./template.marko'),
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
`template.marko`
|
||||
|
||||
```html
|
||||
<div w-bind>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
|
||||
|
||||
`component.js`
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
`index.marko`
|
||||
|
||||
```html
|
||||
<div>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
> The compiled template now exports the component
|
||||
|
||||
### Allow event handler attribute to bind additional arguments ([#401](https://github.com/marko-js/marko/issues/401))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<ul for(color in colors)>
|
||||
<li w-onClick="handleColorClick" data-color=color>${color}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
```js
|
||||
handleColorClick(event, el) {
|
||||
console.log(el.getAttribute('data-color'), 'was clicked');
|
||||
}
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<ul for(color in colors)>
|
||||
<li onClick('handleColorClick', color)>${color}</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
```js
|
||||
handleColorClick(color, event, el) {
|
||||
console.log(color, 'was clicked');
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: `w-on*` has been deprecated. See: [Deprecate `w-on*` in favor of `on*()`](#deprecate-w-on)
|
||||
|
||||
### Introduce the `<import>` tag ([#404](https://github.com/marko-js/marko/issues/404))
|
||||
|
||||
Marko v4 introduces ES6 style imports for importing other JavaScript modules:
|
||||
|
||||
**Old:**
|
||||
|
||||
```html
|
||||
<script marko-init>
|
||||
var helpers = require('./helpers');
|
||||
</script>
|
||||
<div>Total: ${helpers.formatCurrency(data.total))</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
import helpers from "./helpers"
|
||||
<div>Total: ${helpers.formatCurrency(data.total))</div>
|
||||
```
|
||||
|
||||
### Allow dynamic custom tags/components to be used with `<include>` ([#139](https://github.com/marko-js/marko/issues/139))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<invoke data.myComponent.renderer({name: 'Frank'}, out)/>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<include(data.myComponent) name='Frank' />
|
||||
```
|
||||
or
|
||||
```html
|
||||
<include(data.myComponent, {name: 'Frank'}) />
|
||||
```
|
||||
|
||||
### Introduce `state` as a local variable ([#400](https://github.com/marko-js/marko/issues/400))
|
||||
|
||||
**Old:**
|
||||
|
||||
`component.js`
|
||||
|
||||
```js
|
||||
{
|
||||
getInitialState(input) {
|
||||
return {
|
||||
name: input.name,
|
||||
birthday: input.birthday
|
||||
}
|
||||
},
|
||||
getTemplateData(state, input) {
|
||||
return {
|
||||
name: state.name,
|
||||
age: calculateAge(state.birthday)
|
||||
}
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
`template.marko`
|
||||
|
||||
```html
|
||||
<div>
|
||||
Hello ${data.name}! You are ${data.age} year(s) old.
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
|
||||
`component.js`
|
||||
|
||||
```js
|
||||
{
|
||||
onInput(input) {
|
||||
// `this.state` will be available as the `state` variable
|
||||
// in the template.
|
||||
this.state = {
|
||||
name: input.name,
|
||||
birthday: input.birthday
|
||||
};
|
||||
}
|
||||
getTemplateData(state) {
|
||||
// state is automatically available in the template, but we can also
|
||||
// provide additional template data by returning it from this method
|
||||
// and it will be available as part of the `data` variable.
|
||||
return {
|
||||
age: calculateAge(state.birthday) // Only need to pass values derived
|
||||
// from the state to the template.
|
||||
};
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
`template.marko`
|
||||
|
||||
```html
|
||||
<div>
|
||||
Hello ${state.name}! You are ${data.age} year(s) old.
|
||||
</div>
|
||||
```
|
||||
|
||||
### Make output of render `Promise`-compatible ([#251](https://github.com/marko-js/marko/issues/251))
|
||||
|
||||
**Old:**
|
||||
```js
|
||||
template.render({}, function(err, html, out) {});
|
||||
```
|
||||
|
||||
**New:**
|
||||
```js
|
||||
template.render({})
|
||||
.then(function(result){})
|
||||
.catch(function(err) {});
|
||||
|
||||
// render() can now be used with async/await
|
||||
var out = await template.render({});
|
||||
out.appendTo(document.body);
|
||||
```
|
||||
|
||||
NOTE: callback/events still work as well
|
||||
|
||||
### Make `<await-reorderer/>` optional ([#410](https://github.com/marko-js/marko/issues/410))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<html>
|
||||
...
|
||||
<body>
|
||||
...
|
||||
<await-reorderer/>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<html>
|
||||
...
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
*Automatically inserted before `</body>`*
|
||||
|
||||
### Allow multiple extensions when installing the Node.js require hook ([#407](https://github.com/marko-js/marko/issues/407))
|
||||
|
||||
**Old:**
|
||||
```js
|
||||
require('marko/node-require').install({
|
||||
extension: '.marko'
|
||||
});
|
||||
```
|
||||
|
||||
**New:**
|
||||
```js
|
||||
require('marko/node-require').install({
|
||||
extensions: ['.marko', '.marko.xml', '.html']
|
||||
});
|
||||
```
|
||||
|
||||
### Auto hot reload for any extensions provided when installing the Node.js require hook ([#363](https://github.com/marko-js/marko/issues/363))
|
||||
|
||||
Hot reload any extensions that were registered via `require('marko/node-require').install()`.
|
||||
|
||||
### Allow spaces around attributes ([#403](https://github.com/marko-js/marko/issues/403))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
var className="foo"
|
||||
<div class=className/>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
var className = "foo"
|
||||
<div class = className/>
|
||||
```
|
||||
|
||||
> NOTE: spaces are **allowed**, not required
|
||||
|
||||
### Allow compile-time transformers to be registered at the template level ([#408](https://github.com/marko-js/marko/issues/408))
|
||||
|
||||
`marko.json`
|
||||
```json
|
||||
{
|
||||
"transformer": "./my-transformer.js"
|
||||
}
|
||||
```
|
||||
`my-transformer.js`
|
||||
|
||||
```js
|
||||
module.exports = function transform(rootNode, context) {
|
||||
// ...
|
||||
};
|
||||
```
|
||||
[see commit](https://github.com/marko-js/marko/commit/a35e6bdbc3fe6e7f4e92fb377c435e29ab3d6e33)
|
||||
|
||||
### Introduce `<function>` tag ([#405](https://github.com/marko-js/marko/issues/405))
|
||||
|
||||
**Old:**
|
||||
```js
|
||||
<%
|
||||
function foo() {
|
||||
console.log('bar');
|
||||
}
|
||||
%>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```js
|
||||
<function foo() {
|
||||
console.log('bar');
|
||||
}/>
|
||||
```
|
||||
|
||||
Or, in concise:
|
||||
|
||||
```js
|
||||
function foo() {
|
||||
console.log('bar');
|
||||
}
|
||||
```
|
||||
|
||||
### Debug mode ([#247](https://github.com/marko-js/marko/issues/247))
|
||||
|
||||
Run
|
||||
|
||||
```
|
||||
DEBUG=marko node server.js
|
||||
```
|
||||
|
||||
Get debug output
|
||||
|
||||
```html
|
||||
<div data-template-path="/my-project/components/foo/index.marko">
|
||||
<h1>Foo</h1>
|
||||
<div>
|
||||
<div data-template-path="/my-project/components/bar/index.marko">
|
||||
<h2>Bar</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Allow regular expression for an HTML attribute value ([#386](https://github.com/marko-js/marko/issues/386))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<!-- escaped backslash (\) since strings are parsed as JS values -->
|
||||
<input type="text" pattern="\\w{2,20}" />
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<!-- just use a regex -->
|
||||
<input type="text" pattern=/\w{2,20}/ />
|
||||
```
|
||||
|
||||
## Deprecations
|
||||
|
||||
A huge effort is being made to make this release as painless as possible and keep backwards compatibility wherever possible. It should be possible to continue to use custom tags that were developed against v3 with the v4 release as long as there are no dependencies on features deprecated in Marko v3 that have now been removed in Marko v4 (see [Breaking Changes](#breaking-changes) below).
|
||||
|
||||
Additionally, [`marko-migrate`](https://github.com/marko-js/marko-migrate) will be updated to handle many of the deprecations described below.
|
||||
|
||||
### Deprecate `<script marko-init>` and replace with `render()` section ([#397](https://github.com/marko-js/marko/issues/397))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<script marko-init>
|
||||
var format = require('format');
|
||||
</script>
|
||||
<var name="World"/>
|
||||
<div>Hello ${format(name)}</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
var format=require('format')
|
||||
render()
|
||||
var name='World'
|
||||
<div>Hello ${format(name)}</div>
|
||||
```
|
||||
|
||||
or, with the non-concise syntax:
|
||||
|
||||
```html
|
||||
<var format=require('format')/>
|
||||
|
||||
<render()>
|
||||
<var name='World'/>
|
||||
<div>Hello ${format(name)}</div>
|
||||
</render>
|
||||
```
|
||||
|
||||
### Deprecate `w-bind` and make it optional when using a default name ([#394](https://github.com/marko-js/marko/issues/394), [#395](https://github.com/marko-js/marko/issues/395))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<div w-bind>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<div component="./component.js">
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
Or, applied as a tag (see next: multiple top level DOM elements):
|
||||
|
||||
```html
|
||||
<script component="./component.js"/>
|
||||
<div>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
Or, since `component.js` is automatically recognized
|
||||
|
||||
```html
|
||||
<div>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `widget-types` ([#514](https://github.com/marko-js/marko/issues/514))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<widget-types default="./component" mobile="./component-mobile"/>
|
||||
|
||||
<div w-bind=(data.isMobile ? 'default' : 'mobile')>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `w-id` and `w-for` in favor of `key` and `for-key` ([#394](https://github.com/marko-js/marko/issues/394))
|
||||
|
||||
The `w-id` attribute was used to obtain references using `this.getEl(refId)`. `w-id` has been replaced with the `key` attribute:
|
||||
|
||||
**Old:**
|
||||
|
||||
```html
|
||||
<input type="text" w-id="name" />
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<input type="text" key="name" />
|
||||
```
|
||||
|
||||
Similarly, `w-for` has been been replaced with `for-key`:
|
||||
|
||||
**Old:**
|
||||
|
||||
```html
|
||||
<label w-for="name">Name</label>
|
||||
<input type="text" w-id="name" />
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<label for-key="name">Name</label>
|
||||
<input type="text" key="name" />
|
||||
```
|
||||
|
||||
<a name="deprecate-w-on"></a>
|
||||
|
||||
### Deprecate `w-on*` in favor of `on*()` ([#420](https://github.com/marko-js/marko/issues/420))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<button w-on-click="handleClick">click me</button>
|
||||
```
|
||||
or
|
||||
```html
|
||||
<button w-onClick="handleClick">click me</button>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<button on-click('handleClick')>click me</button>
|
||||
```
|
||||
or
|
||||
```html
|
||||
<button onClick('handleClick')>click me</button>
|
||||
```
|
||||
|
||||
### Deprecate `<init-widgets/>` ([#409](https://github.com/marko-js/marko/issues/409))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<html>
|
||||
...
|
||||
<body>
|
||||
...
|
||||
<init-widgets/>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**New:**
|
||||
|
||||
**Automatic component initialization!**
|
||||
|
||||
### Deprecate `w-body` and replace with `include` ([#418](https://github.com/marko-js/marko/issues/418))
|
||||
|
||||
**Old:**
|
||||
|
||||
```html
|
||||
<div>
|
||||
<h1>My Awesome Component</h1>
|
||||
<div class="body" w-body/>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
|
||||
```html
|
||||
<div>
|
||||
<h1>My Awesome Component</h1>
|
||||
<div class="body" include()/>
|
||||
</div>
|
||||
```
|
||||
|
||||
Or, as a tag:
|
||||
|
||||
```html
|
||||
<div>
|
||||
<h1>My Awesome Component</h1>
|
||||
<div class="body">
|
||||
<include()/>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
NOTE: The parens (i.e., `()`) are optional for both the include attribute and the include tag
|
||||
|
||||
Or, with an argument value:
|
||||
|
||||
```html
|
||||
<div>
|
||||
<h1>My Awesome Component</h1>
|
||||
<div class="body">
|
||||
<include(data.renderBody || data.label)/>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `w-preserve*` and replace with `no-update*` ([#419](https://github.com/marko-js/marko/issues/419))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<div w-preserve>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<div no-update>
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `w-preserve-attrs` and replace with `:no-update` ([#422](https://github.com/marko-js/marko/issues/422))
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<div style="color:#09c" w-preserve-attrs="style">
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<div style:no-update="color:#09c">
|
||||
...
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `w-extend` and allow multiple components to be bound to the same HTML element ([#392](https://github.com/marko-js/marko/issues/392))
|
||||
|
||||
> `w-extend` is now deprecated
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<div w-bind>
|
||||
<some-component w-onEvent="handleEvent"/>
|
||||
</div>
|
||||
```
|
||||
or
|
||||
```html
|
||||
<some-component w-extend w-onEvent="handleEvent"/>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<some-component onEvent('handleEvent')/>
|
||||
```
|
||||
|
||||
NOTE: The outer most component is what is returned when calling `getComponent()`/`getComponentForEl()`.
|
||||
|
||||
<a name="breaking-changes"></a>
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
In order to move forward it was necessary to introduce a few (minor) breaking changes. We are also removing support for some features that were already logging deprecation messages in v3.
|
||||
|
||||
### Consistent rendering API ([#389](https://github.com/marko-js/marko/issues/389))
|
||||
|
||||
**Old:**
|
||||
```js
|
||||
var template = require('./template.marko');
|
||||
var component = require('./my-component');
|
||||
var data = {};
|
||||
|
||||
template.render(data); // returns `out`
|
||||
template.render(data, (err, html, out) => {});
|
||||
template.renderSync(data); // returns a String representing the HTML output
|
||||
|
||||
component.render(data); // returns a `RenderResult`
|
||||
component.render(data, (err, renderResult) => {});
|
||||
component.renderSync(data); // throws an error, not a method.
|
||||
```
|
||||
|
||||
**New:**
|
||||
```js
|
||||
var template = require('./template.marko');
|
||||
var component = require('./my-component');
|
||||
var data = {};
|
||||
|
||||
template.render(data); // returns `out`
|
||||
template.render(data, (err, out) => {});
|
||||
template.renderSync(data); // returns `out`
|
||||
|
||||
component.render(data); // returns `out`
|
||||
component.render(data, (err, out) => {});
|
||||
component.renderSync(data); // returns `out`
|
||||
```
|
||||
|
||||
Also, `out` has been updated to implement DOM manipulation methods like `appendTo` that were previously only available from the `RenderResult` returned from component renders.
|
||||
|
||||
NOTE: We will implement `out.toString()` and `out.toJSON()` so in many cases the `out` can be used as a string.
|
||||
|
||||
### Remove support for deprecated `empty`/`notEmpty` helpers ([#357](https://github.com/marko-js/marko/issues/357))
|
||||
|
||||
> Already deprecated in v3
|
||||
|
||||
The `empty`/`notEmpty` helpers were automatically being added to every compiled
|
||||
template. While they can be helpful, we feel it is better if the developer
|
||||
explicitly imports only the exact helpers that your code depends on for
|
||||
improved modularity.
|
||||
|
||||
### Remove hyphenated properties from input model ([#356](https://github.com/marko-js/marko/issues/356))
|
||||
|
||||
> Already deprecated in v3
|
||||
|
||||
Given a template like this:
|
||||
|
||||
```xml
|
||||
<include("./include-target.marko") first-name='Frank'/>
|
||||
```
|
||||
|
||||
`include-target.marko` looks like:
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
- Hello ${data['first-name']}
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
- Hello ${data.firstName}
|
||||
```
|
||||
|
||||
### Remove support for deprecated `<async-fragment>` and related tags ([#312](https://github.com/marko-js/marko/pull/312))
|
||||
|
||||
> Already deprecated in v3
|
||||
|
||||
**Old:**
|
||||
```html
|
||||
<async-fragment var="foo" data-provider=data.provider>
|
||||
${foo}
|
||||
</async-fragment>
|
||||
```
|
||||
|
||||
**New:**
|
||||
```html
|
||||
<await(foo from data.provider)>
|
||||
${foo}
|
||||
</await>
|
||||
```
|
||||
|
||||
### Remove support for emitting deprecated `async-fragment` events ([#426](https://github.com/marko-js/marko/issues/426))
|
||||
|
||||
> Already deprecated in v3
|
||||
|
||||
| Old | New |
|
||||
|------------------------------|-----------------------|
|
||||
| `asyncFragmentFinish` | `await:finish` |
|
||||
| `asyncFragmentBegin` | `await:begin` |
|
||||
| `asyncFragmentBeforeRender` | `await:beforeRender` |
|
||||
| `asyncFragmentClientReorder` | `await:clientReorder` |
|
||||
[Issue #666 - Proposal: Scoped CSS](https://github.com/marko-js/marko/issues/666)
|
||||
|
||||
@ -16,7 +16,7 @@ export default {
|
||||
moduleName: 'app',
|
||||
plugins: [
|
||||
babelPlugin({
|
||||
include: ['node_modules/**', '**/*.js', '**/*.jsx'],
|
||||
include: [],
|
||||
babelrc: false,
|
||||
"presets": [
|
||||
["es2015", { "loose": true, "modules": false }],
|
||||
@ -34,4 +34,4 @@ export default {
|
||||
})
|
||||
],
|
||||
dest: path.join(__dirname, '../build/bundles/inferno.js')
|
||||
};
|
||||
};
|
||||
|
||||
3
benchmark/size/marko/main.js
Normal file
3
benchmark/size/marko/main.js
Normal file
@ -0,0 +1,3 @@
|
||||
var helpers = require('marko/src/runtime/vdom/helpers');
|
||||
|
||||
console.log('HELPERS:', helpers);
|
||||
@ -1,3 +1,5 @@
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
import commonjsPlugin from 'rollup-plugin-commonjs';
|
||||
import browserifyPlugin from 'rollup-plugin-browserify-transform';
|
||||
import nodeResolvePlugin from 'rollup-plugin-node-resolve';
|
||||
@ -6,8 +8,6 @@ import envify from 'envify';
|
||||
import minpropsify from 'minprops/browserify';
|
||||
import path from 'path';
|
||||
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
// NODE_ENV=production browserify -t envify -t markoify --extension='.marko' --global-transform minprops/browserify -o build/bundles/marko.js marko/client.js
|
||||
|
||||
|
||||
@ -20,16 +20,16 @@ export default {
|
||||
browserifyPlugin(envify),
|
||||
browserifyPlugin(minpropsify),
|
||||
nodeResolvePlugin({
|
||||
jsnext: true, // Default: false
|
||||
jsnext: false, // Default: false
|
||||
main: true, // Default: true
|
||||
browser: true, // Default: false
|
||||
preferBuiltins: false,
|
||||
extensions: [ '.js', '.marko' ]
|
||||
}),
|
||||
commonjsPlugin({
|
||||
include: [ 'node_modules/**', '**/*.marko', '**/*.js'],
|
||||
include: [],
|
||||
extensions: [ '.js', '.marko' ]
|
||||
})
|
||||
],
|
||||
dest: path.join(__dirname, '../build/bundles/marko.js')
|
||||
};
|
||||
};
|
||||
|
||||
@ -42,12 +42,12 @@
|
||||
"preact": "^7.1.0",
|
||||
"react": "^15.4.1",
|
||||
"react-dom": "^15.4.1",
|
||||
"rollup": "^0.39.2",
|
||||
"rollup": "^0.41.6",
|
||||
"rollup-plugin-babel": "^2.7.1",
|
||||
"rollup-plugin-browserify-transform": "^0.1.0",
|
||||
"rollup-plugin-commonjs": "^7.0.0",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-marko": "0.0.2",
|
||||
"rollup-plugin-node-resolve": "^2.0.0",
|
||||
"rollup-plugin-node-resolve": "^3.0.0",
|
||||
"uglify-js": "^2.7.5",
|
||||
"vue": "^2.1.6",
|
||||
"vueify": "^9.4.0"
|
||||
|
||||
@ -27,9 +27,9 @@ export default {
|
||||
extensions: [ '.js', '.jsx' ]
|
||||
}),
|
||||
commonjsPlugin({
|
||||
include: [ 'node_modules/**', '**/*.js', '**/*.jsx'],
|
||||
include: [],
|
||||
extensions: [ '.js', '.jsx' ]
|
||||
})
|
||||
],
|
||||
dest: path.join(__dirname, '../build/bundles/preact.js')
|
||||
};
|
||||
};
|
||||
|
||||
@ -27,9 +27,9 @@ export default {
|
||||
extensions: [ '.js', '.jsx' ]
|
||||
}),
|
||||
commonjsPlugin({
|
||||
include: [ 'node_modules/**', '**/*.js', '**/*.jsx'],
|
||||
include: [],
|
||||
extensions: [ '.js', '.jsx' ]
|
||||
})
|
||||
],
|
||||
dest: path.join(__dirname, '../build/bundles/react.js')
|
||||
};
|
||||
};
|
||||
|
||||
@ -25,9 +25,9 @@ export default {
|
||||
extensions: [ '.js', '.vue' ]
|
||||
}),
|
||||
commonjsPlugin({
|
||||
include: [ 'node_modules/**', '**/*.vue', '**/*.js'],
|
||||
include: [],
|
||||
extensions: [ '.js', '.vue' ]
|
||||
})
|
||||
],
|
||||
dest: path.join(__dirname, '../build/bundles/vue.js')
|
||||
};
|
||||
};
|
||||
|
||||
@ -116,12 +116,17 @@ var args = require('argly').createParser({
|
||||
|
||||
var output = 'html';
|
||||
|
||||
var isForBrowser = false;
|
||||
|
||||
if (args.vdom) {
|
||||
output = 'vdom';
|
||||
isForBrowser = true;
|
||||
}
|
||||
|
||||
|
||||
var compileOptions = {
|
||||
output: output,
|
||||
browser: isForBrowser,
|
||||
compilerType: 'markoc',
|
||||
compilerVersion: markoPkgVersion || markocPkgVersion
|
||||
};
|
||||
|
||||
7
browser-refresh.js
Normal file
7
browser-refresh.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/browser-refresh');
|
||||
} else {
|
||||
module.exports = require('./dist/browser-refresh');
|
||||
}
|
||||
4
compiler-browser.marko
Normal file
4
compiler-browser.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/compiler");\n`;
|
||||
});
|
||||
7
compiler.js
Normal file
7
compiler.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/compiler');
|
||||
} else {
|
||||
module.exports = require('./dist/compiler');
|
||||
}
|
||||
4
components-browser.marko
Normal file
4
components-browser.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/components");\n`;
|
||||
});
|
||||
7
components.js
Normal file
7
components.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/components');
|
||||
} else {
|
||||
module.exports = require('./dist/components');
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
require('./init-components').$__initServerRendered();
|
||||
@ -1,21 +0,0 @@
|
||||
var componentsUtil = require('./util');
|
||||
var events = require('../runtime/events');
|
||||
var Component = require('./Component');
|
||||
var initComponents = require('./init-components');
|
||||
|
||||
require('./ComponentsContext').$__initClientRendered = initComponents.$__initClientRendered;
|
||||
|
||||
function onInitComponent(listener) {
|
||||
events.on('initComponent', listener);
|
||||
}
|
||||
|
||||
exports.onInitComponent = onInitComponent;
|
||||
exports.Component = Component;
|
||||
exports.getComponentForEl = componentsUtil.$__getComponentForEl;
|
||||
exports.init = initComponents.$__initServerRendered;
|
||||
|
||||
exports.c = require('./defineComponent'); // Referenced by compiled templates
|
||||
exports.r = require('./renderer'); // Referenced by compiled templates
|
||||
exports.rc = require('./registry').$__register; // Referenced by compiled templates
|
||||
|
||||
window.$__MARKO_COMPONENTS = exports; // Helpful when debugging... WARNING: DO NOT USE IN REAL CODE!
|
||||
14
env.js
Normal file
14
env.js
Normal file
@ -0,0 +1,14 @@
|
||||
var isDebug = false;
|
||||
|
||||
var env = process.env || {};
|
||||
|
||||
if (env.MARKO_DEBUG != null) {
|
||||
isDebug = env.MARKO_DEBUG !== 'false' && env.MARKO_DEBUG !== '0';
|
||||
} else {
|
||||
var NODE_ENV = env.NODE_ENV;
|
||||
isDebug = NODE_ENV == null ||
|
||||
NODE_ENV === 'development' ||
|
||||
NODE_ENV === 'dev';
|
||||
}
|
||||
|
||||
exports.isDebug = isDebug;
|
||||
52
express.js
52
express.js
@ -1,49 +1,7 @@
|
||||
require('./runtime/env-init');
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
var assign = require('object-assign');
|
||||
var express = module.parent.require('express');
|
||||
patchResponse(express.response);
|
||||
delete require.cache[__filename];
|
||||
|
||||
module.exports = function markoAppMiddleware() {
|
||||
var sacrificialApp = express();
|
||||
|
||||
sacrificialApp.once('mount', function onmount(parent) {
|
||||
// Patch the response
|
||||
patchResponse(parent.response);
|
||||
|
||||
// Remove sacrificial express app
|
||||
parent._router.stack.pop();
|
||||
});
|
||||
|
||||
return sacrificialApp;
|
||||
}
|
||||
|
||||
function patchResponse(response) {
|
||||
response.marko = response.marko || function(template, data) {
|
||||
if(typeof template === 'string') {
|
||||
throw new Error(
|
||||
'res.marko does not take a template name or path like res.render. ' +
|
||||
'Instead you should use `require(\'./path/to/template.marko\')` ' +
|
||||
'and pass the loaded template to this function.'
|
||||
);
|
||||
}
|
||||
|
||||
var res = this;
|
||||
var req = res.req;
|
||||
var app = res.app;
|
||||
var $global = assign({ app, req, res }, app.locals, res.locals);
|
||||
|
||||
if (data) {
|
||||
data = assign(data, {
|
||||
$global: assign($global, data.$global)
|
||||
});
|
||||
} else {
|
||||
data = { $global };
|
||||
}
|
||||
|
||||
res.set({ 'content-type': 'text/html; charset=utf-8' });
|
||||
|
||||
template.render(data, res);
|
||||
};
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/express');
|
||||
} else {
|
||||
module.exports = require('./dist/express');
|
||||
}
|
||||
|
||||
7
hot-reload.js
Normal file
7
hot-reload.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/hot-reload');
|
||||
} else {
|
||||
module.exports = require('./dist/hot-reload');
|
||||
}
|
||||
4
index-browser.marko
Normal file
4
index-browser.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/index");\n`;
|
||||
});
|
||||
7
index.js
Normal file
7
index.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/');
|
||||
} else {
|
||||
module.exports = require('./dist/');
|
||||
}
|
||||
4
jquery.marko
Normal file
4
jquery.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/components/jquery");\n`;
|
||||
});
|
||||
4
legacy-components-browser.marko
Normal file
4
legacy-components-browser.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/components/legacy");\n`;
|
||||
});
|
||||
7
legacy-components.js
Normal file
7
legacy-components.js
Normal file
@ -0,0 +1,7 @@
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/components/legacy');
|
||||
} else {
|
||||
module.exports = require('./dist/components/legacy');
|
||||
}
|
||||
146
node-require.js
146
node-require.js
@ -1,143 +1,7 @@
|
||||
'use strict';
|
||||
require('./runtime/env-init');
|
||||
var { isDebug } = require('./env');
|
||||
|
||||
const path = require('path');
|
||||
const resolveFrom = require('resolve-from');
|
||||
const fs = require('fs');
|
||||
const fsReadOptions = { encoding: 'utf8' };
|
||||
const MARKO_EXTENSIONS = Symbol('MARKO_EXTENSIONS');
|
||||
|
||||
function normalizeExtension(extension) {
|
||||
if (extension.charAt(0) !== '.') {
|
||||
extension = '.' + extension;
|
||||
}
|
||||
return extension;
|
||||
if (isDebug) {
|
||||
module.exports = require('./src/node-require');
|
||||
} else {
|
||||
module.exports = require('./dist/node-require');
|
||||
}
|
||||
|
||||
function compile(templatePath, markoCompiler, compilerOptions) {
|
||||
if (compilerOptions) {
|
||||
compilerOptions = Object.assign({}, markoCompiler.defaultOptions, compilerOptions);
|
||||
} else {
|
||||
compilerOptions = markoCompiler.defaultOptions;
|
||||
}
|
||||
|
||||
var writeToDisk = compilerOptions.writeToDisk;
|
||||
|
||||
var templateSrc;
|
||||
var compiledSrc;
|
||||
|
||||
if (writeToDisk === false) {
|
||||
// Don't write the compiled template to disk. Instead, load it
|
||||
// directly from the compiled source using the internals of the
|
||||
// Node.js module loading system.
|
||||
templateSrc = fs.readFileSync(templatePath, fsReadOptions);
|
||||
compiledSrc = markoCompiler.compile(templateSrc, templatePath);
|
||||
} else {
|
||||
var targetFile = templatePath + '.js';
|
||||
|
||||
if (markoCompiler.defaultOptions.assumeUpToDate && fs.existsSync(targetFile)) {
|
||||
// If the target file already exists and "assumeUpToDate" then just use the previously
|
||||
// compiled template.
|
||||
return fs.readFileSync(targetFile, fsReadOptions);
|
||||
}
|
||||
|
||||
var targetDir = path.dirname(templatePath);
|
||||
|
||||
var isUpToDate = markoCompiler.checkUpToDate(targetFile);
|
||||
|
||||
if (isUpToDate) {
|
||||
compiledSrc = fs.readFileSync(targetFile, fsReadOptions);
|
||||
} else {
|
||||
templateSrc = fs.readFileSync(templatePath, fsReadOptions);
|
||||
compiledSrc = markoCompiler.compile(templateSrc, templatePath, compilerOptions);
|
||||
|
||||
// Write to a temporary file and move it into place to avoid problems
|
||||
// assocatiated with multiple processes write to the same file. We only
|
||||
// write the compiled source code to disk so that stack traces will
|
||||
// be accurate.
|
||||
var filename = path.basename(targetFile);
|
||||
var tempFile = path.join(targetDir, '.' + process.pid + '.' + Date.now() + '.' + filename);
|
||||
fs.writeFileSync(tempFile, compiledSrc, fsReadOptions);
|
||||
fs.renameSync(tempFile, targetFile);
|
||||
}
|
||||
}
|
||||
|
||||
// We attach a path to the compiled template so that hot reloading will work.
|
||||
return compiledSrc;
|
||||
}
|
||||
|
||||
function getLoadedTemplate(path) {
|
||||
var cached = require.cache[path];
|
||||
return cached && cached.exports.render ? cached.exports : undefined;
|
||||
}
|
||||
|
||||
function install(options) {
|
||||
options = options || {};
|
||||
|
||||
var requireExtensions = options.require ? // options.require introduced for testing
|
||||
options.require.extensions :
|
||||
require.extensions;
|
||||
|
||||
var compilerOptions = options.compilerOptions;
|
||||
|
||||
if (compilerOptions) {
|
||||
require('./compiler').configure(compilerOptions);
|
||||
} else {
|
||||
compilerOptions = {};
|
||||
}
|
||||
|
||||
var extensions = [];
|
||||
|
||||
if (options.extension) {
|
||||
extensions.push(options.extension);
|
||||
}
|
||||
|
||||
if (options.extensions) {
|
||||
extensions = extensions.concat(options.extensions);
|
||||
}
|
||||
|
||||
if (extensions.length === 0) {
|
||||
extensions.push('.marko');
|
||||
}
|
||||
|
||||
function markoRequireExtension(module, filename) {
|
||||
var targetFile = filename + '.js';
|
||||
var cachedTemplate = getLoadedTemplate(targetFile) || getLoadedTemplate(filename);
|
||||
if (cachedTemplate) {
|
||||
// The template has already been loaded so use the exports of the already loaded template
|
||||
module.exports = cachedTemplate;
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve the appropriate compiler relative to the location of the
|
||||
// marko template file on disk using the "resolve-from" module.
|
||||
var dirname = path.dirname(filename);
|
||||
var markoCompilerModulePath = resolveFrom(dirname, 'marko/compiler');
|
||||
var markoCompiler = require(markoCompilerModulePath);
|
||||
|
||||
// Now use the appropriate Marko compiler to compile the Marko template
|
||||
// file to JavaScript source code:
|
||||
var compiledSrc = compile(filename, markoCompiler, compilerOptions);
|
||||
|
||||
// Append ".js" to the filename since that is where we write the compiled
|
||||
// source code that is being loaded. This allows stack traces to match up.
|
||||
module._compile(compiledSrc, targetFile);
|
||||
}
|
||||
|
||||
requireExtensions[MARKO_EXTENSIONS] = requireExtensions[MARKO_EXTENSIONS] ||
|
||||
(requireExtensions[MARKO_EXTENSIONS] = []);
|
||||
|
||||
extensions.forEach((extension) => {
|
||||
extension = normalizeExtension(extension);
|
||||
requireExtensions[extension] = markoRequireExtension;
|
||||
requireExtensions[MARKO_EXTENSIONS].push(extension);
|
||||
});
|
||||
}
|
||||
|
||||
install();
|
||||
|
||||
exports.install = install;
|
||||
|
||||
exports.getExtensions = function() {
|
||||
return require.extensions[MARKO_EXTENSIONS];
|
||||
};
|
||||
|
||||
59
package.json
59
package.json
@ -20,24 +20,27 @@
|
||||
"url": "https://github.com/marko-js/marko.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node scripts/build.js",
|
||||
"test": "npm run jshint -s && npm run mocha -s && npm run test-components -s && npm run test-components-deprecated -s",
|
||||
"mocha": "mocha --ui bdd --reporter spec ./test/",
|
||||
"test-ci": "npm run test-generate-coverage && npm run build && NODE_ENV=production npm run test",
|
||||
"mocha": "node test/server-tests-runner/cli.js",
|
||||
"prepublishOnly": "npm run build",
|
||||
"test-coverage": "npm run test-generate-coverage && nyc report --reporter=html && open ./coverage/index.html",
|
||||
"test-generate-coverage": "nyc -asc npm run test",
|
||||
"test-generate-coverage": "nyc -asc npm test",
|
||||
"test-fast": "mocha --ui bdd --reporter spec ./test/render-test",
|
||||
"test-async": "mocha --ui bdd --reporter spec ./test/async-render-test",
|
||||
"test-taglib-loader": "mocha --ui bdd --reporter spec ./test/taglib-loader-test",
|
||||
"test-express": "mocha --ui bdd --reporter spec ./test/express-test",
|
||||
"test-components": "npm run test-components-browser -s && npm run test-components-pages -s",
|
||||
"test-components-deprecated": "npm run test-components-browser-deprecated -s && npm run test-components-pages-deprecated -s",
|
||||
"test-components-browser": "node test/browser-tests-runner/cli.js test/components-browser-tests.js --automated",
|
||||
"test-components-browser-deprecated": "node test/browser-tests-runner/cli.js test/deprecated-components-browser-tests.js --automated && npm run test-components-pages-deprecated -s",
|
||||
"test-components-browser": "node test/browser-tests-runner/cli.js components-browser-tests.js --automated",
|
||||
"test-components-browser-deprecated": "node test/browser-tests-runner/cli.js deprecated-components-browser-tests.js --automated && npm run test-components-pages-deprecated -s",
|
||||
"test-components-pages": "node test/browser-tests-runner/cli.js --pages --automated",
|
||||
"test-components-pages-deprecated": "node test/browser-tests-runner/cli.js --pagesDeprecated --automated",
|
||||
"test-components-browser-dev": "browser-refresh test/browser-tests-runner/cli.js test/components-browser-tests.js --server",
|
||||
"test-page": "node test/browser-tests-runner/cli.js test/components-browser-tests.js --automated --page",
|
||||
"test-components-browser-dev": "browser-refresh test/browser-tests-runner/cli.js components-browser-tests.js --server",
|
||||
"test-page": "node test/browser-tests-runner/cli.js components-browser-tests.js --automated --page",
|
||||
"test-pages": "npm run test-components-pages",
|
||||
"jshint": "jshint compiler/ runtime/ taglibs/ components/",
|
||||
"jshint": "jshint src/",
|
||||
"coveralls": "nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"author": "Patrick Steele-Idem <pnidem@gmail.com>",
|
||||
@ -83,12 +86,14 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^2.1.4",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-core": "^6.24.1",
|
||||
"benchmark": "^2.1.1",
|
||||
"bluebird": "^3.4.7",
|
||||
"browser-refresh": "^1.6.0",
|
||||
"browser-refresh-taglib": "^1.1.0",
|
||||
"chai": "^3.3.0",
|
||||
"child-process-promise": "^2.0.3",
|
||||
"child-process-promise": "^2.2.1",
|
||||
"coveralls": "^2.11.9",
|
||||
"express": "^4.13.4",
|
||||
"fs-extra": "^2.0.0",
|
||||
@ -98,9 +103,11 @@
|
||||
"jsdom": "^9.6.0",
|
||||
"jshint": "^2.5.0",
|
||||
"lasso": "^2.4.1",
|
||||
"lasso-babel-transform": "^1.0.0",
|
||||
"lasso-marko": "^2.1.0",
|
||||
"lasso-resolve-from": "^1.2.0",
|
||||
"md5-hex": "^2.0.0",
|
||||
"micromatch": "^2.3.11",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^3.2.0",
|
||||
"mocha-phantomjs-core": "^2.1.1",
|
||||
@ -112,6 +119,7 @@
|
||||
"request": "^2.72.0",
|
||||
"require-self-ref": "^2.0.1",
|
||||
"serve-static": "^1.11.1",
|
||||
"shelljs": "^0.7.7",
|
||||
"through": "^2.3.4",
|
||||
"through2": "^2.0.1"
|
||||
},
|
||||
@ -119,44 +127,27 @@
|
||||
"bin": {
|
||||
"markoc": "bin/markoc"
|
||||
},
|
||||
"main": "runtime/index.js",
|
||||
"main": "index.js",
|
||||
"browser": {
|
||||
"./compiler.js": "../compiler-browser.marko",
|
||||
"./components.js": "./components-browser.marko",
|
||||
"./index.js": "./index-browser.marko",
|
||||
"./legacy-components.js": "./legacy-components-browser.marko"
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"browser": {
|
||||
"./node-require.js": "./node-require-browser.js"
|
||||
},
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
"**/benchmark/**",
|
||||
"**/coverage/**",
|
||||
"**/test/**"
|
||||
"**/test/**",
|
||||
"**/dist/**"
|
||||
]
|
||||
},
|
||||
"homepage": "http://markojs.com/",
|
||||
"version": "4.3.0",
|
||||
"logo": {
|
||||
"url": "https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-small.png"
|
||||
},
|
||||
"minprops": {
|
||||
"exclude": [
|
||||
"$c",
|
||||
"b",
|
||||
"be",
|
||||
"bed",
|
||||
"c",
|
||||
"ca",
|
||||
"d",
|
||||
"e",
|
||||
"ed",
|
||||
"ee",
|
||||
"h",
|
||||
"id",
|
||||
"n",
|
||||
"r",
|
||||
"sa",
|
||||
"t"
|
||||
],
|
||||
"matchPrefix": "$__"
|
||||
}
|
||||
}
|
||||
|
||||
4
ready.marko
Normal file
4
ready.marko
Normal file
@ -0,0 +1,4 @@
|
||||
module-code(function(require) {
|
||||
var isDebug = require('./env').isDebug;
|
||||
return `module.exports = require("./${isDebug ? 'src' : 'dist'}/components/ready");\n`;
|
||||
});
|
||||
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Loads a template
|
||||
*/
|
||||
module.exports = require('./loader');
|
||||
@ -1,25 +0,0 @@
|
||||
'use strict';
|
||||
var AsyncStream = require('./AsyncStream');
|
||||
var makeRenderable = require('../renderable');
|
||||
|
||||
function Template(path, renderFunc, options) {
|
||||
this.path = path;
|
||||
this._ = renderFunc;
|
||||
this.$__shouldBuffer = !options || options.shouldBuffer !== false;
|
||||
this.meta = undefined;
|
||||
}
|
||||
|
||||
function createOut(globalData, parent, state, buffer) {
|
||||
return new AsyncStream(globalData, parent, state, buffer);
|
||||
}
|
||||
|
||||
Template.prototype = {
|
||||
createOut: createOut,
|
||||
stream: function() {
|
||||
throw new Error('You must require("marko/stream")');
|
||||
}
|
||||
};
|
||||
|
||||
makeRenderable(Template.prototype);
|
||||
|
||||
module.exports = Template;
|
||||
@ -1,6 +0,0 @@
|
||||
'use strict';
|
||||
require('./env-init'); // no-op in the browser, but enables extra features on the server
|
||||
|
||||
exports.createOut = require('./createOut');
|
||||
exports.load = require('./loader');
|
||||
exports.events = require('./events');
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
"browser": {
|
||||
"./loader/index.js": "./loader/index-browser.js",
|
||||
"./nextTick": "./nextTick-browser.js",
|
||||
"./env-init.js": false
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
'use strict';
|
||||
/*
|
||||
This module is used to monkey patch `Template.prototype` to add a new `stream(templateData)` method. Since
|
||||
this module is likely not needed in the browser, we have split out the code into a separate module. This module
|
||||
is always loaded on the server, but if you need streaming in the browser you must add the following
|
||||
line to your app:
|
||||
|
||||
require('marko/stream');
|
||||
|
||||
*/
|
||||
var stream = require('stream');
|
||||
var Template = require('./html/Template');
|
||||
var AsyncStream = require('./html/AsyncStream');
|
||||
|
||||
function Readable(template, data, options) {
|
||||
Readable.$super.call(this);
|
||||
this._t = template;
|
||||
this._d = data;
|
||||
this._shouldBuffer = !options || options.shouldBuffer !== false;
|
||||
this._rendered = false;
|
||||
}
|
||||
|
||||
Readable.prototype = {
|
||||
write: function(data) {
|
||||
if (data != null) {
|
||||
this.push(data);
|
||||
}
|
||||
},
|
||||
end: function() {
|
||||
this.push(null);
|
||||
},
|
||||
_read: function() {
|
||||
if (this._rendered) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._rendered = true;
|
||||
|
||||
var template = this._t;
|
||||
var data = this._d;
|
||||
var globalData = data && data.$global;
|
||||
var shouldBuffer = this._shouldBuffer;
|
||||
var out = new AsyncStream(globalData, this, null, shouldBuffer);
|
||||
template.render(data, out);
|
||||
out.end();
|
||||
}
|
||||
};
|
||||
|
||||
require('raptor-util/inherit')(Readable, stream.Readable);
|
||||
|
||||
Template.prototype.stream = function(data) {
|
||||
return new Readable(this, data, this._options);
|
||||
};
|
||||
@ -1,23 +0,0 @@
|
||||
var VNode = require('./VNode');
|
||||
var inherit = require('raptor-util/inherit');
|
||||
|
||||
function VComment(value) {
|
||||
this.$__VNode(-1 /* no children */);
|
||||
this.nodeValue = value;
|
||||
}
|
||||
|
||||
VComment.prototype = {
|
||||
$__nodeType: 8,
|
||||
|
||||
$__actualize: function(doc) {
|
||||
return doc.createComment(this.nodeValue);
|
||||
},
|
||||
|
||||
$__cloneNode: function() {
|
||||
return new VComment(this.nodeValue);
|
||||
}
|
||||
};
|
||||
|
||||
inherit(VComment, VNode);
|
||||
|
||||
module.exports = VComment;
|
||||
@ -1,25 +0,0 @@
|
||||
var VNode = require('./VNode');
|
||||
var inherit = require('raptor-util/inherit');
|
||||
|
||||
function VText(value) {
|
||||
this.$__VNode(-1 /* no children */);
|
||||
this.nodeValue = value;
|
||||
}
|
||||
|
||||
VText.prototype = {
|
||||
$__Text: true,
|
||||
|
||||
$__nodeType: 3,
|
||||
|
||||
$__actualize: function(doc) {
|
||||
return doc.createTextNode(this.nodeValue);
|
||||
},
|
||||
|
||||
$__cloneNode: function() {
|
||||
return new VText(this.nodeValue);
|
||||
}
|
||||
};
|
||||
|
||||
inherit(VText, VNode);
|
||||
|
||||
module.exports = VText;
|
||||
@ -1,47 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var vdom = require('./vdom');
|
||||
var VElement = vdom.$__VElement;
|
||||
var VText = vdom.$__VText;
|
||||
|
||||
var commonHelpers = require('../helpers');
|
||||
var extend = require('raptor-util/extend');
|
||||
|
||||
var classList = commonHelpers.cl;
|
||||
|
||||
exports.e = function(tagName, attrs, childCount, flags, props) {
|
||||
return new VElement(tagName, attrs, childCount, flags, props);
|
||||
};
|
||||
|
||||
exports.t = function(value) {
|
||||
return new VText(value);
|
||||
};
|
||||
|
||||
exports.const = function(id) {
|
||||
var i=0;
|
||||
return function() {
|
||||
return id + (i++);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal helper method to handle the "class" attribute. The value can either
|
||||
* be a string, an array or an object. For example:
|
||||
*
|
||||
* ca('foo bar') ==> ' class="foo bar"'
|
||||
* ca({foo: true, bar: false, baz: true}) ==> ' class="foo baz"'
|
||||
* ca(['foo', 'bar']) ==> ' class="foo bar"'
|
||||
*/
|
||||
exports.ca = function(classNames) {
|
||||
if (!classNames) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof classNames === 'string') {
|
||||
return classNames;
|
||||
} else {
|
||||
return classList(classNames);
|
||||
}
|
||||
};
|
||||
|
||||
extend(exports, commonHelpers);
|
||||
19
scripts/build-test.js
Normal file
19
scripts/build-test.js
Normal file
@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
const { buildDir } = require('./util');
|
||||
|
||||
buildDir('test', 'test-dist', {
|
||||
babelExclude: {
|
||||
'taglibs/async/client-reorder-runtime.min.js': true
|
||||
},
|
||||
babelOptions: {
|
||||
"plugins": [
|
||||
[
|
||||
"minprops", {
|
||||
"matchPrefix": "___",
|
||||
"prefix": "",
|
||||
"suffix": "_"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
});
|
||||
38
scripts/build.js
Normal file
38
scripts/build.js
Normal file
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
const { buildDir } = require('./util');
|
||||
const babelOptions = {
|
||||
"plugins": [
|
||||
[
|
||||
"minprops", {
|
||||
"matchPrefix": "___",
|
||||
"prefix": "",
|
||||
"suffix": "_",
|
||||
"hello": "world",
|
||||
"context": "marko"
|
||||
}
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
buildDir('src', 'dist', {
|
||||
babelExclude: [
|
||||
'/taglibs/async/client-reorder-runtime.min.js'
|
||||
],
|
||||
babelOptions
|
||||
});
|
||||
|
||||
buildDir('test', 'test-dist', {
|
||||
babelExclude: [
|
||||
'*expected*.*',
|
||||
'input.js*'
|
||||
],
|
||||
exclude: [
|
||||
'/generated',
|
||||
'*.marko.js',
|
||||
'*.skip',
|
||||
'*.generated.*',
|
||||
'*actual*.*',
|
||||
'actualized-expected.html*'
|
||||
],
|
||||
babelOptions
|
||||
});
|
||||
108
scripts/util.js
Normal file
108
scripts/util.js
Normal file
@ -0,0 +1,108 @@
|
||||
const { mkdir, ls, rm, cp } = require('shelljs');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const babel = require("babel-core");
|
||||
const mm = require('micromatch');
|
||||
|
||||
const rootDir = path.join(__dirname, '..');
|
||||
|
||||
function babelTransformFile(sourceFile, targetFile, babelOptions) {
|
||||
babelOptions = Object.assign({}, babelOptions);
|
||||
babelOptions.filename = sourceFile;
|
||||
var source = fs.readFileSync(sourceFile, 'utf-8');
|
||||
var transformed = babel.transform(source, babelOptions).code;
|
||||
|
||||
fs.writeFileSync(targetFile, transformed, { encoding: 'utf8' });
|
||||
}
|
||||
|
||||
function createMatcher(patterns) {
|
||||
var matchers = patterns.map((pattern) => {
|
||||
return mm.matcher(pattern, { matchBase: true });
|
||||
});
|
||||
|
||||
return function isMatch(file) {
|
||||
for (var i=0; i<matchers.length; i++) {
|
||||
if (matchers[i](file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function findFiles(dir, callback, isExcluded) {
|
||||
function findFilesHelper(parentDir, parentRelativePath) {
|
||||
var names = fs.readdirSync(parentDir);
|
||||
for (var i=0; i<names.length; i++) {
|
||||
var name = names[i];
|
||||
var file = path.join(parentDir, name);
|
||||
var relativePath = path.join(parentRelativePath, name);
|
||||
|
||||
if (isExcluded && isExcluded(relativePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var stat = fs.statSync(file);
|
||||
|
||||
callback(file, relativePath, stat);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
findFilesHelper(file, relativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findFilesHelper(dir, '/');
|
||||
}
|
||||
|
||||
exports.buildDir = function buildDir(sourceName, targetName, options) {
|
||||
const sourceDir = path.join(rootDir, sourceName);
|
||||
const distDir = path.join(rootDir, targetName);
|
||||
|
||||
options = options || {};
|
||||
|
||||
const babelOptions = options.babelOptions || {};
|
||||
|
||||
var isExcluded;
|
||||
var isBabelExcluded;
|
||||
|
||||
if (options.exclude) {
|
||||
isExcluded = createMatcher(options.exclude);
|
||||
}
|
||||
|
||||
if (options.babelExclude) {
|
||||
isBabelExcluded = createMatcher(options.babelExclude);
|
||||
}
|
||||
|
||||
rm('-rf', distDir);
|
||||
|
||||
// console.log();
|
||||
// console.log('Running babel...');
|
||||
//
|
||||
//
|
||||
// console.log('babel completed successfully');
|
||||
// console.log();
|
||||
var matcher = mm.matcher('**/actual*.*', { matchBase: true });
|
||||
|
||||
console.log('isBabelExcluded', matcher('/autotests/codegen/functionDeclaration-anonymous/actual.js'));
|
||||
|
||||
findFiles(sourceDir, function(sourceFile, relativePath, stat) {
|
||||
var targetFile = path.join(distDir, relativePath);
|
||||
var targetDir = path.dirname(targetFile);
|
||||
|
||||
if (stat.isFile()) {
|
||||
mkdir('-p', targetDir);
|
||||
|
||||
var ext = path.extname(relativePath);
|
||||
if (ext !== '.js' || isBabelExcluded(relativePath)) {
|
||||
console.log('Copying file:', relativePath);
|
||||
cp(sourceFile, targetDir + '/');
|
||||
} else {
|
||||
console.log("Running babel: " + relativePath);
|
||||
babelTransformFile(sourceFile, targetFile, babelOptions);
|
||||
}
|
||||
}
|
||||
}, isExcluded);
|
||||
|
||||
};
|
||||
@ -16,7 +16,7 @@ exports.enable = function() {
|
||||
// installed in the project will have browser refresh enabled.
|
||||
process.env.MARKO_BROWSER_REFRESH = 'true';
|
||||
|
||||
var hotReload = require('../hot-reload');
|
||||
var hotReload = require('./hot-reload');
|
||||
hotReload.enable();
|
||||
|
||||
browserRefreshClient
|
||||
@ -24,4 +24,4 @@ exports.enable = function() {
|
||||
.onFileModified(function(path) {
|
||||
hotReload.handleFileModified(path);
|
||||
});
|
||||
};
|
||||
};
|
||||
@ -19,12 +19,12 @@ var utilFingerprint = require('./util/finger-print');
|
||||
var htmlElements = require('./util/html-elements');
|
||||
var markoModules = require('./modules');
|
||||
|
||||
const markoPkgVersion = require('../package.json').version;
|
||||
const markoPkgVersion = require('../../package.json').version;
|
||||
const rootDir = path.join(__dirname, '../');
|
||||
const markoEnv = require('../../env');
|
||||
|
||||
const FLAG_PRESERVE_WHITESPACE = 'PRESERVE_WHITESPACE';
|
||||
|
||||
|
||||
|
||||
function getTaglibPath(taglibPath) {
|
||||
if (typeof window === 'undefined') {
|
||||
return path.relative(process.cwd(), taglibPath);
|
||||
@ -62,6 +62,18 @@ const helpers = {
|
||||
vdom: { module: 'marko/runtime/vdom/helper-createInlineTemplate'},
|
||||
html: { module: 'marko/runtime/html/helper-createInlineTemplate'}
|
||||
},
|
||||
'defineComponent': {
|
||||
module: 'marko/components/helpers',
|
||||
method: 'c'
|
||||
},
|
||||
'defineComponent-legacy': {
|
||||
module: 'marko/components/legacy/helpers',
|
||||
method: 'c'
|
||||
},
|
||||
'defineWidget-legacy': {
|
||||
module: 'marko/components/legacy/helpers',
|
||||
method: 'w'
|
||||
},
|
||||
'escapeXml': 'x',
|
||||
'escapeXmlAttr': 'xa',
|
||||
'escapeScript': 'xs',
|
||||
@ -77,6 +89,18 @@ const helpers = {
|
||||
'loadTemplate': { module: 'marko/runtime/helper-loadTemplate' },
|
||||
'mergeNestedTagsHelper': { module: 'marko/runtime/helper-mergeNestedTags' },
|
||||
'merge': { module: 'marko/runtime/helper-merge' },
|
||||
'renderer': {
|
||||
module: 'marko/components/helpers',
|
||||
method: 'r'
|
||||
},
|
||||
'rendererLegacy': {
|
||||
module: 'marko/components/legacy/helpers',
|
||||
method: 'r'
|
||||
},
|
||||
'registerComponent': {
|
||||
module: 'marko/components/helpers',
|
||||
method: 'rc'
|
||||
},
|
||||
'renderComponent': { module: 'marko/components/taglib/helpers/renderComponent' },
|
||||
'str': 's',
|
||||
'styleAttr': {
|
||||
@ -106,11 +130,13 @@ class CompileContext extends EventEmitter {
|
||||
|
||||
const writeVersionComment = this.options.writeVersionComment;
|
||||
|
||||
this.root = undefined; // root will be set by the Compiler
|
||||
this.target = this.options.browser ? 'browser' : 'server';
|
||||
this.outputType = this.options.output || 'html';
|
||||
this.compilerType = this.options.compilerType || 'marko';
|
||||
this.compilerVersion = this.options.compilerVersion || markoPkgVersion;
|
||||
this.writeVersionComment = writeVersionComment !== 'undefined' ? writeVersionComment : true;
|
||||
|
||||
this.markoModulePrefix =
|
||||
this._vars = {};
|
||||
this._uniqueVars = new UniqueVars();
|
||||
this._staticVars = {};
|
||||
@ -124,7 +150,9 @@ class CompileContext extends EventEmitter {
|
||||
this._preserveComments = null;
|
||||
this.inline = this.options.inline === true;
|
||||
this.useMeta = this.options.meta !== false;
|
||||
this._moduleRuntimeTarget = this.outputType === 'vdom' ? 'marko/vdom' : 'marko/html';
|
||||
this.markoModulePrefix = markoEnv.isDebug ? 'marko/src/' : 'marko/dist/';
|
||||
|
||||
this._moduleRuntimeTarget = this.markoModulePrefix + (this.outputType === 'vdom' ? 'vdom' : 'html');
|
||||
this.unrecognizedTags = [];
|
||||
this._parsingFinished = false;
|
||||
|
||||
@ -208,8 +236,7 @@ class CompileContext extends EventEmitter {
|
||||
var dataStack = this._dataStacks[key];
|
||||
|
||||
if (!dataStack || dataStack.length === 0) {
|
||||
throw new Error('No data pushed for "' + key + '"');
|
||||
}
|
||||
throw new Error('No data pushed for "' + key + '"'); }
|
||||
|
||||
dataStack.pop();
|
||||
|
||||
@ -278,6 +305,15 @@ class CompileContext extends EventEmitter {
|
||||
}
|
||||
|
||||
getRequirePath(targetFilename) {
|
||||
if (targetFilename.startsWith(rootDir)) {
|
||||
var deresolved = this.markoModulePrefix + targetFilename.substring(rootDir.length);
|
||||
var ext = path.extname(deresolved);
|
||||
if (ext === '.js') {
|
||||
deresolved = deresolved.slice(0, 0 - ext.length);
|
||||
}
|
||||
return deresolved;
|
||||
}
|
||||
|
||||
return markoModules.deresolve(targetFilename, this.dirname);
|
||||
}
|
||||
|
||||
@ -286,12 +322,31 @@ class CompileContext extends EventEmitter {
|
||||
throw new Error('"path" should be a string');
|
||||
}
|
||||
|
||||
var varId = this._imports[path];
|
||||
if (path === 'marko') {
|
||||
path = this.markoModulePrefix;
|
||||
} else if (path.startsWith('marko/')) {
|
||||
if (path.startsWith('marko/src/') || path.startsWith('marko/dist/')) {
|
||||
|
||||
if (!varId) {
|
||||
} else {
|
||||
path = this.markoModulePrefix + path.substring('marko/'.length);
|
||||
}
|
||||
}
|
||||
|
||||
var key = path + ':' + (varName != null);
|
||||
|
||||
var varId = this._imports[key];
|
||||
if (varId === undefined) {
|
||||
var builder = this.builder;
|
||||
var requireFuncCall = this.builder.require(builder.literal(path));
|
||||
this._imports[path] = varId = this.addStaticVar(varName, requireFuncCall);
|
||||
|
||||
var requireFuncCall = builder.require(builder.literal(path));
|
||||
|
||||
if (varName) {
|
||||
this._imports[key] = varId = this.addStaticVar(varName, requireFuncCall);
|
||||
|
||||
} else {
|
||||
this.addStaticCode(requireFuncCall);
|
||||
this._imports[key] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return varId;
|
||||
@ -721,13 +776,20 @@ class CompileContext extends EventEmitter {
|
||||
'marko_' + name,
|
||||
this.builder.memberExpression(this.helpersIdentifier, methodIdentifier));
|
||||
} else if (helperInfo && helperInfo.module) {
|
||||
helperIdentifier = this.addStaticVar(
|
||||
'marko_' + name,
|
||||
this.builder.require(this.builder.literal(helperInfo.module)));
|
||||
if (helperInfo.method) {
|
||||
let moduleIdentifier = this.importModule('marko_' + helperInfo.module, helperInfo.module);
|
||||
helperIdentifier = this.addStaticVar(
|
||||
'marko_' + name,
|
||||
this.builder.memberExpression(moduleIdentifier, helperInfo.method));
|
||||
} else {
|
||||
helperIdentifier = this.importModule('marko_' + name, helperInfo.module);
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid helper: ' + name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this._helpers[name] = helperIdentifier;
|
||||
}
|
||||
|
||||
@ -79,4 +79,4 @@ class MemberExpression extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MemberExpression;
|
||||
module.exports = MemberExpression;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user