2 | Hello ${input.name}!
3 | <${input.renderBody}/>
4 |
5 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-tagname/components/goodbye.marko:
--------------------------------------------------------------------------------
1 | Goodbye ${input.name}!
2 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-tagname/components/hello.marko:
--------------------------------------------------------------------------------
1 | Hello ${input.name}!
2 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-tagname/dynamic-component.marko:
--------------------------------------------------------------------------------
1 | import Hello from "./components/hello.marko"
2 | import Goodbye from "./components/goodbye.marko"
3 |
4 | $ const isLeaving = false;
5 | <${isLeaving ? Goodbye : Hello} name="Frank"/>
6 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-tagname/dynamic-native-tag.marko:
--------------------------------------------------------------------------------
1 | $ const href = "http://ebay.com";
2 | <${href ? "a" : "button"} href=href>Lets go!>
3 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-tagname/provide-body-content.marko:
--------------------------------------------------------------------------------
1 |
2 | This is the body content
3 |
4 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-text/html.marko:
--------------------------------------------------------------------------------
1 | $ const message = "Welcome to Marko!";
2 | HTML $!{message}
3 | Escaped HTML: ${message}
4 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/dynamic-text/text.marko:
--------------------------------------------------------------------------------
1 | $ const name = "Frank";
2 | $ const messageCount = 30;
3 |
4 | Hello ${name.toUpperCase()}!
5 | You have ${messageCount} new messages.
6 |
7 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/embedded-js/blocks.marko:
--------------------------------------------------------------------------------
1 |
2 | static {
3 | var uniqueId = 0;
4 |
5 | function getNextId() {
6 | return uniqueId++;
7 | }
8 |
9 | console.log("Template loaded!");
10 | }
11 |
12 |
13 | $ {
14 | let name = input.name || "Frank";
15 | name = name.toUpperCase();
16 | console.log("Name:", name);
17 | }
18 |
19 | Hello ${name}!
20 | ${getNextId()}
21 |
22 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/embedded-js/helper-functions.marko:
--------------------------------------------------------------------------------
1 | static function isNegative(value) {
2 | // Static helper functions do not have
3 | // access to non-static variables such as "value" and "person"
4 | return value < 0 ? "Yes" : "No";
5 | }
6 |
7 | $ const value = 123;
8 | $ const person = {
9 | firstName: "John",
10 | lastName: "Doe"
11 | };
12 | $ function getNameFormatted() {
13 | // Non-static functions have access to non-static and static variables
14 | return person.firstName + " " + person.lastName.charAt(0) + ".";
15 | }
16 |
17 | Hello ${getNameFormatted()}Is negative? ${isNegative(value)}
18 |
19 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/embedded-js/import.marko:
--------------------------------------------------------------------------------
1 | import path from 'path'
2 |
3 | ${path.join("/Users/marko", "development")}
4 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/embedded-js/variables.marko:
--------------------------------------------------------------------------------
1 |
2 | static const dateLoaded = new Date();
3 |
4 |
5 | $ let name = "Frank";
6 | $ name = name.toUpperCase();
7 | $ console.log(name);
8 | Hello ${name}!
9 | This template was loaded at ${dateLoaded.toString()}
10 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/import/helper.js:
--------------------------------------------------------------------------------
1 | exports.add = function(a, b) {
2 | return a + b;
3 | };
4 |
5 | exports.subtract = function(a, b) {
6 | return a - b;
7 | };
8 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/import/import.marko:
--------------------------------------------------------------------------------
1 | import { add, subtract } from "./helper.js"
2 |
3 | 1 + 2 = ${add(1, 2)}
4 | 2 - 1 = ${subtract(2, 1)}
5 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/layouts/components/layout.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 | <${input.title}/>
4 |
5 |
6 | <${input.body}/>
7 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/layouts/index.marko:
--------------------------------------------------------------------------------
1 |
2 | <@title>This is the title@title>
3 | <@body>This is the body content@body>
4 | <@footer>This is the footer content@footer>
5 |
6 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/array.marko:
--------------------------------------------------------------------------------
1 | $ const colors = ["red", "green", "blue"];
2 |
9 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/properties.marko:
--------------------------------------------------------------------------------
1 | $ const person = {
2 | firstName: "John",
3 | lastName: "Doe",
4 | age: 20
5 | };
6 |
7 |
8 | -
9 | ${name}: ${value}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/range-loop.marko:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 | $ const myArray = [1, 2, 3, 4, 5];
15 |
16 |
17 | - ${myArray[i]}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/separator.marko:
--------------------------------------------------------------------------------
1 | $ const colors = ["red", "green", "blue"];
2 |
3 |
4 | ${color}
7 | ,
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/while.marko:
--------------------------------------------------------------------------------
1 |
2 | $ let n = 0;
3 |
4 | - ${n++}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/looping/with-index.marko:
--------------------------------------------------------------------------------
1 | $ const colors = ["red", "green", "blue"];
2 |
3 |
4 | -
5 | ${i + 1}) ${color}- FIRST
6 | - LAST
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/macros/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
7 | Hello ${name}!
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/macros/macro-body.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 | <${renderBody}/>
8 |
9 |
10 |
11 |
14 | American astronaut and the first person to walk on the Moon
15 |
16 |
17 | American author and journalist.
18 |
19 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/parent-child-communication/components/language-selector.marko:
--------------------------------------------------------------------------------
1 | class {
2 | onLanguageSelect() {
3 | const el = this.getEl("languageSelect");
4 | const selected = el.options[el.selectedIndex].value;
5 | this.emit("select-language", selected);
6 | }
7 | }
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/parent-child-communication/parent.marko:
--------------------------------------------------------------------------------
1 | class {
2 | onCreate() {
3 | this.state = { selectedLanguage: "English" };
4 | }
5 |
6 | onLanguageSelect(selectedLanguage) {
7 | this.state.selectedLanguage = selectedLanguage;
8 | }
9 | }
10 |
11 |
12 |
${state.selectedLanguage}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/sample-header/component.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | onInput (input) {
3 | this.state = {
4 | title: input.title
5 | };
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/sample-header/index.marko:
--------------------------------------------------------------------------------
1 | style {
2 | header {
3 | font-size: 2.5em;
4 | font-weight: 300;
5 | background-color: #f1f1f1;
6 | padding: 1em;
7 | text-align: center;
8 | }
9 | body {
10 | font-family: "Helvetica Neue", Roboto, "Arial Nova", "Segoe UI", Arial,
11 | sans-serif;
12 | margin: 0;
13 | }
14 | .color-picker-container {
15 | position: absolute;
16 | top: 30%;
17 | left: 50%;
18 | transform: translate(-50%, -50%);
19 | }
20 | .logo {
21 | height: 2.2em;
22 | }
23 | }
24 |
25 |
26 |
27 | ${input.title}
28 |
29 |
--------------------------------------------------------------------------------
/examples/language-guide/src/components/sample-header/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marko-js/examples/90689e6423c68147794cc8d278b1523f1764026b/examples/language-guide/src/components/sample-header/logo.png
--------------------------------------------------------------------------------
/examples/language-guide/src/components/whitespace/index.marko:
--------------------------------------------------------------------------------
1 |
2 | By default, pre tags have
3 | their whitespace preserved
4 |
5 |
9 |
--------------------------------------------------------------------------------
/examples/language-guide/src/pages/index.marko:
--------------------------------------------------------------------------------
1 | $ const name = "Frank";
2 | style {
3 | .container {
4 | margin-left: auto;
5 | margin-right: auto;
6 | width: 800px;
7 | }
8 | }
9 |
10 |
11 |
12 |
Hello ${name}!
13 | $ const colors = ["red", "green", "blue"];
14 |
15 |
16 |
17 | - ${color}
20 |
21 |
22 |
23 |
24 | No colors!
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/lasso-express/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | static
3 | .cache
4 | *.marko.js
5 | *.log
6 | .env
7 |
--------------------------------------------------------------------------------
/examples/lasso-express/README.md:
--------------------------------------------------------------------------------
1 | Sample App: Marko + Express
2 | ======================================
3 |
4 | This sample app illustrates how to integrate Marko with a very basic Express app. For this sample app, we use the streaming API to stream the output of the template rendering to the HTTP response stream. In addition, this sample application illustrates how to create custom tags that can be embedded into your templates.
5 |
6 | # Installation
7 |
8 | ```
9 | npx @marko/create marko-app --template lasso-express
10 | cd marko-app
11 | npm install
12 | npm run dev
13 | ```
14 |
15 | Navigate to [http://localhost:8080/](http://localhost:8080/) to see your server in action!
16 |
--------------------------------------------------------------------------------
/examples/lasso-express/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [["@babel/preset-env", { targets: { node: "current" } }]]
3 | }
4 |
--------------------------------------------------------------------------------
/examples/lasso-express/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lasso-express-example",
3 | "description": "Sample Express-based server app that integrates with Marko.",
4 | "version": "1.0.0",
5 | "dependencies": {
6 | "@babel/core": "^7.19.3",
7 | "@babel/preset-env": "^7.19.3",
8 | "@babel/register": "^7.18.9",
9 | "@lasso/marko-taglib": "^2.0.5",
10 | "@marko/compiler": "^5.22.8",
11 | "@marko/express": "^2.0.1",
12 | "browser-refresh": "^1.7.3",
13 | "browser-refresh-taglib": "^1.2.1",
14 | "express": "^4.18.1",
15 | "lasso": "^4.0.1",
16 | "lasso-marko": "^3.2.1",
17 | "marko": "^5.21.9"
18 | },
19 | "private": true,
20 | "scripts": {
21 | "dev": "browser-refresh --enable-source-maps -r @babel/register -r @marko/compiler/register src/server.js",
22 | "start": "NODE_ENV=production node -r @babel/register -r @marko/compiler/register src/server.js"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/lasso-express/src/components/app-header/index.marko:
--------------------------------------------------------------------------------
1 | style {
2 | header {
3 | font-size: 2.5em;
4 | font-weight: 300;
5 | background-color: #f1f1f1;
6 | padding: 1em;
7 | text-align: center;
8 | }
9 | body {
10 | font-family: "Helvetica Neue", Roboto, "Arial Nova", "Segoe UI", Arial, sans-serif;
11 | margin: 0;
12 | }
13 | }
14 |
15 |
16 |
17 | ${input.title}
18 |
19 |
--------------------------------------------------------------------------------
/examples/lasso-express/src/components/app-header/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marko-js/examples/90689e6423c68147794cc8d278b1523f1764026b/examples/lasso-express/src/components/app-header/logo.png
--------------------------------------------------------------------------------
/examples/lasso-express/src/components/app-layout/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Marko | Lasso + Express
8 |
9 |
10 |
11 |
12 |
13 | <${input.renderBody}/>
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 | style {
27 | .container{
28 | margin-left: auto;
29 | margin-right: auto;
30 | width: 800px;
31 | }
32 | }
--------------------------------------------------------------------------------
/examples/lasso-express/src/pages/home/components/app-hello/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 | class {
4 | onCreate() {
5 | this.state = {
6 | count: 0
7 | }
8 | }
9 |
10 | onMount() {
11 | console.log("Mounted in the browser!");
12 | }
13 |
14 | increment() {
15 | this.state.count++;
16 | }
17 | }
18 |
19 | style {
20 | .count {
21 | color:#09c;
22 | font-size:3em;
23 | }
24 | .example-button {
25 | font-size:1em;
26 | padding:0.5em;
27 | }
28 | }
29 |
30 | Hello ${input.name}
31 |
32 |
33 | ${state.count}
34 |
35 |
36 |
37 | Click me
38 |
39 |
--------------------------------------------------------------------------------
/examples/lasso-express/src/pages/home/index.js:
--------------------------------------------------------------------------------
1 | import template from "./template.marko";
2 |
3 | export default (req, res) => {
4 | res.marko(template, {
5 | name: "Frank",
6 | count: 30,
7 | colors: ["red", "green", "blue"]
8 | });
9 | };
10 |
--------------------------------------------------------------------------------
/examples/lasso-express/src/pages/home/template.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | You have ${input.count} new messages!
5 |
6 |
7 |
8 |
9 | - ${color}
10 |
11 |
12 |
13 |
14 | No colors!
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/README.md:
--------------------------------------------------------------------------------
1 | Sample App: Marko + Fastify
2 | ======================================
3 |
4 | This sample app illustrates how to integrate Marko with a very basic Fastify app. For this sample app, we use the streaming API to stream the output of the template rendering to the HTTP response stream. In addition, this sample application illustrates how to create custom tags that can be embedded into your templates.
5 |
6 | # Installation
7 |
8 | ```
9 | npx @marko/create marko-app --template lasso-fastify
10 | cd marko-app
11 | npm install
12 | npm run dev
13 | ```
14 |
15 | Navigate to [http://localhost:8080/](http://localhost:8080/) to see your server in action!
16 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [["@babel/preset-env", { targets: { node: "current" } }]]
3 | }
4 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lasso-fastify-example",
3 | "description": "Sample Fastify-based server that integrates with Marko.",
4 | "version": "1.0.0",
5 | "dependencies": {
6 | "@babel/core": "^7.19.3",
7 | "@babel/preset-env": "^7.19.3",
8 | "@babel/register": "^7.18.9",
9 | "@fastify/static": "6.5.0",
10 | "@fastify/compress": "6.1.1",
11 | "@marko/compiler": "^5.22.8",
12 | "@marko/fastify": "^1.1.1",
13 | "@lasso/marko-taglib": "^2.0.5",
14 | "browser-refresh": "^1.7.3",
15 | "browser-refresh-taglib": "^1.2.1",
16 | "fastify": "^4.6.0",
17 | "lasso": "^4.0.1",
18 | "lasso-marko": "^3.2.1",
19 | "marko": "^5.21.9"
20 | },
21 | "private": true,
22 | "scripts": {
23 | "dev": "browser-refresh --enable-source-maps -r @babel/register -r @marko/compiler/register src/server.js",
24 | "start": "NODE_ENV=production node -r @babel/register -r @marko/compiler/register src/server.js"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/components/app-header/index.marko:
--------------------------------------------------------------------------------
1 | style {
2 | header {
3 | font-size: 2.5em;
4 | font-weight: 300;
5 | background-color: #f1f1f1;
6 | padding: 1em;
7 | text-align: center;
8 | }
9 | body {
10 | font-family: "Helvetica Neue", Roboto, "Arial Nova", "Segoe UI", Arial, sans-serif;
11 | margin: 0;
12 | }
13 | }
14 |
15 |
16 |
17 | ${input.title}
18 |
19 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/components/app-header/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marko-js/examples/90689e6423c68147794cc8d278b1523f1764026b/examples/lasso-fastify/src/components/app-header/logo.png
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/components/app-layout/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Marko | Lasso + Fastify
8 |
9 |
10 |
11 |
12 |
13 | <${input.renderBody}/>
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 | style {
27 | .container{
28 | margin-left: auto;
29 | margin-right: auto;
30 | width: 800px;
31 | }
32 | }
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/pages/home/components/app-hello/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 | class {
4 | onCreate() {
5 | this.state = {
6 | count: 0
7 | }
8 | }
9 |
10 | onMount() {
11 | console.log("Mounted in the browser!");
12 | }
13 |
14 | increment() {
15 | this.state.count++;
16 | }
17 | }
18 |
19 | style {
20 | .count {
21 | color:#09c;
22 | font-size:3em;
23 | }
24 | .example-button {
25 | font-size:1em;
26 | padding:0.5em;
27 | }
28 | }
29 |
30 | Hello ${input.name}
31 |
32 |
33 | ${state.count}
34 |
35 |
36 |
37 | Click me
38 |
39 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/pages/home/index.js:
--------------------------------------------------------------------------------
1 | import Template from "./template.marko";
2 |
3 | export default (req, reply) => {
4 | reply.marko(Template, {
5 | name: "Frank",
6 | count: 30,
7 | colors: ["red", "green", "blue"]
8 | });
9 | };
10 |
--------------------------------------------------------------------------------
/examples/lasso-fastify/src/pages/home/template.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | You have ${input.count} new messages!
5 |
6 |
7 |
8 |
9 | - ${color}
10 |
11 |
12 |
13 |
14 | No colors!
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/lasso-koa/README.md:
--------------------------------------------------------------------------------
1 | Sample App: Marko + Koa
2 | ======================================
3 |
4 | This sample app illustrates how to integrate Marko with a very basic Koa app. For this sample app, we use the streaming API to stream the output of the template rendering to the HTTP response stream. In addition, this sample application illustrates how to create custom tags that can be embedded into your templates.
5 |
6 | # Installation
7 |
8 | ```
9 | npx @marko/create marko-app --template lasso-koa
10 | cd marko-app
11 | npm install
12 | npm run dev
13 | ```
14 |
15 | Navigate to [http://localhost:8080/](http://localhost:8080/) to see your server in action!
16 |
--------------------------------------------------------------------------------
/examples/lasso-koa/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [["@babel/preset-env", { targets: { node: "current" } }]]
3 | }
4 |
--------------------------------------------------------------------------------
/examples/lasso-koa/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lasso-koa-example",
3 | "description": "Sample Koa-based server app that integrates with Marko.",
4 | "version": "1.0.0",
5 | "dependencies": {
6 | "@babel/core": "^7.13.1",
7 | "@babel/preset-env": "^7.13.5",
8 | "@babel/register": "^7.13.0",
9 | "@lasso/marko-taglib": "^2.0.3",
10 | "browser-refresh": "^1.7.3",
11 | "browser-refresh-taglib": "^1.1.0",
12 | "koa": "^2.13.1",
13 | "koa-mount": "^4.0.0",
14 | "koa-router": "^10.0.0",
15 | "koa-static": "^5.0.0",
16 | "lasso": "^3.4.1",
17 | "lasso-marko": "^3.0.1",
18 | "marko": "^5.1.20"
19 | },
20 | "private": true,
21 | "scripts": {
22 | "dev": "browser-refresh --enable-source-maps -r @babel/register -r marko/node-require src/server.js",
23 | "start": "NODE_ENV=production node -r @babel/register -r marko/node-require src/server.js"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/lasso-koa/src/components/app-header/index.marko:
--------------------------------------------------------------------------------
1 | style {
2 | header {
3 | font-size: 2.5em;
4 | font-weight: 300;
5 | background-color: #f1f1f1;
6 | padding: 1em;
7 | text-align: center;
8 | }
9 | body {
10 | font-family: "Helvetica Neue", Roboto, "Arial Nova", "Segoe UI", Arial, sans-serif;
11 | margin: 0;
12 | }
13 | .logo {
14 | height: 2.2em;
15 | }
16 | }
17 |
18 |
19 |
20 | ${input.title}
21 |
22 |
--------------------------------------------------------------------------------
/examples/lasso-koa/src/components/app-header/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marko-js/examples/90689e6423c68147794cc8d278b1523f1764026b/examples/lasso-koa/src/components/app-header/logo.png
--------------------------------------------------------------------------------
/examples/lasso-koa/src/components/app-layout/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Marko | Lasso + Koa
8 |
9 |
10 |
11 |
12 |
13 | <${input.renderBody}/>
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | style {
29 | .container{
30 | margin-left: auto;
31 | margin-right: auto;
32 | width: 800px;
33 | }
34 | }
--------------------------------------------------------------------------------
/examples/lasso-koa/src/pages/home/components/app-hello/index.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 | class {
4 | onCreate() {
5 | this.state = {
6 | count: 0
7 | }
8 | }
9 |
10 | onMount() {
11 | console.log("Mounted in the browser!");
12 | }
13 |
14 | increment() {
15 | this.state.count++;
16 | }
17 | }
18 |
19 | style {
20 | .count {
21 | color:#09c;
22 | font-size:3em;
23 | }
24 | .example-button {
25 | font-size:1em;
26 | padding:0.5em;
27 | }
28 | }
29 |
30 | Hello ${input.name}
31 |
32 |
33 | ${state.count}
34 |
35 |
36 |
37 | Click me
38 |
39 |
--------------------------------------------------------------------------------
/examples/lasso-koa/src/pages/home/index.js:
--------------------------------------------------------------------------------
1 | import template from "./template.marko";
2 |
3 | export default ctx => {
4 | ctx.type = "html";
5 | ctx.body = template.stream({
6 | name: "Frank",
7 | count: 30,
8 | colors: ["red", "green", "blue"]
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/examples/lasso-koa/src/pages/home/template.marko:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | You have ${input.count} new messages!
5 |
6 |
7 |
8 |
9 | - ${color}
10 |
11 |
12 |
13 |
14 | No colors!
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/library-ts/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/settings.json
2 | *.DS_Store
3 | *.log
4 | *.tgz
5 | coverage
6 | dist
7 | node_modules
8 | .env
9 |
--------------------------------------------------------------------------------
/examples/library-ts/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 | .env
3 |
--------------------------------------------------------------------------------
/examples/library-ts/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | lint-staged && npm run build
2 |
--------------------------------------------------------------------------------
/examples/library-ts/.lintstagedrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/lintstagedrc.schema.json",
3 | "*.{ts,js}": ["eslint --fix", "prettier --write"],
4 | "*.css": ["stylelint --fix", "prettier --write"],
5 | "*.{marko,html,json,md}": ["prettier --write"]
6 | }
7 |
--------------------------------------------------------------------------------
/examples/library-ts/.postcssrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/postcssrc.json",
3 | "plugins": {
4 | "postcss-auto-modules": {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/examples/library-ts/.prettierignore:
--------------------------------------------------------------------------------
1 | __snapshots__
2 | .vscode
3 | CHANGELOG.md
4 | coverage
5 | dist
6 | node_modules
7 | package-lock.json
8 |
--------------------------------------------------------------------------------
/examples/library-ts/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/prettierrc",
3 | "plugins": ["prettier-plugin-packagejson", "prettier-plugin-marko"]
4 | }
5 |
--------------------------------------------------------------------------------
/examples/library-ts/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/marko-vite";
2 |
3 | export default {
4 | framework: "@storybook/marko-vite",
5 | stories: ["../src/**/{,*.}stories.ts"],
6 | addons: ["@storybook/addon-essentials"],
7 | core: {
8 | disableTelemetry: true,
9 | disableWhatsNewNotifications: true,
10 | },
11 | } satisfies StorybookConfig;
12 |
--------------------------------------------------------------------------------
/examples/library-ts/.stylelintignore:
--------------------------------------------------------------------------------
1 | __snapshots__
2 | coverage
3 | dist
4 | node_modules
5 |
--------------------------------------------------------------------------------
/examples/library-ts/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/stylelintrc.json",
3 | "extends": "stylelint-config-standard",
4 | "allowEmptyInput": true,
5 | "cache": true,
6 | "rules": {
7 | "import-notation": "string"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/examples/library-ts/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "Marko-JS.marko-vscode",
6 | "stylelint.vscode-stylelint"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/examples/library-ts/README.md:
--------------------------------------------------------------------------------
1 | # Starter Marko Library with TypeScript
2 |
3 | A template for component libraries and other reusable Marko packages.
4 |
5 | ## Installation
6 |
7 | ```sh
8 | npm init marko -- --template library-ts
9 | ```
10 |
11 | ## Overview
12 |
13 | This project is powered by [Marko](https://markojs.com), [Storybook](https://storybook.js.org), and [Vite](https://vitejs.dev).
14 |
15 | - Run `npm run storybook` to view the component storybook
16 | - Run `npm run test` to run tests with vitest
17 | - Run `npm run build` to build a production-ready library
18 |
--------------------------------------------------------------------------------
/examples/library-ts/eslint.config.js:
--------------------------------------------------------------------------------
1 | import eslint from "@eslint/js";
2 | import sortImportPlugin from "eslint-plugin-simple-import-sort";
3 | import globals from "globals";
4 | import tslint from "typescript-eslint";
5 |
6 | export default tslint.config(
7 | {
8 | ignores: ["__snapshots__", "coverage", "dist", "node_modules"],
9 | },
10 | eslint.configs.recommended,
11 | ...tslint.configs.recommended,
12 | {
13 | languageOptions: {
14 | globals: {
15 | ...globals.browser,
16 | ...globals.node,
17 | },
18 | },
19 | plugins: {
20 | "simple-import-sort": sortImportPlugin,
21 | },
22 | rules: {
23 | "simple-import-sort/imports": "error",
24 | "simple-import-sort/exports": "error",
25 | "@typescript-eslint/no-import-type-side-effects": "error",
26 | "@typescript-eslint/no-non-null-assertion": "off",
27 | "@typescript-eslint/no-empty-function": "off",
28 | "@typescript-eslint/no-explicit-any": "off",
29 | },
30 | },
31 | );
32 |
--------------------------------------------------------------------------------
/examples/library-ts/marko.json:
--------------------------------------------------------------------------------
1 | {
2 | "exports": "./dist/components"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/__snapshots__/server.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`Default 1`] = `
4 |
9 | `;
10 |
11 | exports[`Double 1`] = `
12 |
17 | `;
18 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/browser.test.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent, render, screen } from "@marko/testing-library";
2 | import { composeStories } from "@storybook/marko";
3 |
4 | import * as stories from "./stories";
5 |
6 | const { Default, Double } = composeStories(stories);
7 |
8 | test("Default", async () => {
9 | const { emitted } = await render(Default);
10 | const $btn = screen.getByRole("button");
11 |
12 | expect($btn).toHaveTextContent("0");
13 |
14 | await fireEvent.click($btn);
15 |
16 | expect($btn).toHaveTextContent("1");
17 | expect(emitted("increment")).toHaveLength(1);
18 | });
19 |
20 | test("Double", async () => {
21 | const { emitted } = await render(Double);
22 | const $btn = screen.getByRole("button");
23 |
24 | expect($btn).toHaveTextContent("0");
25 |
26 | await fireEvent.click($btn);
27 |
28 | expect($btn).toHaveTextContent("2");
29 | expect(emitted("increment")).toHaveLength(1);
30 | });
31 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/index.marko:
--------------------------------------------------------------------------------
1 | import style from "./styles.module.css";
2 | export interface Input {
3 | multiplier?: number;
4 | }
5 | class {
6 | declare state: {
7 | count: number;
8 | };
9 |
10 | onCreate() {
11 | this.state = {
12 | count: 0,
13 | };
14 | }
15 |
16 | increment() {
17 | this.state.count++;
18 | this.emit("increment");
19 | }
20 | }
21 |
22 |
25 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/server.test.ts:
--------------------------------------------------------------------------------
1 | import { render, screen } from "@marko/testing-library";
2 | import { composeStories } from "@storybook/marko";
3 |
4 | import * as stories from "./stories";
5 |
6 | for (const [name, story] of Object.entries(composeStories(stories))) {
7 | test(name, async () => {
8 | await render(story);
9 | expect(screen.getByRole("button")).toMatchSnapshot();
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/stories.ts:
--------------------------------------------------------------------------------
1 | import type { Meta, Story } from "@storybook/marko";
2 |
3 | import Template, { type Input } from "./index.marko";
4 |
5 | export default {
6 | title: "Counter",
7 | component: Template,
8 | argTypes: {
9 | multiplier: {
10 | control: {
11 | type: "number",
12 | },
13 | },
14 | },
15 | } as Meta;
16 |
17 | export const Default: Story = {
18 | args: {},
19 | };
20 |
21 | export const Double: Story = {
22 | args: {
23 | multiplier: 2,
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/examples/library-ts/src/components/counter/styles.module.css:
--------------------------------------------------------------------------------
1 | .test {
2 | color: blue;
3 | }
4 |
--------------------------------------------------------------------------------
/examples/library-ts/src/types.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.css" {
2 | const content: { [className: string]: string };
3 | export default content;
4 | }
5 |
--------------------------------------------------------------------------------
/examples/library-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src/**/*"],
3 | "compilerOptions": {
4 | "allowSyntheticDefaultImports": true,
5 | "incremental": true,
6 | "lib": ["dom", "ESNext"],
7 | "module": "ESNext",
8 | "moduleResolution": "bundler",
9 | "noImplicitOverride": true,
10 | "noUnusedLocals": true,
11 | "outDir": "dist",
12 | "resolveJsonModule": true,
13 | "rootDir": "src",
14 | "skipLibCheck": true,
15 | "strict": true,
16 | "target": "ESNext",
17 | "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
18 | "types": ["vite/client", "vitest/globals", "@vitest/browser/matchers"],
19 | "verbatimModuleSyntax": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/library-ts/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import marko from "@marko/vite";
2 | import { defineConfig } from "vitest/config";
3 | const isCI = !!process.env.CI;
4 |
5 | export default defineConfig({
6 | plugins: [marko()],
7 | test: {
8 | globals: true,
9 | coverage: {
10 | enabled: isCI,
11 | provider: "istanbul",
12 | include: ["src/**/*"],
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/examples/library-ts/vitest.workspace.ts:
--------------------------------------------------------------------------------
1 | import { defineWorkspace } from "vitest/config";
2 | const isCI = !!process.env.CI;
3 |
4 | export default defineWorkspace([
5 | {
6 | extends: "vitest.config.ts",
7 | test: {
8 | name: "server",
9 | environment: "node",
10 | include: ["src/**/{,*.}server.test.ts"],
11 | },
12 | },
13 | {
14 | extends: "vitest.config.ts",
15 | test: {
16 | name: "browser",
17 | browser: {
18 | enabled: true,
19 | name: "chromium",
20 | provider: isCI ? "playwright" : "preview",
21 | },
22 | include: ["src/**/{,*.}browser.test.ts"],
23 | },
24 | },
25 | ]);
26 |
--------------------------------------------------------------------------------
/examples/rollup-express/.browserslistrc:
--------------------------------------------------------------------------------
1 | Safari >= 10.1
2 | Chrome >= 61
3 | Firefox >= 60
4 | Edge >= 16
5 |
--------------------------------------------------------------------------------
/examples/rollup-express/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | *.log
4 | .env
5 |
--------------------------------------------------------------------------------
/examples/rollup-express/README.md:
--------------------------------------------------------------------------------
1 | Marko Widgets: UI Components Playground w/ rollup.js
2 | ==================================
3 |
4 | ## Getting Started
5 |
6 | ```bash
7 | npm install
8 | npm run dev
9 | ```
10 |
11 | ## Production Build
12 | ```bash
13 | npm run build
14 | npm start
15 | ```
16 |
--------------------------------------------------------------------------------
/examples/rollup-express/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = api => {
2 | const config = {
3 | presets: ["@babel/env"]
4 | };
5 |
6 | if (api.caller(it => it.target) === "server") {
7 | config.targets = { node: "current" };
8 | }
9 |
10 | return config;
11 | };
12 |
--------------------------------------------------------------------------------
/examples/rollup-express/postcss.config.js:
--------------------------------------------------------------------------------
1 | const presetEnv = require("postcss-preset-env");
2 |
3 | module.exports = () => {
4 | return {
5 | plugins: [
6 | presetEnv()
7 | ]
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-button/index.marko:
--------------------------------------------------------------------------------
1 | class {
2 | handleClick(event) {
3 | // Every Widget instance is also an EventEmitter instance.
4 | // We will emit a custom "click" event when a DOM click event
5 | // is triggered
6 | this.emit("click", {
7 | event: event // Pass along the DOM event in case it is helpful to others
8 | });
9 | }
10 | }
11 |
12 | $ const {
13 | label,
14 | class: className,
15 | size = "normal",
16 | variant = "primary",
17 | ...attrs
18 | } = input;
19 |
20 |
38 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-button/marko-tag.json:
--------------------------------------------------------------------------------
1 | {
2 | "@label": "string",
3 | "@variant": {
4 | "type": "string",
5 | "enum": ["primary", "secondary"]
6 | },
7 | "@size": {
8 | "type": "string",
9 | "enum": ["small", "normal", "large"]
10 | },
11 | "@class": {
12 | "type": "string",
13 | "description": "Additional CSS class names"
14 | },
15 | "@*": "string"
16 | }
17 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-button/style.css:
--------------------------------------------------------------------------------
1 | .app-button {
2 | display: inline-block;
3 | border-radius: 8px;
4 | padding: 12px;
5 | background-color: var(--button-bg);
6 | color: var(--button-fg);
7 | transition-property: background-color;
8 | transition-duration: 0.3s;
9 | transition-timing-function: ease-out;
10 | }
11 |
12 | /* Variants */
13 | .app-button-secondary {
14 | background-color: var(--button-secondary-bg);
15 | color: var(--button-secondary-fg);
16 | }
17 |
18 | .app-button:hover, .app-button-secondary:hover {
19 | filter: brightness(110%);
20 | }
21 |
22 |
23 |
24 | /* Sizes */
25 | .app-button-small {
26 | font-size: 0.9em;
27 | padding-top: 6px;
28 | padding-bottom: 6px;
29 | }
30 |
31 | .app-button-large {
32 | font-size: 1.2em;
33 | font-weight: 100;
34 | }
35 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-checkbox/images/checked.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-checkbox/images/unchecked.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-checkbox/marko-tag.json:
--------------------------------------------------------------------------------
1 | {
2 | "@label": "string",
3 | "@data": "expression",
4 | "@checked": "boolean",
5 | "@class": "string",
6 | "@*": "string"
7 | }
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-checkbox/style.css:
--------------------------------------------------------------------------------
1 | .app-button.app-checkbox {
2 | background-color: var(--button-secondary-bg);
3 | color: var(--button-secondary-fg);
4 | }
5 |
6 | .app-button.app-checkbox.checked {
7 | background-color: var(--button-bg);
8 | color: var(--button-fg);
9 | }
10 |
11 | .app-checkbox-icon {
12 | background-image: url(./images/unchecked.svg);
13 | background-size: contain;
14 | width: 18px;
15 | height: 18px;
16 | display: inline-block;
17 | background-repeat: no-repeat;
18 | opacity: 0.2;
19 | margin-right: 4px;
20 | }
21 |
22 | .app-checkbox.checked .app-checkbox-icon {
23 | background-image: url(./images/checked.svg);
24 | opacity: 1;
25 | }
26 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-fetch-data/style.css:
--------------------------------------------------------------------------------
1 | .app-fetch-data .loading {
2 | background-image: url("./loading.svg");
3 | width: 64px;
4 | height: 64px;
5 | display: inline-block;
6 | vertical-align: middle;
7 | }
8 |
9 | .app-fetch-data .table-container {
10 | max-height: 400px;
11 | overflow: auto;
12 | }
13 |
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-layout/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marko-js/examples/90689e6423c68147794cc8d278b1523f1764026b/examples/rollup-express/src/components/app-layout/favicon.png
--------------------------------------------------------------------------------
/examples/rollup-express/src/components/app-layout/index.marko:
--------------------------------------------------------------------------------
1 | import favicon from "./favicon.png";
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | $ const jsChunk = output.find(chunk => chunk.name === entry);
12 |
13 |
14 |
15 |