Markoa app generator
slush markoa
(basic project with markoa apps)slush markoa:app
(add app to apps)slush markoa:data
(add app to apps)slush markoa:layout
(Stylus and Jade->Marko configuration)slush markoa:roots
(roots.cx configuration)slush markoa:tag
(add one marko tag)slush markoa:taglibs
(add one or more marko taglibs)slush markoa:tags
(add multiple marko tags)slush markoa:widget
(add one or more marko widgets)TODO: Improve widget
generator similar to make more similar to tag
generator ;)
Install slush-markoa
globally:
$ npm install -g slush-markoa
Create a new folder for your project:
$ mkdir my-slush-markoa
Run the generator from within the new folder:
$ cd my-slush-markoa && slush markoa
We recommend running the layout generator included to get a nice project setup for using Stylus with various cool plugins to make layout and styling of your app a much more fun experience!!!
Note: Be sure to read the Layout.md
file generated for tips, info etc. ;)
/apps
/_global
/components
/data
index.js
/layouts
layout.jade
mobile.jade
/index
/components
/tags
/project-feed
marko-tag.json
app.jade
marko-taglib.json
/layouts
base.jade
mobile.jade
/page
/dependencies
browser.json
app.browser.json
app.jade
/data
index.js
marko-taglib.json
meta.js
/repositories
/teams
...
marko-taglib.json
// Gulp build tasks
/build
/tasks
jade.js
stylus.js
watch.js
paths.js
...
Watching files:
gulp watch
- watches .jade
files in /apps
and .styl
files in /styles
The Markoa server is by default configured to watch .marko files in the /apps folders registered and will reload in order to recompile to .js
template files.
You can enable browser refresh
npm install browser-refresh --global
browser-refresh server.js
Which should auto reload the browser whenever a .marko
page is changes, for instant feedback!
There is also a browser-refresh.json
file for configuring this in more details, including for SSL support.
Static assets in public
are compiled to /dist
and can be referenced from marko directly.
<link rel="stylesheet" type="text/css" href="https://github.com/kristianmandrup/slush-markoa/blob/master/app.css">
<link rel="stylesheet" type="text/css" href="https://github.com/kristianmandrup/slush-markoa/blob/master/semantic.min.css">
<script src="https://github.com/kristianmandrup/slush-markoa/raw/master/semantic.min.js"></script>
Or the same in a .jade
file
link(rel="stylesheet" type="text/css" href="https://github.com/kristianmandrup/slush-markoa/blob/master/app.css")
link(rel="stylesheet" type="text/css" href="https://github.com/kristianmandrup/slush-markoa/blob/master/semantic.min.css")
script(src="https://github.com/kristianmandrup/slush-markoa/raw/master/semantic.min.js")
However we recommend using proper page dependencies via Lasso and browser.json
files (see below)
First run slush markoa:layout
to generate setup for Jade, Stylus and Semantic UI - to power the layout of your app.
Install Semantic UI as instructed: npm install semantic-ui --save
slush markoa:app
This geneator will create an app under apps/[app-name] similar to the default index
app generated by the default marko generator. Use this generator each time you want to add an app!
/[app]
/components
/tags
/project-feed
marko-tag.json
template.jade
marko-taglib.json
/layouts
base.jade
/data
index.js
/page
app.jade
/dependencies
app.browser.json
marko-taglib.json
slush markoa:tag
Use this generator each time you want to add a tag! If no app name is given, the tag becomes global:
apps/_global/components
/apps
/_global
/components
/tags
/[tag]
marko-tag.json
renderer.js
template.jade
marko-taglib.json
If an app name is given: apps/[app-name]/components
/apps
/[app]
/components
/tags
/[tag]
marko-tag.json
renderer.js
template.jade
As you get more fine grained tags, it starts to make sense to group them into categories such as:
In order to support this, you can use a special namespace feature xxx:aaa
or xxx:aaa-bb
This will create a subfolder xxx
for the tag. F.ex for the tag menu:top
/apps
/_global
/components
/tags
/menu
/menu-top
marko-tag.json
renderer.js
template.marko
template.jade
marko-taglib.json
marko-taglib.json
The new folder menu
is a new sub-tag lib. For this new menu
taglib to be reachable, it must be imported in a parent taglib (see section below on Taglibs).
top-menu
Creates the global tag top-menu
under apps/_global
- template.jade
- template.marko
- renderer.js
- marko-tag.json
Example ui-tabs
Example: ui-tabs/marko-tag.json
{
"@orientation": "string",
"@tabs <tab>[]": {
"@title": "string"
}
}
renderer.js
references template.marko
(see below)
var template = require('./template.marko');
exports.renderer = function(input, out) {
template.render(input, out);
};
ui-tabs/template.marko
<div class="tabs">
<ul class="nav nav-tabs">
<li class="tab" for="tab in data.tabs">
<a href="#">
...
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane" for="tab in data.tabs">
<invoke function="tab.renderBody(out)"/>
</div>
</div>
</div>
Each app has its own taglib file. This file can reference multiple folders if needed.
marko-taglib.json
example:
{
"tags-dir": ["./components", "./modules"]
}
You can also import other taglibs into a taglib. This feature is used to include the /menu
taglib for the global taglib:
{
"tags-dir": "./_global/components",
"taglib-imports": [
"./_global/components/menu/marko-taglib.json"
]
}
top-menu, side-bar, session-bar
index
Creates the tags: top-menu
, side-bar
and session-bar
for the app apps/index
Marko Widgets are special kinds of tags that support dynamic rendering and data binding etc. much like Reactive widgets/components from other frameworks such as React components. However Marko Widgets support both client and server side rendering amongst many other benefits, such as much lower footprint (kb) and higher server rendering performance (x10) than typical React components.
To create one or more widgets:
slush markoa:widget
Name the widget or list widgets to be created, just like for a tag. The simplest Widget template looks something like this:
<div w-bind>
Hello $data.name
</div>
With a corresponding "ViewModel" or Widget controller:
// widget.js
module.exports = require('marko-widgets').defineComponent({
template: require('./template.marko'),
getTemplateData: function(state, input) {
return {
name: input.name || 'unknown name'
};
},
init: function() {
var el = this.el; // The root DOM element that the widget is bound to
console.log('Initializing widget: ' + el.id);
}
});
Read more about how to get the full benefits of reactive Widgets for client and server on the Marko Widgets page. Enjoy :)
<lasso-page name="index" package-path="./dependencies/app-browser.json" />
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Marko Widgets: Bind</title>
<lasso-head/>
</head>
<body>
<h1>Marko Widgets: Bind</h1>
<div class="my-component" w-bind="./widget">
<h2>Click Me</h2>
</div>
<lasso-body/>
<init-widgets/>
</body>
</html>
The browser.json
that includes the required client-side code is shown below:
src/pages/index/browser.json
{
"dependencies": [
"require: marko-widgets",
"require: ./widget"
]
}
This browser.json
setup for client side widget dependencies doesn't work as is. Our setup is more advanced. We need the /widget
folder to expose methods to give us all global widgets and all widgets for each app. Then determine or find the widgets being used on the page, by either: - use a list such as widgets.json
in the /page folder
- if no widgets.json
, parse through the marko.html
for non-html tags
look up widgets in widget registry as part of yet another compile phase (on gulp watch
) and dynamically generate the browser.json file (perhaps by having a browser.json
(no marko widgets) and an index.browser.json
generated and referenced).
Follow a recipe like the following...
let markoa = require('markoa');
// see markoa docs for how to create appContainer
let myAppContainer = ...;
let myApp = require('./my-app');
let apps = ['index', 'projects'];
// mount apps on your appContainer using conventions!
myApp.mountIn(myAppContainer, apps);
Slush is a tool that uses Gulp for project scaffolding.
Slush does not contain anything "out of the box", except the ability to locate installed slush generators and to run them with liftoff.
To find out more about Slush, check out the documentation.
See the CONTRIBUTING Guidelines
If you have any problem or suggestion please open an issue here.