Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/app marionette js #7981

Merged
merged 13 commits into from
Jan 20, 2020
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl
| [Vue](app/vue) | [v5.1.0](https://storybooks-vue.netlify.com/) | [![Vue](https://img.shields.io/npm/dm/@storybook/vue.svg)](app/vue) |
| [Angular](app/angular) | [v5.1.0](https://storybooks-angular.netlify.com/) | [![Angular](https://img.shields.io/npm/dm/@storybook/angular.svg)](app/angular) |
| [Polymer](app/polymer) | [v5.1.0](https://storybooks-polymer.netlify.com/) | [![Polymer](https://img.shields.io/npm/dm/@storybook/polymer.svg)](app/polymer) |
| [Marionette.js](app/marionette) | - | [![Marionette.js](https://img.shields.io/npm/dm/@storybook/marionette.svg)](app/marionette) |
| [Mithril](app/mithril) | [v5.1.0](https://storybooks-mithril.netlify.com/) | [![Mithril](https://img.shields.io/npm/dm/@storybook/mithril.svg)](app/mithril) |
| [Marko](app/marko) | [v5.1.0](https://storybooks-marko.netlify.com/) | [![Marko](https://img.shields.io/npm/dm/@storybook/marko.svg)](app/marko) |
| [HTML](app/html) | [v5.1.0](https://storybooks-html.netlify.com/) | [![HTML](https://img.shields.io/npm/dm/@storybook/html.svg)](app/html) |
Expand Down
25 changes: 25 additions & 0 deletions app/marionette/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Storybook for Marionette.js

---

Storybook for Marionette.js is a UI development environment for your Marionette.js components.
With it, you can visualize different states of your UI components and develop them interactively.

![Storybook Screenshot](https://github.com/storybookjs/storybook/blob/master/media/storybook-intro.gif)

Storybook runs outside of your app.
So you can develop UI components in isolation without worrying about app specific dependencies and requirements.

## Getting Started

```sh
cd my-app
npx -p @storybook/cli sb init
```

For more information visit: [storybook.js.org](https://storybook.js.org)

---

Storybook also comes with a lot of [addons](https://storybook.js.org/addons/introduction) and a great API to customize as you wish.
You can also build a [static version](https://storybook.js.org/basics/exporting-storybook) of your storybook and deploy it anywhere you want.
4 changes: 4 additions & 0 deletions app/marionette/bin/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node

process.env.NODE_ENV = process.env.NODE_ENV || 'production';
require('../dist/server/build');
3 changes: 3 additions & 0 deletions app/marionette/bin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node

require('../dist/server');
48 changes: 48 additions & 0 deletions app/marionette/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@storybook/marionette",
"version": "5.3.7",
"description": "Storybook for Marionette: Develop Marionette.js component in isolation with Hot Reloading.",
"keywords": [
"storybook"
],
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/marionette",
"bugs": {
"url": "https://github.com/storybookjs/storybook/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/storybookjs/storybook.git",
"directory": "app/marionette"
},
"license": "MIT",
"main": "dist/client/index.js",
"bin": {
"build-storybook": "./bin/build.js",
"start-storybook": "./bin/index.js",
"storybook-server": "./bin/index.js"
},
"scripts": {
"prepare": "node ../../scripts/prepare.js"
},
"dependencies": {
"@storybook/core": "5.3.7",
"common-tags": "^1.8.0",
"core-js": "^3.0.1",
"global": "^4.3.2",
"html-loader": "^0.5.5",
"regenerator-runtime": "^0.12.1"
},
"devDependencies": {
"backbone.marionette": "*"
},
"peerDependencies": {
"babel-loader": "^7.0.0 || ^8.0.0",
"backbone.marionette": "*"
},
"engines": {
"node": ">=8.0.0"
},
"publishConfig": {
"access": "public"
}
}
15 changes: 15 additions & 0 deletions app/marionette/src/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export {
storiesOf,
setAddon,
addDecorator,
addParameters,
configure,
getStorybook,
forceReRender,
raw,
load,
} from './preview';

if (module && module.hot && module.hot.decline) {
module.hot.decline();
}
18 changes: 18 additions & 0 deletions app/marionette/src/client/preview/element_check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Marionette from 'backbone.marionette';

const allMarionetteViewConstructors = [
'View',
'CompositeView',
'CollectionView',
'NextCollectionView',
];
const viewConstructorsSupportedByMarionette = allMarionetteViewConstructors
.filter(constructorName => constructorName in Marionette)
.map(constructorName => Marionette[constructorName]);

// accepts an element and return true if renderable else return false
const isMarionetteRenderable = element => {
return viewConstructorsSupportedByMarionette.find(Constructor => element instanceof Constructor);
};

export default isMarionetteRenderable;
3 changes: 3 additions & 0 deletions app/marionette/src/client/preview/globals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { window } from 'global';

window.STORYBOOK_ENV = 'marionette';
22 changes: 22 additions & 0 deletions app/marionette/src/client/preview/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { start } from '@storybook/core/client';

import './globals';
import render from './render';

const { load: coreLoad, clientApi, configApi, forceReRender } = start(render);

export const {
setAddon,
addDecorator,
addParameters,
clearDecorators,
getStorybook,
raw,
} = clientApi;

const framework = 'marionette';
export const storiesOf = (...args) => clientApi.storiesOf(...args).addParameters({ framework });
export const load = (...args) => coreLoad(...args, framework);

export const { configure } = configApi;
export { forceReRender };
40 changes: 40 additions & 0 deletions app/marionette/src/client/preview/render.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { document } from 'global';
import { stripIndents } from 'common-tags';
import Marionette from 'backbone.marionette';
import isMarionetteRenderable from './element_check';

const rootEl = document.getElementById('root');
const rootRegion = new Marionette.Region({ el: rootEl });

function render(view) {
rootRegion.show(view);
}

export default function renderMain({ storyFn, selectedKind, selectedStory, showMain, showError }) {
const element = storyFn();

if (!element) {
showError({
title: `Expecting a Marionette View from the story: "${selectedStory}" of "${selectedKind}".`,
description: stripIndents`
Did you forget to return the React element from the story?
Use "() => (<MyComp/>)" or "() => { return <MyComp/>; }" when defining the story.
`,
});
return;
}

if (!isMarionetteRenderable(element)) {
showError({
title: `Expecting a valid Marionette View from the story: "${selectedStory}" of "${selectedKind}".`,
description: stripIndents`
Seems like you are not returning a correct Marionette View from the story.
Could you double check that?
`,
});
return;
}

render(element);
showMain();
}
4 changes: 4 additions & 0 deletions app/marionette/src/server/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { buildStatic } from '@storybook/core/server';
import options from './options';

buildStatic(options);
3 changes: 3 additions & 0 deletions app/marionette/src/server/framework-preset-marionette.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function webpack(config) {
return config;
}
4 changes: 4 additions & 0 deletions app/marionette/src/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { buildDev } from '@storybook/core/server';
import options from './options';

buildDev(options);
6 changes: 6 additions & 0 deletions app/marionette/src/server/options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import packageJson from '../../package.json';

export default {
packageJson,
frameworkPresets: [require.resolve('./framework-preset-marionette.js')],
};
8 changes: 8 additions & 0 deletions app/marionette/standalone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const build = require('@storybook/core/standalone');
const frameworkOptions = require('./dist/server/options').default;

async function buildStandalone(options) {
return build(options, frameworkOptions);
}

module.exports = buildStandalone;
37 changes: 37 additions & 0 deletions lib/cli/generators/MARIONETTE/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import fse from 'fs-extra';
import path from 'path';
import npmInit from '../../lib/npm_init';
import {
getVersion,
getPackageJson,
writePackageJson,
getBabelDependencies,
installDependencies,
} from '../../lib/helpers';

export default async npmOptions => {
const storybookVersion = await getVersion(npmOptions, '@storybook/marionette');
fse.copySync(path.resolve(__dirname, 'template/'), '.', { overwrite: true });

let packageJson = getPackageJson();
if (!packageJson) {
await npmInit();
packageJson = getPackageJson();
}

packageJson.dependencies = packageJson.dependencies || {};
packageJson.devDependencies = packageJson.devDependencies || {};

packageJson.scripts = packageJson.scripts || {};
packageJson.scripts.storybook = 'start-storybook -p 6006';
packageJson.scripts['build-storybook'] = 'build-storybook';

writePackageJson(packageJson);

const babelDependencies = await getBabelDependencies(npmOptions, packageJson);

installDependencies(npmOptions, [
`@storybook/marionette@${storybookVersion}`,
...babelDependencies,
]);
};
9 changes: 9 additions & 0 deletions lib/cli/generators/MARIONETTE/template/.storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { configure } from '@storybook/marionette';

// automatically import all files ending in *.stories.js
const req = require.context('../stories', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);
20 changes: 20 additions & 0 deletions lib/cli/generators/MARIONETTE/template/stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Marionette from 'backbone.marionette';

import { storiesOf } from '@storybook/marionette';

storiesOf('Demo', module).add(
'button',
() =>
new Marionette.View({
template: () => '<button id="my_button">some button</button>',
ui: {
button: '#my_button',
},
triggers: {
'click @ui.button': 'click',
},
onClick() {
console.log('button clicked');
},
})
);
6 changes: 6 additions & 0 deletions lib/cli/lib/detect.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ function detectFramework(dependencies) {
) {
return types.MITHRIL;
}
if (
(dependencies.dependencies && dependencies.dependencies['backbone.marionette']) ||
(dependencies.devDependencies && dependencies.devDependencies['backbone.marionette'])
) {
return types.MARIONETTE;
}

if (
(dependencies.dependencies && dependencies.dependencies.marko) ||
Expand Down
6 changes: 6 additions & 0 deletions lib/cli/lib/initiate.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import vueGenerator from '../generators/VUE';
import polymerGenerator from '../generators/POLYMER';
import webpackReactGenerator from '../generators/WEBPACK_REACT';
import mithrilGenerator from '../generators/MITHRIL';
import marionetteGenerator from '../generators/MARIONETTE';
import markoGenerator from '../generators/MARKO';
import htmlGenerator from '../generators/HTML';
import webComponentsGenerator from '../generators/WEB-COMPONENTS';
Expand Down Expand Up @@ -163,6 +164,11 @@ const installStorybook = (projectType, options) => {
.then(commandLog('Adding storybook support to your "Mithril" app'))
.then(end);

case types.MARIONETTE:
return marionetteGenerator(npmOptions)
.then(commandLog('Adding storybook support to your "Marionette.js" app'))
.then(end);

case types.MARKO:
return markoGenerator(npmOptions, generatorOptions)
.then(commandLog('Adding storybook support to your "Marko" app'))
Expand Down
2 changes: 2 additions & 0 deletions lib/cli/lib/project_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const projectTypes = {
POLYMER: 'POLYMER',
WEB_COMPONENTS: 'WEB_COMPONENTS',
MITHRIL: 'MITHRIL',
MARIONETTE: 'MARIONETTE',
MARKO: 'MARKO',
HTML: 'HTML',
RIOT: 'RIOT',
Expand All @@ -34,6 +35,7 @@ export const supportedFrameworks = [
'mithril',
'riot',
'ember',
'marionette',
'marko',
'meteor',
'preact',
Expand Down
1 change: 1 addition & 0 deletions lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"@storybook/channels": "5.3.7",
"@storybook/ember": "5.3.7",
"@storybook/html": "5.3.7",
"@storybook/marionette": "5.3.7",
"@storybook/marko": "5.3.7",
"@storybook/mithril": "5.3.7",
"@storybook/polymer": "5.3.7",
Expand Down
17 changes: 17 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7459,6 +7459,18 @@ babylon@^6.18.0:
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==

backbone.marionette@*:
version "4.1.2"
resolved "https://registry.yarnpkg.com/backbone.marionette/-/backbone.marionette-4.1.2.tgz#55de74363219f6d5c343dab5bff6aeb20fc44419"
integrity sha512-T8wWxZZnuYjylONTnWZsGsgXtdx2ZrE38pZWJI9LmPqzYK5j0T8uduapFO7OEpsW5rtdbBgwof30xhzAkbb5eQ==
dependencies:
backbone.radio "^2.0.0"

backbone.radio@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/backbone.radio/-/backbone.radio-2.0.0.tgz#bbe8672b373e313f99f36d2fbcf583fe77d04f42"
integrity sha1-u+hnKzc+MT+Z820vvPWD/nfQT0I=

backbone@^1.1.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12"
Expand Down Expand Up @@ -27385,6 +27397,11 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==

regenerator-runtime@^0.12.1:
version "0.12.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==

regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
Expand Down