├── CNAME ├── src ├── styles │ ├── components │ │ ├── footer.scss │ │ ├── transition.scss │ │ ├── header.scss │ │ ├── mouse-pointer.scss │ │ ├── slide.scss │ │ ├── progress.scss │ │ └── presentation-window.scss │ ├── elements │ │ ├── iframe.scss │ │ ├── code.scss │ │ ├── figure.scss │ │ └── img.scss │ ├── settings.scss │ ├── elements.scss │ ├── main.scss │ ├── vendor │ │ └── highlight.css │ └── typography.scss ├── lagom.js ├── bin │ ├── helpers │ │ ├── fetchUtils.js │ │ ├── url-shortener.js │ │ ├── create-gist.js │ │ ├── ask-for-input.js │ │ └── ask-for-selection.js │ ├── lagom-server.js │ ├── lagom-help.js │ ├── lagom.js │ ├── lagom-deploy.js │ └── lagom-create.js ├── scripts │ ├── modules │ │ ├── codeBlocks.js │ │ ├── swipeListener.js │ │ ├── comments.js │ │ ├── localStorage.js │ │ ├── mousePointer.js │ │ ├── slides.js │ │ ├── presentationWindow.js │ │ └── highlighting.js │ └── index.js └── index.html ├── .gitignore ├── lagom.png ├── favicon.ico ├── .babelrc ├── .eslintrc ├── dist ├── starter │ ├── index.html │ └── styles │ │ └── lagom.css └── bin │ ├── lagom-help │ ├── lagom-server │ ├── lagom-create │ ├── lagom-deploy │ └── lagom ├── LICENSE ├── lagom.hook.io.js ├── README.md ├── package.json ├── webpack.config.js └── index.html /CNAME: -------------------------------------------------------------------------------- 1 | lagom.re.im -------------------------------------------------------------------------------- /src/styles/components/footer.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules 3 | .build -------------------------------------------------------------------------------- /lagom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reimertz/lagom/HEAD/lagom.png -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reimertz/lagom/HEAD/favicon.ico -------------------------------------------------------------------------------- /src/styles/elements/iframe.scss: -------------------------------------------------------------------------------- 1 | section iframe { 2 | height: 70vh; 3 | } -------------------------------------------------------------------------------- /src/lagom.js: -------------------------------------------------------------------------------- 1 | // Stylesheets 2 | require('./styles/main.scss') 3 | 4 | // Scripts 5 | require('./scripts/index.js') -------------------------------------------------------------------------------- /src/styles/elements/code.scss: -------------------------------------------------------------------------------- 1 | code.hljs { 2 | margin: 1rem; 3 | padding-bottom: 2rem; 4 | white-space: pre; 5 | font-size: 1.2rem; 6 | } -------------------------------------------------------------------------------- /src/styles/elements/figure.scss: -------------------------------------------------------------------------------- 1 | figure { 2 | text-align: center; 3 | 4 | h1 { 5 | 6 | } 7 | 8 | figcaption { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015" 4 | ], 5 | "plugins": [ 6 | "transform-runtime", 7 | "transform-async-to-generator" 8 | ] 9 | } -------------------------------------------------------------------------------- /src/styles/components/transition.scss: -------------------------------------------------------------------------------- 1 | @for $i from 0 through 200 { 2 | body[data-lagom-current-slide="#{$i}"] { 3 | 4 | section[id="#{$i}"] { 5 | opacity: 1; 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | extends: eslint:recommended 3 | 4 | ecmaFeatures: 5 | modules: true 6 | parserOptions: 7 | sourceType: module 8 | ecmaVersion: 8 9 | env: 10 | es6: true 11 | browser: true 12 | node: true 13 | -------------------------------------------------------------------------------- /src/styles/components/header.scss: -------------------------------------------------------------------------------- 1 | header { 2 | background: white; 3 | font-size: 1.2rem; 4 | left: 1.5rem; 5 | padding: 1rem; 6 | position: fixed; 7 | text-align: left; 8 | top: 1.5rem; 9 | z-index: 3; 10 | } -------------------------------------------------------------------------------- /src/bin/helpers/fetchUtils.js: -------------------------------------------------------------------------------- 1 | export async function checkStatus (response) { 2 | if (response.ok) { 3 | return response 4 | } else { 5 | const error = new Error(response.statusText) 6 | 7 | error.response = response 8 | throw error 9 | } 10 | } -------------------------------------------------------------------------------- /src/scripts/modules/codeBlocks.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js' 2 | 3 | export const renderCodeBlocks = () => { 4 | const codes = document.getElementsByTagName('code') 5 | 6 | Array.prototype.forEach.call(codes, (code) => { 7 | code.innerHTML = code.innerHTML.replace(/ { 5 | const mc = new Manager(document.body) 6 | 7 | mc.add( new Swipe({ direction: DIRECTION_HORIZONTAL, threshold: 0 }) ) 8 | mc.on("swipeleft", nextSlide) 9 | mc.on("swiperight", previousSlide) 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/bin/lagom-server.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | const liveServer = require("live-server") 3 | 4 | const params = { 5 | port: 3000, 6 | file: "index.html", // When set, serve this file for every 404 (useful for single-page applications) 7 | logLevel: 0, // 0 = errors only, 1 = some, 2 = lots 8 | }; 9 | 10 | export const server = () => { 11 | process.stdout.write(chalk.green('◩ lagom-server is running')) 12 | liveServer.start(params) 13 | } 14 | -------------------------------------------------------------------------------- /src/bin/lagom-help.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | 3 | export const help = () => { 4 | process.stdout.write(chalk.green('lagom create create a new presentation\n')) 5 | process.stdout.write(chalk.green('lagom server start live-reloading server\n')) 6 | process.stdout.write(chalk.green('lagom deploy deploy presentation to a gist \n')) 7 | process.stdout.write(chalk.green('lagom help show this help\n')) 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/styles/elements.scss: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | margin: 0; 4 | overflow: hidden; 5 | padding: 0; 6 | position: relative; 7 | } 8 | 9 | body { 10 | background: white; 11 | color: black; 12 | font-family: Menlo !important; 13 | font-size: 20px; 14 | width: 100vw; 15 | } 16 | 17 | left { 18 | text-align: left; 19 | } 20 | 21 | right { 22 | text-align: right; 23 | } 24 | 25 | 26 | ::selection { 27 | color: white; 28 | background: black; 29 | } -------------------------------------------------------------------------------- /src/styles/components/slide.scss: -------------------------------------------------------------------------------- 1 | section, .slide { 2 | transform: translateZ(0); 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | align-items: center; 7 | min-height: 100vh; 8 | min-width: 100vw; 9 | max-width: 800px; 10 | position: relative; 11 | text-align: left; 12 | opacity: 0; 13 | z-index: 0; 14 | 15 | & > * { 16 | margin: 0 5vw; 17 | max-width: 800px; 18 | } 19 | } 20 | 21 | body section { 22 | transition: 750ms; 23 | } 24 | -------------------------------------------------------------------------------- /src/scripts/modules/comments.js: -------------------------------------------------------------------------------- 1 | 2 | export const checkForSlideComment = (id) => { 3 | const commentsContainer = document.getElementById('lagom_comments') 4 | const childNodes = document.querySelector(`section[id="${id}"]`).childNodes 5 | const comments = Array.prototype.filter.call(childNodes, node => { 6 | return node.nodeType === 8 7 | }) 8 | 9 | commentsContainer.innerHTML = '' 10 | 11 | comments.map(comment => { 12 | commentsContainer.innerHTML += comment.textContent 13 | }) 14 | } -------------------------------------------------------------------------------- /src/bin/lagom.js: -------------------------------------------------------------------------------- 1 | import { create } from './lagom-create' 2 | import { server } from './lagom-server' 3 | import { deploy } from './lagom-deploy' 4 | import { help } from './lagom-help' 5 | 6 | if (~process.argv.indexOf('create')){ 7 | create() 8 | } 9 | else if (~process.argv.indexOf('server')){ 10 | server() 11 | } 12 | 13 | else if (~process.argv.indexOf('deploy')){ 14 | const possibleFileName = process.argv[process.argv.indexOf('deploy') + 1] 15 | 16 | deploy(possibleFileName) 17 | } 18 | else { 19 | help() 20 | } 21 | -------------------------------------------------------------------------------- /src/bin/helpers/url-shortener.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import FormData from 'form-data' 3 | import { checkStatus } from './fetchUtils' 4 | 5 | const GIT_IO_URL = 'https://git.io/create' 6 | 7 | export async function urlShortener(gistUrl) { 8 | const form = new FormData() 9 | form.append('url', gistUrl) 10 | 11 | const response = await fetch(GIT_IO_URL, { method: 'post', body: form }) 12 | await checkStatus(response) 13 | const shortUrl = await response.text() 14 | 15 | return shortUrl 16 | 17 | } -------------------------------------------------------------------------------- /src/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import "elements"; 2 | @import "typography"; 3 | 4 | @import "components/header"; 5 | @import "components/progress"; 6 | @import "components/slide"; 7 | @import "components/transition"; 8 | @import "components/mouse-pointer"; 9 | 10 | @import "components/presentation-window"; 11 | 12 | @import "elements/img"; 13 | @import "elements/code"; 14 | @import "elements/iframe"; 15 | 16 | @import "vendor/highlight"; 17 | 18 | @media print { 19 | body { 20 | height: auto; 21 | overflow: scroll; 22 | } 23 | 24 | section { 25 | opacity: 1; 26 | height: 100vh; 27 | } 28 | 29 | span[id=lagom-mousepointer] { 30 | display: none; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/styles/components/progress.scss: -------------------------------------------------------------------------------- 1 | $progress-height: 5px; 2 | 3 | body:before { 4 | background: black; 5 | content: ''; 6 | display: block; 7 | height: $progress-height; 8 | left: 0; 9 | position: fixed; 10 | top: 0; 11 | transition: 500ms width; 12 | z-index: 3; 13 | width: 0%; 14 | } 15 | 16 | body[data-lagom-progress]:before { 17 | width: 100%; 18 | } 19 | 20 | @for $i from 0 through 100 { 21 | body[data-lagom-progress="#{$i}"]:before { 22 | width: percentage($i/100); 23 | } 24 | } 25 | 26 | body:after { 27 | font-size: 1.2rem; 28 | right: 1.5rem; 29 | padding: 1rem; 30 | position: fixed; 31 | text-align: left; 32 | bottom: 1.5rem; 33 | z-index: 3; 34 | content: attr(data-lagom-current-slide) " / " attr(data-lagom-total-slides); 35 | } -------------------------------------------------------------------------------- /src/scripts/modules/localStorage.js: -------------------------------------------------------------------------------- 1 | const PREFIX = `lagom-` 2 | let listeners = [] 3 | 4 | export const persistToLocalstorage = (key, val) => { 5 | localStorage.setItem(`${PREFIX}${key}`, JSON.stringify(val)) 6 | } 7 | 8 | export const getFromLocalStorage = (key) => { 9 | return JSON.parse(localStorage.getItem(`${PREFIX}${key}`)) 10 | } 11 | 12 | export const addStorageEventListener = (event, func) => { 13 | if (!listeners[`${PREFIX}${event}`]) { 14 | listeners[`${PREFIX}${event}`] = [] 15 | } 16 | 17 | listeners[`${PREFIX}${event}`].push(func) 18 | } 19 | 20 | const onStorageEvent = event => { 21 | const { key, newValue} = event 22 | 23 | if(listeners[key]) 24 | listeners[key].map(f => { 25 | f(JSON.parse(newValue)) 26 | }) 27 | } 28 | 29 | window.addEventListener('storage', onStorageEvent) -------------------------------------------------------------------------------- /src/bin/helpers/create-gist.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch' 2 | import { checkStatus } from './fetchUtils' 3 | 4 | const GIST_URL = 'https://api.github.com/gists' 5 | 6 | export async function createGist(indexFile) { 7 | const body = { 8 | description: 'a lagom.js presentation', 9 | public: true, 10 | files: { 11 | 'lagom.html': { 12 | content: indexFile 13 | } 14 | } 15 | } 16 | 17 | const response = await fetch(GIST_URL, { 18 | headers: { 19 | 'User-Agent': 'lagom.js' 20 | }, 21 | method: 'post', 22 | body: JSON.stringify(body) 23 | }) 24 | 25 | await checkStatus(response) 26 | 27 | const json = await response.json() 28 | const htmlFile = json.files['lagom.html'] 29 | const rawUrl = htmlFile.raw_url 30 | 31 | return rawUrl 32 | } -------------------------------------------------------------------------------- /src/styles/components/presentation-window.scss: -------------------------------------------------------------------------------- 1 | body[data-lagom-is-presentation-window="true"] { 2 | 3 | iframe[name="lagom_next_slide"] { 4 | opacity: 0.7; 5 | position: fixed; 6 | top: 5px; 7 | right: 5px; 8 | width: 100vw; 9 | height: 100vh; 10 | z-index: 1; 11 | transform: scale(0.33); 12 | transform-origin: top right; 13 | background: white; 14 | border: 5px solid black; 15 | transition: all 250ms; 16 | 17 | &:hover { 18 | cursor: alias; 19 | transform: scale(0.66); 20 | opacity: 1; 21 | } 22 | } 23 | 24 | aside#lagom_comments { 25 | opacity: 1; 26 | position: fixed; 27 | z-index: 1; 28 | bottom: 10px; 29 | font-size: 1rem; 30 | text-align: center; 31 | background: white; 32 | padding: 1rem 2rem; 33 | white-space: pre; 34 | text-align: left; 35 | max-width: 80%; 36 | 37 | &:empty { 38 | opacity: 0; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/styles/elements/img.scss: -------------------------------------------------------------------------------- 1 | $max-width: 80vw; 2 | $width-small: 300px; 3 | $width-regular: 600px; 4 | $width-large: 800px; 5 | 6 | img { 7 | height: auto; 8 | min-height: $width-small; 9 | max-width: $max-width; 10 | width: $width-regular; 11 | text-align: center; 12 | //border: $width-regular/100 solid black; 13 | max-height: 80vh; 14 | object-fit: cover; 15 | transition: 500ms; 16 | 17 | small > & { 18 | min-height: $width-small; 19 | width: $width-small; 20 | //border-width: $width-small/100; 21 | } 22 | 23 | big > & { 24 | min-height: $width-small; 25 | width: $width-large; 26 | //border-width: $width-large/100; 27 | } 28 | 29 | big > big > & { 30 | transform: translateZ(0); 31 | //border: none; 32 | position: absolute; 33 | top: 0; 34 | left: 0; 35 | width: 100vw; 36 | height: 100vh; 37 | max-width: 100vw; 38 | max-height: 100vh; 39 | z-index: -1; 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} 4 | 5 | 6 |
◩ | {{title}} {{#twitter}}| @{{twitter}}{{/twitter}}
7 | 8 |
9 |

{{title}}

10 |
11 | 12 |
13 | 14 |
15 | 16 |
17 | 18 | {{#homepage}} 19 |

{{homepage}}

20 | {{/homepage}} 21 | {{#twitter}} 22 |

twitter: {{twitter}}

23 | {{/twitter}} 24 | {{#github}} 25 |

github: {{github}}

26 | {{/github}} 27 | 28 | 29 |

created with lagom.js

30 |
31 |
32 | 33 | -------------------------------------------------------------------------------- /dist/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} 4 | 5 | 6 |
◩ | {{title}} {{#twitter}}| @{{twitter}}{{/twitter}}
7 | 8 |
9 |

{{title}}

10 |
11 | 12 |
13 | 14 |
15 | 16 |
17 | 18 | {{#homepage}} 19 |

{{homepage}}

20 | {{/homepage}} 21 | {{#twitter}} 22 |

twitter: {{twitter}}

23 | {{/twitter}} 24 | {{#github}} 25 |

github: {{github}}

26 | {{/github}} 27 | 28 | 29 |

created with lagom.js

30 |
31 |
32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Piérre Reimertz 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/scripts/modules/mousePointer.js: -------------------------------------------------------------------------------- 1 | import { 2 | persistToLocalstorage, 3 | getFromLocalStorage, 4 | addStorageEventListener 5 | } from './localStorage' 6 | 7 | let mousePointerEl 8 | 9 | export const onExternalMousePointerMoved = mousePointer => { 10 | if (!mousePointer) return 11 | 12 | mousePointerEl.style.left = `${mousePointer.x}px` 13 | mousePointerEl.style.top = `${mousePointer.y}px` 14 | } 15 | 16 | export const onMouseMoved = event => { 17 | const { clientX, clientY } = event 18 | persistToLocalstorage('mousepointer', { 19 | x: clientX - 8, 20 | y: clientY + 30 21 | }) 22 | } 23 | 24 | export const initMousePointer = () => { 25 | if (window.name === 'lagom_presentation_window') { 26 | window.addEventListener('mousemove', onMouseMoved) 27 | } 28 | else if (window.name !== 'lagom_next_slide') { 29 | document.body.innerHTML += '' 30 | mousePointerEl = document.getElementById('lagom-mousepointer') 31 | 32 | addStorageEventListener('mousepointer', onExternalMousePointerMoved) 33 | onExternalMousePointerMoved(getFromLocalStorage('mousepointer')) 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/styles/vendor/highlight.css: -------------------------------------------------------------------------------- 1 | .hljs-comment,.hljs-quote{color:#8e908c}.hljs-variable,.hljs-template-variable,.hljs-tag,.hljs-name,.hljs-selector-id,.hljs-selector-class,.hljs-regexp,.hljs-deletion{color:#c82829}.hljs-number,.hljs-built_in,.hljs-builtin-name,.hljs-literal,.hljs-type,.hljs-params,.hljs-meta,.hljs-link{color:#f5871f}.hljs-attribute{color:#eab700}.hljs-string,.hljs-symbol,.hljs-bullet,.hljs-addition{color:#718c00}.hljs-title,.hljs-section{color:#4271ae}.hljs-keyword,.hljs-selector-tag{color:#8959a8}.hljs{display:block;overflow-x:auto;background:white;color:#4d4d4c;padding:0.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} 2 | .hljs-comment,.hljs-quote{color:#8e908c}.hljs-variable,.hljs-template-variable,.hljs-tag,.hljs-name,.hljs-selector-id,.hljs-selector-class,.hljs-regexp,.hljs-deletion{color:#c82829}.hljs-number,.hljs-built_in,.hljs-builtin-name,.hljs-literal,.hljs-type,.hljs-params,.hljs-meta,.hljs-link{color:#f5871f}.hljs-attribute{color:#eab700}.hljs-string,.hljs-symbol,.hljs-bullet,.hljs-addition{color:#718c00}.hljs-title,.hljs-section{color:#4271ae}.hljs-keyword,.hljs-selector-tag{color:#8959a8}.hljs{display:block;overflow-x:auto;background:white;color:#4d4d4c;padding:0.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} -------------------------------------------------------------------------------- /src/scripts/modules/slides.js: -------------------------------------------------------------------------------- 1 | import { 2 | persistToLocalstorage, 3 | getFromLocalStorage, 4 | } from './localStorage' 5 | 6 | import { checkForSlideComment } from './comments' 7 | 8 | export const slides = document.querySelectorAll('body > section') 9 | export const nrOfSlides = slides.length 10 | 11 | document.body.setAttribute('data-lagom-total-slides', nrOfSlides) 12 | 13 | const setHash = id => { 14 | window.location.hash = id 15 | } 16 | 17 | const setProgress = id => { 18 | document.body.setAttribute('data-lagom-progress', Math.floor(((id-1) / (nrOfSlides-1)) * 100)) 19 | } 20 | 21 | const setCurrentSlide = id => { 22 | document.body.setAttribute('data-lagom-current-slide', id) 23 | } 24 | 25 | const updateViews = id => { 26 | setHash(id) 27 | setProgress(id) 28 | setCurrentSlide(id) 29 | } 30 | 31 | export const getCurrentSlide = () => { 32 | return getFromLocalStorage('current-slide') 33 | } 34 | 35 | export const setSlide = id => { 36 | if (window.name === 'lagom_next_slide') { 37 | updateViews(Math.min(getCurrentSlide() + 1, nrOfSlides)) 38 | } 39 | else { 40 | if (window.name === 'lagom_presentation_window') { 41 | checkForSlideComment(id) 42 | } 43 | updateViews(id) 44 | persistToLocalstorage('current-slide', id) 45 | } 46 | } 47 | 48 | export const previousSlide = () => { 49 | return setSlide(Math.max(getCurrentSlide() - 1, 1)) 50 | } 51 | 52 | export const nextSlide = () => { 53 | return setSlide(Math.min(getCurrentSlide() + 1, nrOfSlides)) 54 | } -------------------------------------------------------------------------------- /lagom.hook.io.js: -------------------------------------------------------------------------------- 1 | var https = require('https') 2 | var request = require('request') 3 | 4 | function fetchContent(url) { 5 | return https.request(url, function(newRes) { 6 | var headers = newRes.headers 7 | headers['Content-Type'] = 'text/html charset=utf-8' 8 | delete headers['content-security-policy'] 9 | delete headers['x-frame-options'] 10 | delete headers['strict-transport-security'] 11 | 12 | if (newRes.statusCode !== 200) return hook.res.end('

presentation not found

') 13 | 14 | hook.res.writeHead(newRes.statusCode, headers) 15 | newRes.pipe(hook.res) 16 | }).on('error', function(err) { 17 | hook.res.statusCode = 500 18 | hook.res.end() 19 | }) 20 | } 21 | 22 | module['exports'] = function lagomRenderer (hook) { 23 | var isRawUrl = false, url 24 | 25 | if (hook.params.c) url = 'https://git.io/' + hook.params.c 26 | else if (hook.params.h1 && hook.params.h2) { 27 | var h1 = hook.params.h1 28 | var h2 = hook.params.h2 29 | 30 | isRawUrl = true 31 | 32 | url = 'https://gist.githubusercontent.com/anonymous/' + h1 + '/raw/' + h2 + '/lagom.html' 33 | } 34 | else return hook.res.end('

the url is malformed.

') 35 | 36 | 37 | if (isRawUrl) hook.req.pipe(fetchContent.call(this, url)) 38 | else { 39 | request({ url: url, followRedirect: false }, function (err, res, body) { 40 | if (err) hook.res.end('

the url is malformed.

') 41 | hook.req.pipe(fetchContent.call(this, res.headers.location)) 42 | }) 43 | } 44 | } -------------------------------------------------------------------------------- /src/scripts/index.js: -------------------------------------------------------------------------------- 1 | import { addStorageEventListener } from './modules/localStorage' 2 | 3 | import { 4 | slides, 5 | getCurrentSlide, 6 | setSlide, 7 | previousSlide, 8 | nextSlide 9 | } from './modules/slides' 10 | 11 | import { 12 | openPresentationWindow, 13 | checkIfIsRefreshedPresentationWindow 14 | } from './modules/presentationWindow' 15 | 16 | import { renderCodeBlocks } from './modules/codeBlocks' 17 | import { checkHighlighting } from './modules/highlighting' 18 | import { addSwipeListener } from './modules/swipeListener' 19 | import * as isMobile from 'ismobilejs' 20 | 21 | const onKey = event => { 22 | const keyCode = (event || window.event).keyCode 23 | 24 | if (keyCode == 37) previousSlide() 25 | else if (keyCode == 39) nextSlide() 26 | else if (keyCode == 80 && !(event.metaKey || event.ctrlKey)) openPresentationWindow() 27 | } 28 | 29 | const initLagom = () => { 30 | const initialSlide = getCurrentSlide() || 1 31 | 32 | //;-; some browsers doesn't handle reloads properly and you'll see a white page. 33 | window.location.hash = '' 34 | 35 | Array.prototype.forEach.call(slides, (slide, i) => { 36 | slide.id = i + 1 37 | }) 38 | 39 | //;-; don't want to bring in promises just for this thing. 40 | checkIfIsRefreshedPresentationWindow(() => { 41 | setSlide(initialSlide) 42 | renderCodeBlocks() 43 | }) 44 | 45 | if(isMobile.any) addSwipeListener() 46 | 47 | document.addEventListener('keydown', onKey) 48 | window.addEventListener('mouseup', checkHighlighting) 49 | addStorageEventListener('current-slide', setSlide) 50 | } 51 | 52 | initLagom() -------------------------------------------------------------------------------- /src/styles/typography.scss: -------------------------------------------------------------------------------- 1 | $h1-font-size: 3rem; 2 | $h2-font-size: 2rem; 3 | $h3-font-size: 1.75rem; 4 | $h4-font-size: 1.5rem; 5 | $p-font-size: $h4-font-size; 6 | 7 | html { 8 | font-size: 100%; 9 | transition: font-size 500ms; 10 | } 11 | 12 | h1, h2, h3, h4, h5, h6, p { 13 | font-weight: 400; 14 | background: white; 15 | padding: 0.25rem 1rem; 16 | text-align: center; 17 | } 18 | 19 | h1 { font-size: $h1-font-size; font-weight: 500; margin: $h1-font-size*0.25 auto;} 20 | h2 { font-size: $h2-font-size; margin: $h2-font-size*0.25 auto; } 21 | h3 { font-size: $h3-font-size; margin: $h3-font-size*0.25 auto; } 22 | h4 { font-size: $h4-font-size; margin: $h4-font-size*0.25 auto; } 23 | 24 | p, ul { 25 | font-size: $p-font-size; 26 | line-height: $p-font-size + 0.5; 27 | } 28 | 29 | pre { 30 | text-align: left; 31 | } 32 | 33 | small { 34 | h1 { font-size: $h1-font-size * 0.75; } 35 | h2 { font-size: $h2-font-size * 0.75; } 36 | h3 { font-size: $h3-font-size * 0.75; } 37 | h4 { font-size: $h4-font-size * 0.75; } 38 | p { font-size: $p-font-size * 0.75; } 39 | 40 | } 41 | 42 | big { 43 | h1 { font-size: $h1-font-size * 1.25; } 44 | h2 { font-size: $h2-font-size * 1.25; } 45 | h3 { font-size: $h3-font-size * 1.25; } 46 | h4 { font-size: $h4-font-size * 1.25; } 47 | p { font-size: $p-font-size * 1.25; } 48 | } 49 | 50 | @media (max-width: 1400px) { 51 | html { 52 | font-size: 90%; 53 | } 54 | } 55 | 56 | @media (max-width: 1000px) { 57 | html { 58 | font-size: 85%; 59 | } 60 | } 61 | 62 | @media (max-width: 768px) { 63 | html { 64 | font-size: 80%; 65 | } 66 | } 67 | 68 | @media (max-width: 500px) { 69 | html { 70 | font-size: 70%; 71 | } 72 | } 73 | 74 | @media (max-width: 400px) { 75 | html { 76 | font-size: 65%; 77 | } 78 | } -------------------------------------------------------------------------------- /src/bin/lagom-deploy.js: -------------------------------------------------------------------------------- 1 | import fsp from 'fs-promise' 2 | import { createGist } from './helpers/create-gist' 3 | import { urlShortener } from './helpers/url-shortener' 4 | import chalk from 'chalk' 5 | import Inliner from 'inliner' 6 | 7 | 8 | 9 | const printStatus = async (status) => { 10 | process.stdout.write(`◩ status: ${status}\n`) 11 | } 12 | 13 | const getInlinedFile = async (fileName) => { 14 | const options = { 15 | 'images': false, 16 | 'compressJS': true, 17 | 'collapseWhitespace': false, 18 | 'compressCSS': true, 19 | 'preserveComments': true, 20 | } 21 | 22 | return new Promise(( resolve, reject ) => { 23 | 24 | return new Inliner(fileName, options, (error, html) => { 25 | if (error) reject(error) 26 | else resolve(html) 27 | }).on('progress', printStatus) 28 | 29 | }) 30 | } 31 | 32 | export const deploy = async (fileName = 'index.html') => { 33 | let fileExists, inlinedHTML, rawGistURL, shortenedUrl 34 | process.stdout.write(chalk.green(`◩ lagom: deploy\n`)) 35 | 36 | try { 37 | fileExists = await fsp.exists(`./${fileName}`) 38 | if (!fileExists) throw new Error(`${fileName} doesn't exist`) 39 | 40 | inlinedHTML = await getInlinedFile(`./${fileName}`) 41 | 42 | printStatus('creating gist') 43 | 44 | rawGistURL = await createGist(inlinedHTML) 45 | 46 | printStatus('shortening url') 47 | 48 | try { 49 | shortenedUrl = await urlShortener(rawGistURL) 50 | process.stdout.write(chalk.green(`◩ deployed: http://lagom.hook.io/?c=${shortenedUrl}\n`)) 51 | } 52 | 53 | catch(e) { 54 | let hash1 = rawGistURL.split('/')[4] 55 | let hash2 = rawGistURL.split('/')[6] 56 | 57 | process.stdout.write(chalk.red( `◩ error: couldn't shorten url, fallbacking to regular full url.\n`)) 58 | process.stdout.write(chalk.green(`◩ deployed: http://lagom.hook.io/?h1=${hash1}&h2=${hash2}\n`)) 59 | } 60 | 61 | 62 | 63 | } 64 | 65 | catch(e) { 66 | process.stdout.write(chalk.red(`◩ error: ${e.message}\n`)) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/scripts/modules/presentationWindow.js: -------------------------------------------------------------------------------- 1 | import { initMousePointer } from './mousePointer' 2 | 3 | let presentationWindow = false 4 | 5 | const onResize = () => { 6 | presentationWindow.resizeTo(window.innerWidth, window.innerHeight) 7 | } 8 | 9 | const injectIframeAndPrepAttributes = (done) => { 10 | let body; 11 | presentationWindow.onload = () => { 12 | body = presentationWindow.document.body 13 | 14 | body.setAttribute('data-lagom-is-presentation-window', true) 15 | body.innerHTML += 16 | ` 17 | ` 18 | 19 | done() 20 | } 21 | 22 | presentationWindow.onbeforeunload = () => { 23 | presentationWindow = false; 24 | 25 | [window, presentationWindow].map(object => { 26 | object.removeEventListener('resize', onResize) 27 | }) 28 | } 29 | 30 | window.onbeforeunload = () => { 31 | presentationWindow.close() 32 | } 33 | } 34 | 35 | export const openPresentationWindow = () => { 36 | const options = [ 37 | `${window.location.href}`, 38 | 'lagom_presentation_window', 39 | `_blank`, 40 | `toolbar=0,location=0,menubar=0,resizable=0,width=${window.innerWidth}, height=${window.innerWidth}` 41 | ] 42 | 43 | if (presentationWindow) { 44 | presentationWindow.focus() 45 | } 46 | else { 47 | presentationWindow = window.open.apply(this, options) 48 | injectIframeAndPrepAttributes(); 49 | initMousePointer() 50 | 51 | window.presentationWindow = presentationWindow; 52 | 53 | [window, presentationWindow].map(object => { 54 | object.addEventListener('resize', onResize) 55 | }) 56 | } 57 | } 58 | 59 | export const checkIfIsRefreshedPresentationWindow = (done) => { 60 | const isPresentationWindow = window.name === 'lagom_presentation_window' 61 | const alreadyHookedUp = !!presentationWindow 62 | 63 | if (isPresentationWindow && !alreadyHookedUp) { 64 | presentationWindow = window 65 | injectIframeAndPrepAttributes(done) 66 | initMousePointer() 67 | } 68 | else { 69 | done() 70 | } 71 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Yarn 4 | 5 |

6 | 7 |

8 | simplistic presentation generator 9 |

10 | 11 |

12 | 13 | Build Status 14 | 15 | 16 | NPM version 17 | 18 | 19 | Join gitter channel 20 | 21 |

22 | 23 | --- 24 | 25 | **Ease:** `lagom create` and you have created a folder with a presentation in it. 26 | 27 | **Simplicity:** one `
`, one slide. 28 | 29 | **Maintainable:** `lagom server` boots up your presentation in the browser. it comes with livereloading for easy edits. 30 | 31 | **Magic:** `lagom deploy` will inline all the content of the presentation into one single file, deploy it freely and anonymously on github and finally generate a short url. 32 | 33 | ## Features 34 | - 0 online dependencies: no more OMG!! moments because of bad wifi 35 | - live-reloading server 36 | - Presentation mode: just press p to initiate presentation mode 37 | - Speaker notes 38 | - Synced Aspect ratio 39 | - Synced mouse pointer 40 | - Mirrored highlighting 41 | 42 | 43 | ## install lagom 44 | ``` 45 | yarn global add lagom # much faster 46 | # or 47 | npm install lagom -g --production 48 | ``` 49 | 50 | ## usage 51 | ``` 52 | $ lagom 53 | lagom create create a new presentation 54 | lagom server start live-reloading server 55 | lagom deploy deploy presentation to a gist 56 | lagom help show this help 57 | ``` 58 | 59 | ## example presentations 60 | These is a list of example presentations, please PR this readme if you'd like to add presentation you created. 61 | 62 | - https://reimertz.github.io/lagom/ 63 | - http://lagom.hook.io/?c=vPRgE 64 | 65 | ## todo 66 | 67 | - tests (!) 68 | - iterate on the scss backend 69 | 70 | -------------------------------------------------------------------------------- /src/bin/helpers/ask-for-input.js: -------------------------------------------------------------------------------- 1 | import ansi from 'ansi-escapes' 2 | import chalk from 'chalk' 3 | 4 | //Cred to zeit.co and their email-input thingy. <3 5 | export default function askForInput({ 6 | question = '> Enter your email: ', 7 | appendNewline = true, 8 | forceLowerCase = true, 9 | resolveChars = new Set(['\r']), 10 | abortChars = new Set(['\u0003']), 11 | } = {}) { 12 | return new Promise((resolve, reject) => { 13 | const isRaw = process.stdin.se 14 | 15 | process.stdout.write(chalk.green(question)) 16 | process.stdin.setRawMode(true) 17 | process.stdin.resume() 18 | 19 | let val = '' 20 | let caretOffset = 0 21 | 22 | const ondata = (v) => { 23 | const s = v.toString() 24 | 25 | // abort upon ctrl+C 26 | if (abortChars.has(s)) { 27 | restore() 28 | return reject(new Error('User abort')) 29 | } 30 | 31 | else if ('\u001b[D' === s) { 32 | if (val.length > Math.abs(caretOffset)) { 33 | caretOffset-- 34 | } 35 | } 36 | else if ('\u001b[C' === s) { 37 | if (caretOffset < 0) { 38 | caretOffset++ 39 | } 40 | } 41 | else if ('\x08' === s || '\x7f' === s) { 42 | // delete key needs splicing according to caret position 43 | val = val.substr(0, val.length + caretOffset - 1) + 44 | val.substr(val.length + caretOffset) 45 | } 46 | else { 47 | if (resolveChars.has(s)) { 48 | restore() 49 | return resolve(val) 50 | } 51 | 52 | const add = forceLowerCase ? s.toLowerCase() : s 53 | val = val.substr(0, val.length + caretOffset) + add + 54 | val.substr(val.length + caretOffset) 55 | } 56 | 57 | process.stdout.write(ansi.eraseLines(1) + chalk.green(question) + val) 58 | if (caretOffset) { 59 | process.stdout.write(ansi.cursorBackward(Math.abs(caretOffset))) 60 | } 61 | } 62 | 63 | const restore = () => { 64 | if (appendNewline) process.stdout.write('\n') 65 | 66 | process.stdin.setRawMode(isRaw) 67 | process.stdin.pause() 68 | process.stdin.removeListener('data', ondata) 69 | } 70 | 71 | process.stdin.on('data', ondata) 72 | }) 73 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lagom", 3 | "version": "0.6.5", 4 | "description": "simplistic presentation generator", 5 | "main": "index.js", 6 | "bin": { 7 | "lagom": "./dist/bin/lagom" 8 | }, 9 | "scripts": { 10 | "dist": "rm -rf dist && webpack -p --progress --optimize-minimize", 11 | "build": "webpack", 12 | "bin": "node ./.build/bin/lagom", 13 | "watch": "webpack-dev-server --content-base ./.build/starter", 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "engines": { 17 | "node": ">=4.0.0" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+ssh://git@github.com/reimertz/lagom.git" 22 | }, 23 | "keywords": [ 24 | "slides", 25 | "lagom", 26 | "simplistic", 27 | "presentation", 28 | "javascript" 29 | ], 30 | "author": "Pierre Reimertz", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/reimertz/lagom/issues" 34 | }, 35 | "homepage": "https://github.com/reimertz/lagom", 36 | "dependencies": { 37 | "ansi-escapes": "^1.4.0", 38 | "babel-runtime": "^6.11.6", 39 | "chalk": "^1.1.3", 40 | "form-data": "^2.1.1", 41 | "fs-promise": "^0.5.0", 42 | "live-server": "git://github.com/reimertz/live-server.git", 43 | "mustache": "^2.2.1", 44 | "inliner": "git://github.com/reimertz/inliner.git", 45 | "node-fetch": "^1.6.3" 46 | }, 47 | "devDependencies": { 48 | "any-promise": "^1.3.0", 49 | "autoprefixer": "^6.5.0", 50 | "babel-cli": "^6.14.0", 51 | "babel-loader": "^6.2.5", 52 | "babel-plugin-transform-async-to-generator": "^6.8.0", 53 | "babel-plugin-transform-runtime": "^6.15.0", 54 | "babel-preset-es2015": "^6.14.0", 55 | "babel-register": "^6.14.0", 56 | "css-loader": "^0.25.0", 57 | "eslint": "^3.7.1", 58 | "eslint-loader": "^1.5.0", 59 | "extract-text-webpack-plugin": "^1.0.1", 60 | "hammerjs": "^2.0.8", 61 | "highlight.js": "^9.7.0", 62 | "html-loader": "^0.4.4", 63 | "html-webpack-plugin": "^2.22.0", 64 | "ismobilejs": "^0.4.0", 65 | "node-sass": "^3.10.1", 66 | "postcss-loader": "^0.13.0", 67 | "sass-loader": "^4.0.2", 68 | "style-loader": "^0.13.1", 69 | "webpack": "^1.13.2", 70 | "webpack-dev-server": "^1.16.1", 71 | "webpack-node-externals": "^1.4.3" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/bin/lagom-create.js: -------------------------------------------------------------------------------- 1 | import fsp from 'fs-promise' 2 | import askForInput from './helpers/ask-for-input' 3 | //import askForSelection from './helpers/ask-for-selection' 4 | import chalk from 'chalk' 5 | import Mustache from 'mustache' 6 | 7 | const starterLocation = `${__dirname}/../starter` 8 | 9 | const getInput = async () => { 10 | const title = await askForInput({question: '◩ title: ' }) 11 | //const theme = await askForSelection({question: '◩ theme: ', options:['white', 'black']}) 12 | //const transition = await askForSelection({question: '◩ transitions: ', options:['yes', 'no']}) 13 | const homepage = await askForInput({question: '◩ your www: ' }) 14 | const twitter = await askForInput({question: '◩ twitter: ' }) 15 | const github = await askForInput({question: '◩ github: ' }) 16 | 17 | return { 18 | title, 19 | homepage, 20 | twitter, 21 | github 22 | } 23 | } 24 | 25 | const checkIfFolderExists = async (folderName) => { 26 | return fsp.exists(`./${folderName}`) 27 | } 28 | 29 | 30 | const moveStarterToFolder = async (folderName) => { 31 | return fsp.copy(starterLocation, `./${folderName}`) 32 | } 33 | 34 | const generateIndex = async (folderName, title, homepage, twitter, github) => { 35 | const indexLocation = `./${folderName}/index.html` 36 | const template = await fsp.readFile(`./${folderName}/index.html`, `utf8`) 37 | const rendered = Mustache.render(template, { 38 | title, 39 | homepage, 40 | twitter, 41 | github 42 | }) 43 | 44 | return await fsp.outputFile(indexLocation, rendered) 45 | } 46 | 47 | export const create = async () => { 48 | process.stdout.write(chalk.green('◩ lagom: a simplistic presentation generator\n')) 49 | 50 | const { title, homepage, twitter, github } = await getInput() 51 | const folderName = title.replace(/\s+/g, '-') 52 | 53 | try { 54 | const folderExists = await checkIfFolderExists(folderName) 55 | 56 | if (folderExists) throw new Error('folder already exists.') 57 | 58 | await moveStarterToFolder(folderName) 59 | await generateIndex(folderName, title, homepage, twitter, github) 60 | 61 | process.stdout.write(chalk.green('◩ presentation: ') + 'generated\n') 62 | process.stdout.write(chalk.green('◩ type: ') + chalk.bold(`cd ${folderName}; lagom server`)) 63 | process.stdout.write(chalk.green(' to start\n')) 64 | } 65 | 66 | catch(e) { 67 | process.stdout.write(chalk.red(`◩ ${e}\n`)) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /dist/bin/lagom-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ exports: {}, 16 | /******/ id: moduleId, 17 | /******/ loaded: false 18 | /******/ }; 19 | 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | 23 | /******/ // Flag the module as loaded 24 | /******/ module.loaded = true; 25 | 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | 30 | 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | 37 | /******/ // __webpack_public_path__ 38 | /******/ __webpack_require__.p = ""; 39 | 40 | /******/ // Load entry module and return exports 41 | /******/ return __webpack_require__(0); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ([ 45 | /* 0 */ 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | 'use strict'; 49 | 50 | Object.defineProperty(exports, "__esModule", { 51 | value: true 52 | }); 53 | exports.help = undefined; 54 | 55 | var _chalk = __webpack_require__(1); 56 | 57 | var _chalk2 = _interopRequireDefault(_chalk); 58 | 59 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 60 | 61 | var help = exports.help = function help() { 62 | process.stdout.write(_chalk2.default.green('lagom create create a new presentation\n')); 63 | process.stdout.write(_chalk2.default.green('lagom server start live-reloading server\n')); 64 | process.stdout.write(_chalk2.default.green('lagom deploy deploy presentation to a gist \n')); 65 | process.stdout.write(_chalk2.default.green('lagom help show this help\n')); 66 | }; 67 | 68 | /***/ }, 69 | /* 1 */ 70 | /***/ function(module, exports) { 71 | 72 | module.exports = require("chalk"); 73 | 74 | /***/ } 75 | /******/ ]); -------------------------------------------------------------------------------- /dist/bin/lagom-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ exports: {}, 16 | /******/ id: moduleId, 17 | /******/ loaded: false 18 | /******/ }; 19 | 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | 23 | /******/ // Flag the module as loaded 24 | /******/ module.loaded = true; 25 | 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | 30 | 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | 37 | /******/ // __webpack_public_path__ 38 | /******/ __webpack_require__.p = ""; 39 | 40 | /******/ // Load entry module and return exports 41 | /******/ return __webpack_require__(0); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ([ 45 | /* 0 */ 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | "use strict"; 49 | 50 | Object.defineProperty(exports, "__esModule", { 51 | value: true 52 | }); 53 | exports.server = undefined; 54 | 55 | var _chalk = __webpack_require__(1); 56 | 57 | var _chalk2 = _interopRequireDefault(_chalk); 58 | 59 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 60 | 61 | var liveServer = __webpack_require__(2); 62 | 63 | var params = { 64 | port: 3000, 65 | file: "index.html", // When set, serve this file for every 404 (useful for single-page applications) 66 | logLevel: 0 }; 67 | 68 | var server = exports.server = function server() { 69 | process.stdout.write(_chalk2.default.green('◩ lagom-server is running')); 70 | liveServer.start(params); 71 | }; 72 | 73 | /***/ }, 74 | /* 1 */ 75 | /***/ function(module, exports) { 76 | 77 | module.exports = require("chalk"); 78 | 79 | /***/ }, 80 | /* 2 */ 81 | /***/ function(module, exports) { 82 | 83 | module.exports = require("live-server"); 84 | 85 | /***/ } 86 | /******/ ]); -------------------------------------------------------------------------------- /src/bin/helpers/ask-for-selection.js: -------------------------------------------------------------------------------- 1 | const ansi = require('ansi-escapes') 2 | const chalk = require('chalk') 3 | 4 | //Cred to zeit.co and their email-input thingy. <3 5 | export default function askForInput({ 6 | question = '> Enter your email: ', 7 | options = ['yes', 'no'], 8 | appendNewline = true, 9 | forceLowerCase = true, 10 | suggestionColor = 'gray', 11 | autoCompleteChars = new Set([ 12 | '\t' /* tab */, 13 | '\r' /* return */, 14 | '\u001b[C' /* right arrow */, 15 | ' ' /* spacebar */ 16 | ]), 17 | resolveChars = new Set(['\r']), 18 | abortChars = new Set(['\u0003']), 19 | } = {}) { 20 | return new Promise((resolve, reject) => { 21 | const isRaw = process.stdin.isRaw 22 | const isPaused = process.stdin.isPaused() 23 | const optionsString = options.map((option, index) => { 24 | if(index === 0) return `${chalk.bold(option)}` 25 | else return `${option}` 26 | }).join(' ') 27 | 28 | process.stdout.write(chalk.green(question) + optionsString) 29 | process.stdin.setRawMode(true) 30 | process.stdin.resume() 31 | 32 | let val = '' 33 | let suggestion = '' 34 | let caretOffset = 0 35 | 36 | const ondata = (v) => { 37 | const s = v.toString() 38 | 39 | // abort upon ctrl+C 40 | if (abortChars.has(s)) { 41 | restore() 42 | return reject(new Error('User abort')) 43 | } 44 | 45 | else if ('\u001b[D' === s) { 46 | if (val.length > Math.abs(caretOffset)) { 47 | caretOffset-- 48 | } 49 | } 50 | else if ('\u001b[C' === s) { 51 | if (caretOffset < 0) { 52 | caretOffset++ 53 | } 54 | } 55 | else if ('\x08' === s || '\x7f' === s) { 56 | // delete key needs splicing according to caret position 57 | val = val.substr(0, val.length + caretOffset - 1) + 58 | val.substr(val.length + caretOffset) 59 | } 60 | else { 61 | if (resolveChars.has(s)) { 62 | restore() 63 | return resolve(val) 64 | } 65 | 66 | const add = forceLowerCase ? s.toLowerCase() : s 67 | val = val.substr(0, val.length + caretOffset) + add + 68 | val.substr(val.length + caretOffset) 69 | } 70 | 71 | process.stdout.write(ansi.eraseLines(1) + chalk.green(question) + val) 72 | if (caretOffset) { 73 | process.stdout.write(ansi.cursorBackward(Math.abs(caretOffset))) 74 | } 75 | } 76 | 77 | const restore = () => { 78 | if (appendNewline) process.stdout.write('\n') 79 | 80 | process.stdin.setRawMode(isRaw) 81 | process.stdin.pause() 82 | process.stdin.removeListener('data', ondata) 83 | } 84 | 85 | process.stdin.on('data', ondata) 86 | }) 87 | } -------------------------------------------------------------------------------- /src/scripts/modules/highlighting.js: -------------------------------------------------------------------------------- 1 | import { 2 | persistToLocalstorage, 3 | getFromLocalStorage, 4 | addStorageEventListener 5 | } from './localStorage' 6 | 7 | export const getElementPath = (current, pathArray = []) => { 8 | const parent = current.parentNode 9 | let childIndex 10 | 11 | if (!parent) { 12 | return pathArray 13 | } 14 | else { 15 | childIndex = Array.prototype.indexOf.call(parent.children, current) 16 | return getElementPath(parent, pathArray.concat(childIndex)) 17 | } 18 | } 19 | 20 | const getElementFromPath = (path) => { 21 | return path.reduceRight((node, childIndex) => { 22 | return node.children[childIndex] 23 | }, document) 24 | } 25 | 26 | const onHighlighting = (persistedSelection) => { 27 | if (!persistedSelection) return 28 | 29 | const selection = window.getSelection() 30 | const range = document.createRange(); 31 | const startNode = getElementFromPath(persistedSelection.start.node) 32 | const endNode = getElementFromPath(persistedSelection.end.node) 33 | 34 | try { 35 | range.setStart(startNode.firstChild, persistedSelection.start.offset) 36 | range.setEnd(endNode.firstChild, persistedSelection.end.offset) 37 | selection.removeAllRanges() 38 | selection.addRange(range) 39 | } catch(e) { 40 | selection.removeAllRanges() 41 | } 42 | } 43 | 44 | export const checkHighlighting = () => { 45 | const selection = window.getSelection() 46 | let highlightObject, range 47 | 48 | if (selection) { 49 | if (!selection.anchorNode.parentNode || !selection.focusNode.parentNode) 50 | return persistToLocalstorage('highlight', false) 51 | 52 | let startNode = getElementPath(selection.anchorNode.parentNode) 53 | let endNode = getElementPath(selection.focusNode.parentNode) 54 | 55 | highlightObject = { 56 | start: { 57 | node: startNode, 58 | offset: selection.anchorOffset 59 | }, 60 | end: { 61 | node: endNode, 62 | offset: selection.focusOffset 63 | } 64 | } 65 | 66 | //is the selection right to left? If so, let's do some magic 67 | range = document.createRange() 68 | range.setStart(selection.anchorNode, selection.anchorOffset) 69 | range.setEnd(selection.focusNode, selection.focusOffset) 70 | range.detach() 71 | 72 | if (range.collapsed) { 73 | let tempStart = highlightObject.start 74 | 75 | highlightObject.start = highlightObject.end 76 | highlightObject.end = tempStart 77 | } 78 | 79 | return persistToLocalstorage('highlight', highlightObject) 80 | } 81 | } 82 | 83 | 84 | addStorageEventListener('highlight', onHighlighting) 85 | setTimeout(() => { 86 | onHighlighting(getFromLocalStorage('highlight')) 87 | }, 500) 88 | 89 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const nodeExternals = require('webpack-node-externals') 5 | const autoprefixer = require('autoprefixer') 6 | const path = require('path') 7 | 8 | const isProductionMode = ~process.argv.indexOf('-p') 9 | const outputDir = isProductionMode ? 'dist' : '.build' 10 | 11 | const commandFiles = ['', '-create', '-server', '-deploy', '-help'].map( command => { 12 | return `lagom${command}`; 13 | }) 14 | 15 | const commonOptions = { 16 | resolve: { 17 | extensions: ['', '.js', '.sass'], 18 | modulesDirectories: ['src', 'node_modules'] 19 | } 20 | } 21 | 22 | const binConfigs = commandFiles.map(commandFile => { 23 | return Object.assign({}, commonOptions, { 24 | entry: `./src/bin/${commandFile}.js`, 25 | target: 'node', 26 | node: { 27 | __dirname: false, 28 | __filename: false, 29 | }, 30 | module: { 31 | preLoaders: [{ 32 | test: /\.js$/, loader: "eslint-loader", exclude: /node_modules/ 33 | }], 34 | loaders: [{ 35 | loader: 'babel', 36 | test: /\.js?$/, 37 | exclude: /node_modules/ 38 | }] 39 | }, 40 | plugins: [ 41 | new webpack.BannerPlugin('#!/usr/bin/env node', { raw: true }) 42 | ], 43 | output: { 44 | filename: `${outputDir}/bin/${commandFile}` 45 | }, 46 | externals: [ nodeExternals() ] 47 | }) 48 | }) 49 | 50 | const starterConfig = Object.assign({}, commonOptions, { 51 | entry: './src/lagom.js', 52 | 53 | module: { 54 | preLoaders: [{ 55 | test: /\.js$/, loader: "eslint-loader", exclude: /node_modules/ 56 | }], 57 | loaders: [{ 58 | test: /\.html$/, 59 | loader: 'html', 60 | query: { 61 | minimize: false 62 | } 63 | },{ 64 | test: /\.js?$/, 65 | loader: 'babel', 66 | exclude: /node_modules/ 67 | }, { 68 | test: /\.scss$/, 69 | exclude: /node_modules/, 70 | loader: ExtractTextPlugin.extract( 71 | 'style', // The backup style loader 72 | 'css-loader!postcss-loader!sass-loader' 73 | ), 74 | }] 75 | }, 76 | output: { 77 | filename: `${outputDir}/starter/scripts/lagom.js` 78 | }, 79 | sassLoader: { 80 | includePaths: [ 'src/styles' ] 81 | }, 82 | postcss: function () { 83 | return [autoprefixer({browsers: ['last 5 versions']})]; 84 | }, 85 | plugins: [ 86 | new HtmlWebpackPlugin({ 87 | template: 'src/index.html', 88 | filename: `${outputDir}/starter/index.html`, 89 | inject: false 90 | }), 91 | new ExtractTextPlugin(`${outputDir}/starter/styles/lagom.css`), 92 | new webpack.DefinePlugin({ 93 | 'process.env': { 94 | 'NODE_ENV': isProductionMode ? JSON.stringify('production') : JSON.stringify('development') 95 | } 96 | }) 97 | ] 98 | }) 99 | 100 | module.exports = binConfigs.concat(starterConfig) 101 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | lagom.js 3 | 4 | Fight for the Future 5 |
◩ | lagom.js | docs
6 |
7 |
8 |

lagom.jsbeta

9 |

10 |

a simplistic presentation generator

11 | 12 |

made by @reimertz

13 |
14 |
15 | 19 |
20 | 21 |
22 |

23 | lagom (pronounced [ˈlɑ̀ːɡɔm]) is a Swedish word meaning "just the right amount" 24 |

25 |
26 | 27 |
28 |

a command-line interface

29 | 30 | $ lagom help 31 | 32 | lagom create create a new presentation (default) 33 | lagom server start live-reloading server 34 | lagom deploy deploy presentation 35 | lagom help show this help 36 | 37 |
38 | 39 |
40 |

a lagom architecture

41 | 42 | styles 43 | - lagom.css 44 | scripts 45 | - lagom.js 46 | index.html 47 | 48 |
49 | 50 |
51 |

a lagom markup

52 | 53 | <title>lagom.js</title> 54 | <link rel=stylesheet href="styles/lagom.css"> 55 | 56 | <header> ◩ | lagom.js</header> 57 | 58 | <section> 59 | <h1>lagom.js</h1> 60 | <big><h1>◩</h1></big> 61 | <p>a simplistic presentation generator</p> 62 | </section> 63 | 64 | <script src="scripts/lagom.js"></script> 65 | 66 | 67 |
68 | 69 |
70 |

one section, one slide

71 | 72 | <section></section> 73 | 74 |
75 | 76 |
77 |

elements you are used too

78 | 79 | <h1></h1> 80 | <h2></h2> 81 | <h3></h3> 82 | <p></p> 83 | <ul> 84 | <li></li> 85 | </ul> 86 | <img> 87 | 88 |
89 | 90 |
91 |

old-school modifiers

92 | 93 | <big></big> 94 | <small></small> 95 | 96 | <left></left> 97 | <center></center> 98 | <right></right> 99 | 100 |
101 | 102 |
103 |

a <small> image

104 | 105 | <small> 106 | <img src="tim-and-eric-mind-blown.gif"> 107 | </small> 108 | 109 | 110 | 111 | 112 |
113 | 114 |
115 |

a <big> image

116 | 117 | <big> 118 | <img src="tim-and-eric-mind-blown.gif"> 119 | </big> 120 | 121 | 122 | 123 | 124 |
125 | 126 |
127 |

a <big> <big> image (fullscreen)

128 | 129 | <section> 130 | <h2>a <big> <big> image (fullscreen)</h2> 131 | <big> 132 | <big> 133 | <img src="tim-and-eric-mind-blown.gif"> 134 | </big> 135 | </big> 136 | </section> 137 | 138 | 139 | 140 | 141 | 142 | 143 |
144 | 145 |
146 |

code blocks

147 | 148 | <section> 149 | <h2>code blocks</h2> 150 | <code> 151 | <section> 152 | <h2>code blocks</h2> 153 | <code> 154 | <!-- insert meta joke here --> 155 | </code> 156 | </section> 157 | </code> 158 | </section> 159 | 160 |
161 | 162 |
163 |

presentation mode

164 | 165 | 166 | 167 |

press p to test

168 |
169 | 170 |
171 |

windows are synced

172 |
173 | 174 |
175 |

you can see the next slide ➚

176 | 177 |

(but only if you are in presentation mode)

178 |
179 | 180 |
181 | 182 |
183 |

add notes to a slide

184 | 185 | <section> 186 | <h2>add notes to a slide</h2> 187 | <!-- 188 | this is a note that is 189 | only visible in presentation mode 190 | --> 191 | </section> 192 | 193 | 197 |
198 | 199 |
200 |

matched aspect ratios

201 |

presentation view is locked to the width and height of the main view

202 |
203 | 204 |
205 |

synced highlighting

206 |

when you need to point something out

207 |
208 | 209 |
210 |

synced mouse pointer ☝

211 |

just because i can

212 |
213 | 214 |
215 |

npm install lagom -g --production

216 |

--production to skip devDependencies

217 |
218 | 219 |
220 |

documentation

221 |

github.com/reimertz/lagom

222 |
223 | 224 | 233 | 234 | -------------------------------------------------------------------------------- /dist/bin/lagom-create: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ exports: {}, 16 | /******/ id: moduleId, 17 | /******/ loaded: false 18 | /******/ }; 19 | 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | 23 | /******/ // Flag the module as loaded 24 | /******/ module.loaded = true; 25 | 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | 30 | 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | 37 | /******/ // __webpack_public_path__ 38 | /******/ __webpack_require__.p = ""; 39 | 40 | /******/ // Load entry module and return exports 41 | /******/ return __webpack_require__(0); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ([ 45 | /* 0 */ 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | 'use strict'; 49 | 50 | Object.defineProperty(exports, "__esModule", { 51 | value: true 52 | }); 53 | exports.create = undefined; 54 | 55 | var _regenerator = __webpack_require__(7); 56 | 57 | var _regenerator2 = _interopRequireDefault(_regenerator); 58 | 59 | var _asyncToGenerator2 = __webpack_require__(6); 60 | 61 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 62 | 63 | var _fsPromise = __webpack_require__(8); 64 | 65 | var _fsPromise2 = _interopRequireDefault(_fsPromise); 66 | 67 | var _askForInput = __webpack_require__(2); 68 | 69 | var _askForInput2 = _interopRequireDefault(_askForInput); 70 | 71 | var _chalk = __webpack_require__(1); 72 | 73 | var _chalk2 = _interopRequireDefault(_chalk); 74 | 75 | var _mustache = __webpack_require__(9); 76 | 77 | var _mustache2 = _interopRequireDefault(_mustache); 78 | 79 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 80 | 81 | //import askForSelection from './helpers/ask-for-selection' 82 | var starterLocation = __dirname + '/../starter'; 83 | 84 | var getInput = function () { 85 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() { 86 | var title, homepage, twitter, github; 87 | return _regenerator2.default.wrap(function _callee$(_context) { 88 | while (1) { 89 | switch (_context.prev = _context.next) { 90 | case 0: 91 | _context.next = 2; 92 | return (0, _askForInput2.default)({ question: '◩ title: ' }); 93 | 94 | case 2: 95 | title = _context.sent; 96 | _context.next = 5; 97 | return (0, _askForInput2.default)({ question: '◩ your www: ' }); 98 | 99 | case 5: 100 | homepage = _context.sent; 101 | _context.next = 8; 102 | return (0, _askForInput2.default)({ question: '◩ twitter: ' }); 103 | 104 | case 8: 105 | twitter = _context.sent; 106 | _context.next = 11; 107 | return (0, _askForInput2.default)({ question: '◩ github: ' }); 108 | 109 | case 11: 110 | github = _context.sent; 111 | return _context.abrupt('return', { 112 | title: title, 113 | homepage: homepage, 114 | twitter: twitter, 115 | github: github 116 | }); 117 | 118 | case 13: 119 | case 'end': 120 | return _context.stop(); 121 | } 122 | } 123 | }, _callee, undefined); 124 | })); 125 | 126 | return function getInput() { 127 | return _ref.apply(this, arguments); 128 | }; 129 | }(); 130 | 131 | var checkIfFolderExists = function () { 132 | var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(folderName) { 133 | return _regenerator2.default.wrap(function _callee2$(_context2) { 134 | while (1) { 135 | switch (_context2.prev = _context2.next) { 136 | case 0: 137 | return _context2.abrupt('return', _fsPromise2.default.exists('./' + folderName)); 138 | 139 | case 1: 140 | case 'end': 141 | return _context2.stop(); 142 | } 143 | } 144 | }, _callee2, undefined); 145 | })); 146 | 147 | return function checkIfFolderExists(_x) { 148 | return _ref2.apply(this, arguments); 149 | }; 150 | }(); 151 | 152 | var moveStarterToFolder = function () { 153 | var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(folderName) { 154 | return _regenerator2.default.wrap(function _callee3$(_context3) { 155 | while (1) { 156 | switch (_context3.prev = _context3.next) { 157 | case 0: 158 | return _context3.abrupt('return', _fsPromise2.default.copy(starterLocation, './' + folderName)); 159 | 160 | case 1: 161 | case 'end': 162 | return _context3.stop(); 163 | } 164 | } 165 | }, _callee3, undefined); 166 | })); 167 | 168 | return function moveStarterToFolder(_x2) { 169 | return _ref3.apply(this, arguments); 170 | }; 171 | }(); 172 | 173 | var generateIndex = function () { 174 | var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4(folderName, title, homepage, twitter, github) { 175 | var indexLocation, template, rendered; 176 | return _regenerator2.default.wrap(function _callee4$(_context4) { 177 | while (1) { 178 | switch (_context4.prev = _context4.next) { 179 | case 0: 180 | indexLocation = './' + folderName + '/index.html'; 181 | _context4.next = 3; 182 | return _fsPromise2.default.readFile('./' + folderName + '/index.html', 'utf8'); 183 | 184 | case 3: 185 | template = _context4.sent; 186 | rendered = _mustache2.default.render(template, { 187 | title: title, 188 | homepage: homepage, 189 | twitter: twitter, 190 | github: github 191 | }); 192 | _context4.next = 7; 193 | return _fsPromise2.default.outputFile(indexLocation, rendered); 194 | 195 | case 7: 196 | return _context4.abrupt('return', _context4.sent); 197 | 198 | case 8: 199 | case 'end': 200 | return _context4.stop(); 201 | } 202 | } 203 | }, _callee4, undefined); 204 | })); 205 | 206 | return function generateIndex(_x3, _x4, _x5, _x6, _x7) { 207 | return _ref4.apply(this, arguments); 208 | }; 209 | }(); 210 | 211 | var create = exports.create = function () { 212 | var _ref5 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee5() { 213 | var _ref6, title, homepage, twitter, github, folderName, folderExists; 214 | 215 | return _regenerator2.default.wrap(function _callee5$(_context5) { 216 | while (1) { 217 | switch (_context5.prev = _context5.next) { 218 | case 0: 219 | process.stdout.write(_chalk2.default.green('◩ lagom: a simplistic presentation generator\n')); 220 | 221 | _context5.next = 3; 222 | return getInput(); 223 | 224 | case 3: 225 | _ref6 = _context5.sent; 226 | title = _ref6.title; 227 | homepage = _ref6.homepage; 228 | twitter = _ref6.twitter; 229 | github = _ref6.github; 230 | folderName = title.replace(/\s+/g, '-'); 231 | _context5.prev = 9; 232 | _context5.next = 12; 233 | return checkIfFolderExists(folderName); 234 | 235 | case 12: 236 | folderExists = _context5.sent; 237 | 238 | if (!folderExists) { 239 | _context5.next = 15; 240 | break; 241 | } 242 | 243 | throw new Error('folder already exists.'); 244 | 245 | case 15: 246 | _context5.next = 17; 247 | return moveStarterToFolder(folderName); 248 | 249 | case 17: 250 | _context5.next = 19; 251 | return generateIndex(folderName, title, homepage, twitter, github); 252 | 253 | case 19: 254 | 255 | process.stdout.write(_chalk2.default.green('◩ presentation: ') + 'generated\n'); 256 | process.stdout.write(_chalk2.default.green('◩ type: ') + _chalk2.default.bold('cd ' + folderName + '; lagom server')); 257 | process.stdout.write(_chalk2.default.green(' to start\n')); 258 | _context5.next = 27; 259 | break; 260 | 261 | case 24: 262 | _context5.prev = 24; 263 | _context5.t0 = _context5['catch'](9); 264 | 265 | process.stdout.write(_chalk2.default.red('\u25E9 ' + _context5.t0 + '\n')); 266 | 267 | case 27: 268 | case 'end': 269 | return _context5.stop(); 270 | } 271 | } 272 | }, _callee5, undefined, [[9, 24]]); 273 | })); 274 | 275 | return function create() { 276 | return _ref5.apply(this, arguments); 277 | }; 278 | }(); 279 | 280 | /***/ }, 281 | /* 1 */ 282 | /***/ function(module, exports) { 283 | 284 | module.exports = require("chalk"); 285 | 286 | /***/ }, 287 | /* 2 */ 288 | /***/ function(module, exports, __webpack_require__) { 289 | 290 | 'use strict'; 291 | 292 | Object.defineProperty(exports, "__esModule", { 293 | value: true 294 | }); 295 | 296 | var _set = __webpack_require__(5); 297 | 298 | var _set2 = _interopRequireDefault(_set); 299 | 300 | var _promise = __webpack_require__(4); 301 | 302 | var _promise2 = _interopRequireDefault(_promise); 303 | 304 | exports.default = askForInput; 305 | 306 | var _ansiEscapes = __webpack_require__(3); 307 | 308 | var _ansiEscapes2 = _interopRequireDefault(_ansiEscapes); 309 | 310 | var _chalk = __webpack_require__(1); 311 | 312 | var _chalk2 = _interopRequireDefault(_chalk); 313 | 314 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 315 | 316 | //Cred to zeit.co and their email-input thingy. <3 317 | function askForInput() { 318 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 319 | 320 | var _ref$question = _ref.question; 321 | var question = _ref$question === undefined ? '> Enter your email: ' : _ref$question; 322 | var _ref$appendNewline = _ref.appendNewline; 323 | var appendNewline = _ref$appendNewline === undefined ? true : _ref$appendNewline; 324 | var _ref$forceLowerCase = _ref.forceLowerCase; 325 | var forceLowerCase = _ref$forceLowerCase === undefined ? true : _ref$forceLowerCase; 326 | var _ref$resolveChars = _ref.resolveChars; 327 | var resolveChars = _ref$resolveChars === undefined ? new _set2.default(['\r']) : _ref$resolveChars; 328 | var _ref$abortChars = _ref.abortChars; 329 | var abortChars = _ref$abortChars === undefined ? new _set2.default(['\x03']) : _ref$abortChars; 330 | 331 | return new _promise2.default(function (resolve, reject) { 332 | var isRaw = process.stdin.se; 333 | 334 | process.stdout.write(_chalk2.default.green(question)); 335 | process.stdin.setRawMode(true); 336 | process.stdin.resume(); 337 | 338 | var val = ''; 339 | var caretOffset = 0; 340 | 341 | var ondata = function ondata(v) { 342 | var s = v.toString(); 343 | 344 | // abort upon ctrl+C 345 | if (abortChars.has(s)) { 346 | restore(); 347 | return reject(new Error('User abort')); 348 | } else if ('\x1B[D' === s) { 349 | if (val.length > Math.abs(caretOffset)) { 350 | caretOffset--; 351 | } 352 | } else if ('\x1B[C' === s) { 353 | if (caretOffset < 0) { 354 | caretOffset++; 355 | } 356 | } else if ('\x08' === s || '\x7f' === s) { 357 | // delete key needs splicing according to caret position 358 | val = val.substr(0, val.length + caretOffset - 1) + val.substr(val.length + caretOffset); 359 | } else { 360 | if (resolveChars.has(s)) { 361 | restore(); 362 | return resolve(val); 363 | } 364 | 365 | var add = forceLowerCase ? s.toLowerCase() : s; 366 | val = val.substr(0, val.length + caretOffset) + add + val.substr(val.length + caretOffset); 367 | } 368 | 369 | process.stdout.write(_ansiEscapes2.default.eraseLines(1) + _chalk2.default.green(question) + val); 370 | if (caretOffset) { 371 | process.stdout.write(_ansiEscapes2.default.cursorBackward(Math.abs(caretOffset))); 372 | } 373 | }; 374 | 375 | var restore = function restore() { 376 | if (appendNewline) process.stdout.write('\n'); 377 | 378 | process.stdin.setRawMode(isRaw); 379 | process.stdin.pause(); 380 | process.stdin.removeListener('data', ondata); 381 | }; 382 | 383 | process.stdin.on('data', ondata); 384 | }); 385 | } 386 | 387 | /***/ }, 388 | /* 3 */ 389 | /***/ function(module, exports) { 390 | 391 | module.exports = require("ansi-escapes"); 392 | 393 | /***/ }, 394 | /* 4 */ 395 | /***/ function(module, exports) { 396 | 397 | module.exports = require("babel-runtime/core-js/promise"); 398 | 399 | /***/ }, 400 | /* 5 */ 401 | /***/ function(module, exports) { 402 | 403 | module.exports = require("babel-runtime/core-js/set"); 404 | 405 | /***/ }, 406 | /* 6 */ 407 | /***/ function(module, exports) { 408 | 409 | module.exports = require("babel-runtime/helpers/asyncToGenerator"); 410 | 411 | /***/ }, 412 | /* 7 */ 413 | /***/ function(module, exports) { 414 | 415 | module.exports = require("babel-runtime/regenerator"); 416 | 417 | /***/ }, 418 | /* 8 */ 419 | /***/ function(module, exports) { 420 | 421 | module.exports = require("fs-promise"); 422 | 423 | /***/ }, 424 | /* 9 */ 425 | /***/ function(module, exports) { 426 | 427 | module.exports = require("mustache"); 428 | 429 | /***/ } 430 | /******/ ]); -------------------------------------------------------------------------------- /dist/bin/lagom-deploy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ exports: {}, 16 | /******/ id: moduleId, 17 | /******/ loaded: false 18 | /******/ }; 19 | 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | 23 | /******/ // Flag the module as loaded 24 | /******/ module.loaded = true; 25 | 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | 30 | 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | 37 | /******/ // __webpack_public_path__ 38 | /******/ __webpack_require__.p = ""; 39 | 40 | /******/ // Load entry module and return exports 41 | /******/ return __webpack_require__(0); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ([ 45 | /* 0 */ 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | 'use strict'; 49 | 50 | Object.defineProperty(exports, "__esModule", { 51 | value: true 52 | }); 53 | exports.deploy = undefined; 54 | 55 | var _promise = __webpack_require__(8); 56 | 57 | var _promise2 = _interopRequireDefault(_promise); 58 | 59 | var _regenerator = __webpack_require__(2); 60 | 61 | var _regenerator2 = _interopRequireDefault(_regenerator); 62 | 63 | var _asyncToGenerator2 = __webpack_require__(1); 64 | 65 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 66 | 67 | var _fsPromise = __webpack_require__(11); 68 | 69 | var _fsPromise2 = _interopRequireDefault(_fsPromise); 70 | 71 | var _createGist = __webpack_require__(5); 72 | 73 | var _urlShortener = __webpack_require__(6); 74 | 75 | var _chalk = __webpack_require__(9); 76 | 77 | var _chalk2 = _interopRequireDefault(_chalk); 78 | 79 | var _inliner = __webpack_require__(12); 80 | 81 | var _inliner2 = _interopRequireDefault(_inliner); 82 | 83 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 84 | 85 | var printStatus = function () { 86 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(status) { 87 | return _regenerator2.default.wrap(function _callee$(_context) { 88 | while (1) { 89 | switch (_context.prev = _context.next) { 90 | case 0: 91 | process.stdout.write('\u25E9 status: ' + status + '\n'); 92 | 93 | case 1: 94 | case 'end': 95 | return _context.stop(); 96 | } 97 | } 98 | }, _callee, undefined); 99 | })); 100 | 101 | return function printStatus(_x) { 102 | return _ref.apply(this, arguments); 103 | }; 104 | }(); 105 | 106 | var getInlinedFile = function () { 107 | var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(fileName) { 108 | var options; 109 | return _regenerator2.default.wrap(function _callee2$(_context2) { 110 | while (1) { 111 | switch (_context2.prev = _context2.next) { 112 | case 0: 113 | options = { 114 | 'images': false, 115 | 'compressJS': true, 116 | 'collapseWhitespace': false, 117 | 'compressCSS': true, 118 | 'preserveComments': true 119 | }; 120 | return _context2.abrupt('return', new _promise2.default(function (resolve, reject) { 121 | 122 | return new _inliner2.default(fileName, options, function (error, html) { 123 | if (error) reject(error);else resolve(html); 124 | }).on('progress', printStatus); 125 | })); 126 | 127 | case 2: 128 | case 'end': 129 | return _context2.stop(); 130 | } 131 | } 132 | }, _callee2, undefined); 133 | })); 134 | 135 | return function getInlinedFile(_x2) { 136 | return _ref2.apply(this, arguments); 137 | }; 138 | }(); 139 | 140 | var deploy = exports.deploy = function () { 141 | var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3() { 142 | var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'index.html'; 143 | var fileExists, inlinedHTML, rawGistURL, shortenedUrl, hash1, hash2; 144 | return _regenerator2.default.wrap(function _callee3$(_context3) { 145 | while (1) { 146 | switch (_context3.prev = _context3.next) { 147 | case 0: 148 | fileExists = void 0, inlinedHTML = void 0, rawGistURL = void 0, shortenedUrl = void 0; 149 | 150 | process.stdout.write(_chalk2.default.green('\u25E9 lagom: deploy\n')); 151 | 152 | _context3.prev = 2; 153 | _context3.next = 5; 154 | return _fsPromise2.default.exists('./' + fileName); 155 | 156 | case 5: 157 | fileExists = _context3.sent; 158 | 159 | if (fileExists) { 160 | _context3.next = 8; 161 | break; 162 | } 163 | 164 | throw new Error(fileName + ' doesn\'t exist'); 165 | 166 | case 8: 167 | _context3.next = 10; 168 | return getInlinedFile('./' + fileName); 169 | 170 | case 10: 171 | inlinedHTML = _context3.sent; 172 | 173 | 174 | printStatus('creating gist'); 175 | 176 | _context3.next = 14; 177 | return (0, _createGist.createGist)(inlinedHTML); 178 | 179 | case 14: 180 | rawGistURL = _context3.sent; 181 | 182 | 183 | printStatus('shortening url'); 184 | 185 | _context3.prev = 16; 186 | _context3.next = 19; 187 | return (0, _urlShortener.urlShortener)(rawGistURL); 188 | 189 | case 19: 190 | shortenedUrl = _context3.sent; 191 | 192 | process.stdout.write(_chalk2.default.green('\u25E9 deployed: http://lagom.hook.io/?c=' + shortenedUrl + '\n')); 193 | _context3.next = 29; 194 | break; 195 | 196 | case 23: 197 | _context3.prev = 23; 198 | _context3.t0 = _context3['catch'](16); 199 | hash1 = rawGistURL.split('/')[4]; 200 | hash2 = rawGistURL.split('/')[6]; 201 | 202 | 203 | process.stdout.write(_chalk2.default.red('\u25E9 error: couldn\'t shorten url, fallbacking to regular full url.\n')); 204 | process.stdout.write(_chalk2.default.green('\u25E9 deployed: http://lagom.hook.io/?h1=' + hash1 + '&h2=' + hash2 + '\n')); 205 | 206 | case 29: 207 | _context3.next = 34; 208 | break; 209 | 210 | case 31: 211 | _context3.prev = 31; 212 | _context3.t1 = _context3['catch'](2); 213 | 214 | process.stdout.write(_chalk2.default.red('\u25E9 error: ' + _context3.t1.message + '\n')); 215 | 216 | case 34: 217 | case 'end': 218 | return _context3.stop(); 219 | } 220 | } 221 | }, _callee3, undefined, [[2, 31], [16, 23]]); 222 | })); 223 | 224 | return function deploy(_x3) { 225 | return _ref3.apply(this, arguments); 226 | }; 227 | }(); 228 | 229 | /***/ }, 230 | /* 1 */ 231 | /***/ function(module, exports) { 232 | 233 | module.exports = require("babel-runtime/helpers/asyncToGenerator"); 234 | 235 | /***/ }, 236 | /* 2 */ 237 | /***/ function(module, exports) { 238 | 239 | module.exports = require("babel-runtime/regenerator"); 240 | 241 | /***/ }, 242 | /* 3 */ 243 | /***/ function(module, exports, __webpack_require__) { 244 | 245 | "use strict"; 246 | 247 | Object.defineProperty(exports, "__esModule", { 248 | value: true 249 | }); 250 | exports.checkStatus = undefined; 251 | 252 | var _regenerator = __webpack_require__(2); 253 | 254 | var _regenerator2 = _interopRequireDefault(_regenerator); 255 | 256 | var _asyncToGenerator2 = __webpack_require__(1); 257 | 258 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 259 | 260 | var checkStatus = exports.checkStatus = function () { 261 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(response) { 262 | var error; 263 | return _regenerator2.default.wrap(function _callee$(_context) { 264 | while (1) { 265 | switch (_context.prev = _context.next) { 266 | case 0: 267 | if (!response.ok) { 268 | _context.next = 4; 269 | break; 270 | } 271 | 272 | return _context.abrupt("return", response); 273 | 274 | case 4: 275 | error = new Error(response.statusText); 276 | 277 | 278 | error.response = response; 279 | throw error; 280 | 281 | case 7: 282 | case "end": 283 | return _context.stop(); 284 | } 285 | } 286 | }, _callee, this); 287 | })); 288 | 289 | return function checkStatus(_x) { 290 | return _ref.apply(this, arguments); 291 | }; 292 | }(); 293 | 294 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 295 | 296 | /***/ }, 297 | /* 4 */ 298 | /***/ function(module, exports) { 299 | 300 | module.exports = require("node-fetch"); 301 | 302 | /***/ }, 303 | /* 5 */ 304 | /***/ function(module, exports, __webpack_require__) { 305 | 306 | 'use strict'; 307 | 308 | Object.defineProperty(exports, "__esModule", { 309 | value: true 310 | }); 311 | exports.createGist = undefined; 312 | 313 | var _regenerator = __webpack_require__(2); 314 | 315 | var _regenerator2 = _interopRequireDefault(_regenerator); 316 | 317 | var _stringify = __webpack_require__(7); 318 | 319 | var _stringify2 = _interopRequireDefault(_stringify); 320 | 321 | var _asyncToGenerator2 = __webpack_require__(1); 322 | 323 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 324 | 325 | var createGist = exports.createGist = function () { 326 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(indexFile) { 327 | var body, response, json, htmlFile, rawUrl; 328 | return _regenerator2.default.wrap(function _callee$(_context) { 329 | while (1) { 330 | switch (_context.prev = _context.next) { 331 | case 0: 332 | body = { 333 | description: 'a lagom.js presentation', 334 | public: true, 335 | files: { 336 | 'lagom.html': { 337 | content: indexFile 338 | } 339 | } 340 | }; 341 | _context.next = 3; 342 | return (0, _nodeFetch2.default)(GIST_URL, { 343 | headers: { 344 | 'User-Agent': 'lagom.js' 345 | }, 346 | method: 'post', 347 | body: (0, _stringify2.default)(body) 348 | }); 349 | 350 | case 3: 351 | response = _context.sent; 352 | _context.next = 6; 353 | return (0, _fetchUtils.checkStatus)(response); 354 | 355 | case 6: 356 | _context.next = 8; 357 | return response.json(); 358 | 359 | case 8: 360 | json = _context.sent; 361 | htmlFile = json.files['lagom.html']; 362 | rawUrl = htmlFile.raw_url; 363 | return _context.abrupt('return', rawUrl); 364 | 365 | case 12: 366 | case 'end': 367 | return _context.stop(); 368 | } 369 | } 370 | }, _callee, this); 371 | })); 372 | 373 | return function createGist(_x) { 374 | return _ref.apply(this, arguments); 375 | }; 376 | }(); 377 | 378 | var _nodeFetch = __webpack_require__(4); 379 | 380 | var _nodeFetch2 = _interopRequireDefault(_nodeFetch); 381 | 382 | var _fetchUtils = __webpack_require__(3); 383 | 384 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 385 | 386 | var GIST_URL = 'https://api.github.com/gists'; 387 | 388 | /***/ }, 389 | /* 6 */ 390 | /***/ function(module, exports, __webpack_require__) { 391 | 392 | 'use strict'; 393 | 394 | Object.defineProperty(exports, "__esModule", { 395 | value: true 396 | }); 397 | exports.urlShortener = undefined; 398 | 399 | var _regenerator = __webpack_require__(2); 400 | 401 | var _regenerator2 = _interopRequireDefault(_regenerator); 402 | 403 | var _asyncToGenerator2 = __webpack_require__(1); 404 | 405 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 406 | 407 | var urlShortener = exports.urlShortener = function () { 408 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(gistUrl) { 409 | var form, response, shortUrl; 410 | return _regenerator2.default.wrap(function _callee$(_context) { 411 | while (1) { 412 | switch (_context.prev = _context.next) { 413 | case 0: 414 | form = new _formData2.default(); 415 | 416 | form.append('url', gistUrl); 417 | 418 | _context.next = 4; 419 | return (0, _nodeFetch2.default)(GIT_IO_URL, { method: 'post', body: form }); 420 | 421 | case 4: 422 | response = _context.sent; 423 | _context.next = 7; 424 | return (0, _fetchUtils.checkStatus)(response); 425 | 426 | case 7: 427 | _context.next = 9; 428 | return response.text(); 429 | 430 | case 9: 431 | shortUrl = _context.sent; 432 | return _context.abrupt('return', shortUrl); 433 | 434 | case 11: 435 | case 'end': 436 | return _context.stop(); 437 | } 438 | } 439 | }, _callee, this); 440 | })); 441 | 442 | return function urlShortener(_x) { 443 | return _ref.apply(this, arguments); 444 | }; 445 | }(); 446 | 447 | var _nodeFetch = __webpack_require__(4); 448 | 449 | var _nodeFetch2 = _interopRequireDefault(_nodeFetch); 450 | 451 | var _formData = __webpack_require__(10); 452 | 453 | var _formData2 = _interopRequireDefault(_formData); 454 | 455 | var _fetchUtils = __webpack_require__(3); 456 | 457 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 458 | 459 | var GIT_IO_URL = 'https://git.io/create'; 460 | 461 | /***/ }, 462 | /* 7 */ 463 | /***/ function(module, exports) { 464 | 465 | module.exports = require("babel-runtime/core-js/json/stringify"); 466 | 467 | /***/ }, 468 | /* 8 */ 469 | /***/ function(module, exports) { 470 | 471 | module.exports = require("babel-runtime/core-js/promise"); 472 | 473 | /***/ }, 474 | /* 9 */ 475 | /***/ function(module, exports) { 476 | 477 | module.exports = require("chalk"); 478 | 479 | /***/ }, 480 | /* 10 */ 481 | /***/ function(module, exports) { 482 | 483 | module.exports = require("form-data"); 484 | 485 | /***/ }, 486 | /* 11 */ 487 | /***/ function(module, exports) { 488 | 489 | module.exports = require("fs-promise"); 490 | 491 | /***/ }, 492 | /* 12 */ 493 | /***/ function(module, exports) { 494 | 495 | module.exports = require("inliner"); 496 | 497 | /***/ } 498 | /******/ ]); -------------------------------------------------------------------------------- /dist/starter/styles/lagom.css: -------------------------------------------------------------------------------- 1 | body,html{height:100%;margin:0;overflow:hidden;padding:0;position:relative}body{background:#fff;color:#000;font-family:Menlo!important;font-size:20px;width:100vw}left{text-align:left}right{text-align:right}::-moz-selection{color:#fff;background:#000}::selection{color:#fff;background:#000}html{font-size:100%;transition:font-size .5s}h1,h2,h3,h4,h5,h6,p{font-weight:400;background:#fff;padding:.25rem 1rem;text-align:center}h1{font-size:3rem;font-weight:500;margin:.75rem auto}h2{font-size:2rem;margin:.5rem auto}h3{font-size:1.75rem;margin:.4375rem auto}h4{margin:.375rem auto}h4,p,ul{font-size:1.5rem}p,ul{line-height:2rem}pre{text-align:left}small h1{font-size:2.25rem}small h2{font-size:1.5rem}small h3{font-size:1.3125rem}small h4,small p{font-size:1.125rem}big h1{font-size:3.75rem}big h2{font-size:2.5rem}big h3{font-size:2.1875rem}big h4,big p{font-size:1.875rem}@media (max-width:1400px){html{font-size:90%}}@media (max-width:1000px){html{font-size:85%}}@media (max-width:768px){html{font-size:80%}}@media (max-width:500px){html{font-size:70%}}@media (max-width:400px){html{font-size:65%}}header{background:#fff;font-size:1.2rem;left:1.5rem;padding:1rem;text-align:left;top:1.5rem}body:before,header{position:fixed;z-index:3}body:before{background:#000;content:'';display:block;height:5px;left:0;top:0;transition:width .5s;width:0}body[data-lagom-progress]:before{width:100%}body[data-lagom-progress="0"]:before{width:0}body[data-lagom-progress="1"]:before{width:1%}body[data-lagom-progress="2"]:before{width:2%}body[data-lagom-progress="3"]:before{width:3%}body[data-lagom-progress="4"]:before{width:4%}body[data-lagom-progress="5"]:before{width:5%}body[data-lagom-progress="6"]:before{width:6%}body[data-lagom-progress="7"]:before{width:7%}body[data-lagom-progress="8"]:before{width:8%}body[data-lagom-progress="9"]:before{width:9%}body[data-lagom-progress="10"]:before{width:10%}body[data-lagom-progress="11"]:before{width:11%}body[data-lagom-progress="12"]:before{width:12%}body[data-lagom-progress="13"]:before{width:13%}body[data-lagom-progress="14"]:before{width:14%}body[data-lagom-progress="15"]:before{width:15%}body[data-lagom-progress="16"]:before{width:16%}body[data-lagom-progress="17"]:before{width:17%}body[data-lagom-progress="18"]:before{width:18%}body[data-lagom-progress="19"]:before{width:19%}body[data-lagom-progress="20"]:before{width:20%}body[data-lagom-progress="21"]:before{width:21%}body[data-lagom-progress="22"]:before{width:22%}body[data-lagom-progress="23"]:before{width:23%}body[data-lagom-progress="24"]:before{width:24%}body[data-lagom-progress="25"]:before{width:25%}body[data-lagom-progress="26"]:before{width:26%}body[data-lagom-progress="27"]:before{width:27%}body[data-lagom-progress="28"]:before{width:28%}body[data-lagom-progress="29"]:before{width:29%}body[data-lagom-progress="30"]:before{width:30%}body[data-lagom-progress="31"]:before{width:31%}body[data-lagom-progress="32"]:before{width:32%}body[data-lagom-progress="33"]:before{width:33%}body[data-lagom-progress="34"]:before{width:34%}body[data-lagom-progress="35"]:before{width:35%}body[data-lagom-progress="36"]:before{width:36%}body[data-lagom-progress="37"]:before{width:37%}body[data-lagom-progress="38"]:before{width:38%}body[data-lagom-progress="39"]:before{width:39%}body[data-lagom-progress="40"]:before{width:40%}body[data-lagom-progress="41"]:before{width:41%}body[data-lagom-progress="42"]:before{width:42%}body[data-lagom-progress="43"]:before{width:43%}body[data-lagom-progress="44"]:before{width:44%}body[data-lagom-progress="45"]:before{width:45%}body[data-lagom-progress="46"]:before{width:46%}body[data-lagom-progress="47"]:before{width:47%}body[data-lagom-progress="48"]:before{width:48%}body[data-lagom-progress="49"]:before{width:49%}body[data-lagom-progress="50"]:before{width:50%}body[data-lagom-progress="51"]:before{width:51%}body[data-lagom-progress="52"]:before{width:52%}body[data-lagom-progress="53"]:before{width:53%}body[data-lagom-progress="54"]:before{width:54%}body[data-lagom-progress="55"]:before{width:55%}body[data-lagom-progress="56"]:before{width:56%}body[data-lagom-progress="57"]:before{width:57%}body[data-lagom-progress="58"]:before{width:58%}body[data-lagom-progress="59"]:before{width:59%}body[data-lagom-progress="60"]:before{width:60%}body[data-lagom-progress="61"]:before{width:61%}body[data-lagom-progress="62"]:before{width:62%}body[data-lagom-progress="63"]:before{width:63%}body[data-lagom-progress="64"]:before{width:64%}body[data-lagom-progress="65"]:before{width:65%}body[data-lagom-progress="66"]:before{width:66%}body[data-lagom-progress="67"]:before{width:67%}body[data-lagom-progress="68"]:before{width:68%}body[data-lagom-progress="69"]:before{width:69%}body[data-lagom-progress="70"]:before{width:70%}body[data-lagom-progress="71"]:before{width:71%}body[data-lagom-progress="72"]:before{width:72%}body[data-lagom-progress="73"]:before{width:73%}body[data-lagom-progress="74"]:before{width:74%}body[data-lagom-progress="75"]:before{width:75%}body[data-lagom-progress="76"]:before{width:76%}body[data-lagom-progress="77"]:before{width:77%}body[data-lagom-progress="78"]:before{width:78%}body[data-lagom-progress="79"]:before{width:79%}body[data-lagom-progress="80"]:before{width:80%}body[data-lagom-progress="81"]:before{width:81%}body[data-lagom-progress="82"]:before{width:82%}body[data-lagom-progress="83"]:before{width:83%}body[data-lagom-progress="84"]:before{width:84%}body[data-lagom-progress="85"]:before{width:85%}body[data-lagom-progress="86"]:before{width:86%}body[data-lagom-progress="87"]:before{width:87%}body[data-lagom-progress="88"]:before{width:88%}body[data-lagom-progress="89"]:before{width:89%}body[data-lagom-progress="90"]:before{width:90%}body[data-lagom-progress="91"]:before{width:91%}body[data-lagom-progress="92"]:before{width:92%}body[data-lagom-progress="93"]:before{width:93%}body[data-lagom-progress="94"]:before{width:94%}body[data-lagom-progress="95"]:before{width:95%}body[data-lagom-progress="96"]:before{width:96%}body[data-lagom-progress="97"]:before{width:97%}body[data-lagom-progress="98"]:before{width:98%}body[data-lagom-progress="99"]:before{width:99%}body[data-lagom-progress="100"]:before{width:100%}body:after{font-size:1.2rem;right:1.5rem;padding:1rem;position:fixed;text-align:left;bottom:1.5rem;z-index:3;content:attr(data-lagom-current-slide) " / " attr(data-lagom-total-slides)}.slide,section{-webkit-transform:translateZ(0);transform:translateZ(0);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;min-height:100vh;min-width:100vw;max-width:800px;position:relative;text-align:left;opacity:0;z-index:0}.slide>*,section>*{margin:0 5vw;max-width:800px}body section{transition:.75s}body[data-lagom-current-slide="0"] section[id="0"],body[data-lagom-current-slide="1"] section[id="1"],body[data-lagom-current-slide="2"] section[id="2"],body[data-lagom-current-slide="3"] section[id="3"],body[data-lagom-current-slide="4"] section[id="4"],body[data-lagom-current-slide="5"] section[id="5"],body[data-lagom-current-slide="6"] section[id="6"],body[data-lagom-current-slide="7"] section[id="7"],body[data-lagom-current-slide="8"] section[id="8"],body[data-lagom-current-slide="9"] section[id="9"],body[data-lagom-current-slide="10"] section[id="10"],body[data-lagom-current-slide="11"] section[id="11"],body[data-lagom-current-slide="12"] section[id="12"],body[data-lagom-current-slide="13"] section[id="13"],body[data-lagom-current-slide="14"] section[id="14"],body[data-lagom-current-slide="15"] section[id="15"],body[data-lagom-current-slide="16"] section[id="16"],body[data-lagom-current-slide="17"] section[id="17"],body[data-lagom-current-slide="18"] section[id="18"],body[data-lagom-current-slide="19"] section[id="19"],body[data-lagom-current-slide="20"] section[id="20"],body[data-lagom-current-slide="21"] section[id="21"],body[data-lagom-current-slide="22"] section[id="22"],body[data-lagom-current-slide="23"] section[id="23"],body[data-lagom-current-slide="24"] section[id="24"],body[data-lagom-current-slide="25"] section[id="25"],body[data-lagom-current-slide="26"] section[id="26"],body[data-lagom-current-slide="27"] section[id="27"],body[data-lagom-current-slide="28"] section[id="28"],body[data-lagom-current-slide="29"] section[id="29"],body[data-lagom-current-slide="30"] section[id="30"],body[data-lagom-current-slide="31"] section[id="31"],body[data-lagom-current-slide="32"] section[id="32"],body[data-lagom-current-slide="33"] section[id="33"],body[data-lagom-current-slide="34"] section[id="34"],body[data-lagom-current-slide="35"] section[id="35"],body[data-lagom-current-slide="36"] section[id="36"],body[data-lagom-current-slide="37"] section[id="37"],body[data-lagom-current-slide="38"] section[id="38"],body[data-lagom-current-slide="39"] section[id="39"],body[data-lagom-current-slide="40"] section[id="40"],body[data-lagom-current-slide="41"] section[id="41"],body[data-lagom-current-slide="42"] section[id="42"],body[data-lagom-current-slide="43"] section[id="43"],body[data-lagom-current-slide="44"] section[id="44"],body[data-lagom-current-slide="45"] section[id="45"],body[data-lagom-current-slide="46"] section[id="46"],body[data-lagom-current-slide="47"] section[id="47"],body[data-lagom-current-slide="48"] section[id="48"],body[data-lagom-current-slide="49"] section[id="49"],body[data-lagom-current-slide="50"] section[id="50"],body[data-lagom-current-slide="51"] section[id="51"],body[data-lagom-current-slide="52"] section[id="52"],body[data-lagom-current-slide="53"] section[id="53"],body[data-lagom-current-slide="54"] section[id="54"],body[data-lagom-current-slide="55"] section[id="55"],body[data-lagom-current-slide="56"] section[id="56"],body[data-lagom-current-slide="57"] section[id="57"],body[data-lagom-current-slide="58"] section[id="58"],body[data-lagom-current-slide="59"] section[id="59"],body[data-lagom-current-slide="60"] section[id="60"],body[data-lagom-current-slide="61"] section[id="61"],body[data-lagom-current-slide="62"] section[id="62"],body[data-lagom-current-slide="63"] section[id="63"],body[data-lagom-current-slide="64"] section[id="64"],body[data-lagom-current-slide="65"] section[id="65"],body[data-lagom-current-slide="66"] section[id="66"],body[data-lagom-current-slide="67"] section[id="67"],body[data-lagom-current-slide="68"] section[id="68"],body[data-lagom-current-slide="69"] section[id="69"],body[data-lagom-current-slide="70"] section[id="70"],body[data-lagom-current-slide="71"] section[id="71"],body[data-lagom-current-slide="72"] section[id="72"],body[data-lagom-current-slide="73"] section[id="73"],body[data-lagom-current-slide="74"] section[id="74"],body[data-lagom-current-slide="75"] section[id="75"],body[data-lagom-current-slide="76"] section[id="76"],body[data-lagom-current-slide="77"] section[id="77"],body[data-lagom-current-slide="78"] section[id="78"],body[data-lagom-current-slide="79"] section[id="79"],body[data-lagom-current-slide="80"] section[id="80"],body[data-lagom-current-slide="81"] section[id="81"],body[data-lagom-current-slide="82"] section[id="82"],body[data-lagom-current-slide="83"] section[id="83"],body[data-lagom-current-slide="84"] section[id="84"],body[data-lagom-current-slide="85"] section[id="85"],body[data-lagom-current-slide="86"] section[id="86"],body[data-lagom-current-slide="87"] section[id="87"],body[data-lagom-current-slide="88"] section[id="88"],body[data-lagom-current-slide="89"] section[id="89"],body[data-lagom-current-slide="90"] section[id="90"],body[data-lagom-current-slide="91"] section[id="91"],body[data-lagom-current-slide="92"] section[id="92"],body[data-lagom-current-slide="93"] section[id="93"],body[data-lagom-current-slide="94"] section[id="94"],body[data-lagom-current-slide="95"] section[id="95"],body[data-lagom-current-slide="96"] section[id="96"],body[data-lagom-current-slide="97"] section[id="97"],body[data-lagom-current-slide="98"] section[id="98"],body[data-lagom-current-slide="99"] section[id="99"],body[data-lagom-current-slide="100"] section[id="100"],body[data-lagom-current-slide="101"] section[id="101"],body[data-lagom-current-slide="102"] section[id="102"],body[data-lagom-current-slide="103"] section[id="103"],body[data-lagom-current-slide="104"] section[id="104"],body[data-lagom-current-slide="105"] section[id="105"],body[data-lagom-current-slide="106"] section[id="106"],body[data-lagom-current-slide="107"] section[id="107"],body[data-lagom-current-slide="108"] section[id="108"],body[data-lagom-current-slide="109"] section[id="109"],body[data-lagom-current-slide="110"] section[id="110"],body[data-lagom-current-slide="111"] section[id="111"],body[data-lagom-current-slide="112"] section[id="112"],body[data-lagom-current-slide="113"] section[id="113"],body[data-lagom-current-slide="114"] section[id="114"],body[data-lagom-current-slide="115"] section[id="115"],body[data-lagom-current-slide="116"] section[id="116"],body[data-lagom-current-slide="117"] section[id="117"],body[data-lagom-current-slide="118"] section[id="118"],body[data-lagom-current-slide="119"] section[id="119"],body[data-lagom-current-slide="120"] section[id="120"],body[data-lagom-current-slide="121"] section[id="121"],body[data-lagom-current-slide="122"] section[id="122"],body[data-lagom-current-slide="123"] section[id="123"],body[data-lagom-current-slide="124"] section[id="124"],body[data-lagom-current-slide="125"] section[id="125"],body[data-lagom-current-slide="126"] section[id="126"],body[data-lagom-current-slide="127"] section[id="127"],body[data-lagom-current-slide="128"] section[id="128"],body[data-lagom-current-slide="129"] section[id="129"],body[data-lagom-current-slide="130"] section[id="130"],body[data-lagom-current-slide="131"] section[id="131"],body[data-lagom-current-slide="132"] section[id="132"],body[data-lagom-current-slide="133"] section[id="133"],body[data-lagom-current-slide="134"] section[id="134"],body[data-lagom-current-slide="135"] section[id="135"],body[data-lagom-current-slide="136"] section[id="136"],body[data-lagom-current-slide="137"] section[id="137"],body[data-lagom-current-slide="138"] section[id="138"],body[data-lagom-current-slide="139"] section[id="139"],body[data-lagom-current-slide="140"] section[id="140"],body[data-lagom-current-slide="141"] section[id="141"],body[data-lagom-current-slide="142"] section[id="142"],body[data-lagom-current-slide="143"] section[id="143"],body[data-lagom-current-slide="144"] section[id="144"],body[data-lagom-current-slide="145"] section[id="145"],body[data-lagom-current-slide="146"] section[id="146"],body[data-lagom-current-slide="147"] section[id="147"],body[data-lagom-current-slide="148"] section[id="148"],body[data-lagom-current-slide="149"] section[id="149"],body[data-lagom-current-slide="150"] section[id="150"],body[data-lagom-current-slide="151"] section[id="151"],body[data-lagom-current-slide="152"] section[id="152"],body[data-lagom-current-slide="153"] section[id="153"],body[data-lagom-current-slide="154"] section[id="154"],body[data-lagom-current-slide="155"] section[id="155"],body[data-lagom-current-slide="156"] section[id="156"],body[data-lagom-current-slide="157"] section[id="157"],body[data-lagom-current-slide="158"] section[id="158"],body[data-lagom-current-slide="159"] section[id="159"],body[data-lagom-current-slide="160"] section[id="160"],body[data-lagom-current-slide="161"] section[id="161"],body[data-lagom-current-slide="162"] section[id="162"],body[data-lagom-current-slide="163"] section[id="163"],body[data-lagom-current-slide="164"] section[id="164"],body[data-lagom-current-slide="165"] section[id="165"],body[data-lagom-current-slide="166"] section[id="166"],body[data-lagom-current-slide="167"] section[id="167"],body[data-lagom-current-slide="168"] section[id="168"],body[data-lagom-current-slide="169"] section[id="169"],body[data-lagom-current-slide="170"] section[id="170"],body[data-lagom-current-slide="171"] section[id="171"],body[data-lagom-current-slide="172"] section[id="172"],body[data-lagom-current-slide="173"] section[id="173"],body[data-lagom-current-slide="174"] section[id="174"],body[data-lagom-current-slide="175"] section[id="175"],body[data-lagom-current-slide="176"] section[id="176"],body[data-lagom-current-slide="177"] section[id="177"],body[data-lagom-current-slide="178"] section[id="178"],body[data-lagom-current-slide="179"] section[id="179"],body[data-lagom-current-slide="180"] section[id="180"],body[data-lagom-current-slide="181"] section[id="181"],body[data-lagom-current-slide="182"] section[id="182"],body[data-lagom-current-slide="183"] section[id="183"],body[data-lagom-current-slide="184"] section[id="184"],body[data-lagom-current-slide="185"] section[id="185"],body[data-lagom-current-slide="186"] section[id="186"],body[data-lagom-current-slide="187"] section[id="187"],body[data-lagom-current-slide="188"] section[id="188"],body[data-lagom-current-slide="189"] section[id="189"],body[data-lagom-current-slide="190"] section[id="190"],body[data-lagom-current-slide="191"] section[id="191"],body[data-lagom-current-slide="192"] section[id="192"],body[data-lagom-current-slide="193"] section[id="193"],body[data-lagom-current-slide="194"] section[id="194"],body[data-lagom-current-slide="195"] section[id="195"],body[data-lagom-current-slide="196"] section[id="196"],body[data-lagom-current-slide="197"] section[id="197"],body[data-lagom-current-slide="198"] section[id="198"],body[data-lagom-current-slide="199"] section[id="199"],body[data-lagom-current-slide="200"] section[id="200"]{opacity:1}span[id=lagom-mousepointer]{position:fixed;font-size:2rem;width:10px;height:10px;top:0;left:0;line-height:10px;z-index:3}body[data-lagom-is-presentation-window=true] span[id=lagom-mousepointer]{display:none}body[data-lagom-is-presentation-window=true] iframe[name=lagom_next_slide]{opacity:.7;position:fixed;top:5px;right:5px;width:100vw;height:100vh;z-index:1;-webkit-transform:scale(.33);transform:scale(.33);-webkit-transform-origin:top right;transform-origin:top right;background:#fff;border:5px solid #000;transition:all .25s}body[data-lagom-is-presentation-window=true] iframe[name=lagom_next_slide]:hover{cursor:alias;-webkit-transform:scale(.66);transform:scale(.66);opacity:1}body[data-lagom-is-presentation-window=true] aside#lagom_comments{opacity:1;position:fixed;z-index:1;bottom:10px;font-size:1rem;text-align:center;background:#fff;padding:1rem 2rem;white-space:pre;text-align:left;max-width:80%}body[data-lagom-is-presentation-window=true] aside#lagom_comments:empty{opacity:0}img{height:auto;max-width:80vw;width:600px;text-align:center;max-height:80vh;object-fit:cover;transition:.5s}img,small>img{min-height:300px}small>img{width:300px}big>img{min-height:300px;width:800px}big>big>img{-webkit-transform:translateZ(0);transform:translateZ(0);position:absolute;top:0;left:0;width:100vw;height:100vh;max-width:100vw;max-height:100vh;z-index:-1}code.hljs{margin:1rem;padding-bottom:2rem;white-space:pre;font-size:1.2rem}section iframe{height:70vh}.hljs-comment,.hljs-quote{color:#8e908c}.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#c82829}.hljs-built_in,.hljs-builtin-name,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#f5871f}.hljs-attribute{color:#eab700}.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:#718c00}.hljs-section,.hljs-title{color:#4271ae}.hljs-keyword,.hljs-selector-tag{color:#8959a8}.hljs{display:block;overflow-x:auto;background:#fff;color:#4d4d4c;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}@media print{body{height:auto;overflow:scroll}section{opacity:1;height:100vh}span[id=lagom-mousepointer]{display:none}} -------------------------------------------------------------------------------- /dist/bin/lagom: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) 11 | /******/ return installedModules[moduleId].exports; 12 | 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ exports: {}, 16 | /******/ id: moduleId, 17 | /******/ loaded: false 18 | /******/ }; 19 | 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | 23 | /******/ // Flag the module as loaded 24 | /******/ module.loaded = true; 25 | 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | 30 | 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | 37 | /******/ // __webpack_public_path__ 38 | /******/ __webpack_require__.p = ""; 39 | 40 | /******/ // Load entry module and return exports 41 | /******/ return __webpack_require__(0); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ([ 45 | /* 0 */ 46 | /***/ function(module, exports, __webpack_require__) { 47 | 48 | 'use strict'; 49 | 50 | var _lagomCreate = __webpack_require__(11); 51 | 52 | var _lagomServer = __webpack_require__(14); 53 | 54 | var _lagomDeploy = __webpack_require__(12); 55 | 56 | var _lagomHelp = __webpack_require__(13); 57 | 58 | if (~process.argv.indexOf('create')) { 59 | (0, _lagomCreate.create)(); 60 | } else if (~process.argv.indexOf('server')) { 61 | (0, _lagomServer.server)(); 62 | } else if (~process.argv.indexOf('deploy')) { 63 | var possibleFileName = process.argv[process.argv.indexOf('deploy') + 1]; 64 | 65 | (0, _lagomDeploy.deploy)(possibleFileName); 66 | } else { 67 | (0, _lagomHelp.help)(); 68 | } 69 | 70 | /***/ }, 71 | /* 1 */ 72 | /***/ function(module, exports) { 73 | 74 | module.exports = require("babel-runtime/helpers/asyncToGenerator"); 75 | 76 | /***/ }, 77 | /* 2 */ 78 | /***/ function(module, exports) { 79 | 80 | module.exports = require("babel-runtime/regenerator"); 81 | 82 | /***/ }, 83 | /* 3 */ 84 | /***/ function(module, exports) { 85 | 86 | module.exports = require("chalk"); 87 | 88 | /***/ }, 89 | /* 4 */ 90 | /***/ function(module, exports, __webpack_require__) { 91 | 92 | "use strict"; 93 | 94 | Object.defineProperty(exports, "__esModule", { 95 | value: true 96 | }); 97 | exports.checkStatus = undefined; 98 | 99 | var _regenerator = __webpack_require__(2); 100 | 101 | var _regenerator2 = _interopRequireDefault(_regenerator); 102 | 103 | var _asyncToGenerator2 = __webpack_require__(1); 104 | 105 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 106 | 107 | var checkStatus = exports.checkStatus = function () { 108 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(response) { 109 | var error; 110 | return _regenerator2.default.wrap(function _callee$(_context) { 111 | while (1) { 112 | switch (_context.prev = _context.next) { 113 | case 0: 114 | if (!response.ok) { 115 | _context.next = 4; 116 | break; 117 | } 118 | 119 | return _context.abrupt("return", response); 120 | 121 | case 4: 122 | error = new Error(response.statusText); 123 | 124 | 125 | error.response = response; 126 | throw error; 127 | 128 | case 7: 129 | case "end": 130 | return _context.stop(); 131 | } 132 | } 133 | }, _callee, this); 134 | })); 135 | 136 | return function checkStatus(_x) { 137 | return _ref.apply(this, arguments); 138 | }; 139 | }(); 140 | 141 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 142 | 143 | /***/ }, 144 | /* 5 */ 145 | /***/ function(module, exports) { 146 | 147 | module.exports = require("babel-runtime/core-js/promise"); 148 | 149 | /***/ }, 150 | /* 6 */ 151 | /***/ function(module, exports) { 152 | 153 | module.exports = require("fs-promise"); 154 | 155 | /***/ }, 156 | /* 7 */ 157 | /***/ function(module, exports) { 158 | 159 | module.exports = require("node-fetch"); 160 | 161 | /***/ }, 162 | /* 8 */ 163 | /***/ function(module, exports, __webpack_require__) { 164 | 165 | 'use strict'; 166 | 167 | Object.defineProperty(exports, "__esModule", { 168 | value: true 169 | }); 170 | 171 | var _set = __webpack_require__(17); 172 | 173 | var _set2 = _interopRequireDefault(_set); 174 | 175 | var _promise = __webpack_require__(5); 176 | 177 | var _promise2 = _interopRequireDefault(_promise); 178 | 179 | exports.default = askForInput; 180 | 181 | var _ansiEscapes = __webpack_require__(15); 182 | 183 | var _ansiEscapes2 = _interopRequireDefault(_ansiEscapes); 184 | 185 | var _chalk = __webpack_require__(3); 186 | 187 | var _chalk2 = _interopRequireDefault(_chalk); 188 | 189 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 190 | 191 | //Cred to zeit.co and their email-input thingy. <3 192 | function askForInput() { 193 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 194 | 195 | var _ref$question = _ref.question; 196 | var question = _ref$question === undefined ? '> Enter your email: ' : _ref$question; 197 | var _ref$appendNewline = _ref.appendNewline; 198 | var appendNewline = _ref$appendNewline === undefined ? true : _ref$appendNewline; 199 | var _ref$forceLowerCase = _ref.forceLowerCase; 200 | var forceLowerCase = _ref$forceLowerCase === undefined ? true : _ref$forceLowerCase; 201 | var _ref$resolveChars = _ref.resolveChars; 202 | var resolveChars = _ref$resolveChars === undefined ? new _set2.default(['\r']) : _ref$resolveChars; 203 | var _ref$abortChars = _ref.abortChars; 204 | var abortChars = _ref$abortChars === undefined ? new _set2.default(['\x03']) : _ref$abortChars; 205 | 206 | return new _promise2.default(function (resolve, reject) { 207 | var isRaw = process.stdin.se; 208 | 209 | process.stdout.write(_chalk2.default.green(question)); 210 | process.stdin.setRawMode(true); 211 | process.stdin.resume(); 212 | 213 | var val = ''; 214 | var caretOffset = 0; 215 | 216 | var ondata = function ondata(v) { 217 | var s = v.toString(); 218 | 219 | // abort upon ctrl+C 220 | if (abortChars.has(s)) { 221 | restore(); 222 | return reject(new Error('User abort')); 223 | } else if ('\x1B[D' === s) { 224 | if (val.length > Math.abs(caretOffset)) { 225 | caretOffset--; 226 | } 227 | } else if ('\x1B[C' === s) { 228 | if (caretOffset < 0) { 229 | caretOffset++; 230 | } 231 | } else if ('\x08' === s || '\x7f' === s) { 232 | // delete key needs splicing according to caret position 233 | val = val.substr(0, val.length + caretOffset - 1) + val.substr(val.length + caretOffset); 234 | } else { 235 | if (resolveChars.has(s)) { 236 | restore(); 237 | return resolve(val); 238 | } 239 | 240 | var add = forceLowerCase ? s.toLowerCase() : s; 241 | val = val.substr(0, val.length + caretOffset) + add + val.substr(val.length + caretOffset); 242 | } 243 | 244 | process.stdout.write(_ansiEscapes2.default.eraseLines(1) + _chalk2.default.green(question) + val); 245 | if (caretOffset) { 246 | process.stdout.write(_ansiEscapes2.default.cursorBackward(Math.abs(caretOffset))); 247 | } 248 | }; 249 | 250 | var restore = function restore() { 251 | if (appendNewline) process.stdout.write('\n'); 252 | 253 | process.stdin.setRawMode(isRaw); 254 | process.stdin.pause(); 255 | process.stdin.removeListener('data', ondata); 256 | }; 257 | 258 | process.stdin.on('data', ondata); 259 | }); 260 | } 261 | 262 | /***/ }, 263 | /* 9 */ 264 | /***/ function(module, exports, __webpack_require__) { 265 | 266 | 'use strict'; 267 | 268 | Object.defineProperty(exports, "__esModule", { 269 | value: true 270 | }); 271 | exports.createGist = undefined; 272 | 273 | var _regenerator = __webpack_require__(2); 274 | 275 | var _regenerator2 = _interopRequireDefault(_regenerator); 276 | 277 | var _stringify = __webpack_require__(16); 278 | 279 | var _stringify2 = _interopRequireDefault(_stringify); 280 | 281 | var _asyncToGenerator2 = __webpack_require__(1); 282 | 283 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 284 | 285 | var createGist = exports.createGist = function () { 286 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(indexFile) { 287 | var body, response, json, htmlFile, rawUrl; 288 | return _regenerator2.default.wrap(function _callee$(_context) { 289 | while (1) { 290 | switch (_context.prev = _context.next) { 291 | case 0: 292 | body = { 293 | description: 'a lagom.js presentation', 294 | public: true, 295 | files: { 296 | 'lagom.html': { 297 | content: indexFile 298 | } 299 | } 300 | }; 301 | _context.next = 3; 302 | return (0, _nodeFetch2.default)(GIST_URL, { 303 | headers: { 304 | 'User-Agent': 'lagom.js' 305 | }, 306 | method: 'post', 307 | body: (0, _stringify2.default)(body) 308 | }); 309 | 310 | case 3: 311 | response = _context.sent; 312 | _context.next = 6; 313 | return (0, _fetchUtils.checkStatus)(response); 314 | 315 | case 6: 316 | _context.next = 8; 317 | return response.json(); 318 | 319 | case 8: 320 | json = _context.sent; 321 | htmlFile = json.files['lagom.html']; 322 | rawUrl = htmlFile.raw_url; 323 | return _context.abrupt('return', rawUrl); 324 | 325 | case 12: 326 | case 'end': 327 | return _context.stop(); 328 | } 329 | } 330 | }, _callee, this); 331 | })); 332 | 333 | return function createGist(_x) { 334 | return _ref.apply(this, arguments); 335 | }; 336 | }(); 337 | 338 | var _nodeFetch = __webpack_require__(7); 339 | 340 | var _nodeFetch2 = _interopRequireDefault(_nodeFetch); 341 | 342 | var _fetchUtils = __webpack_require__(4); 343 | 344 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 345 | 346 | var GIST_URL = 'https://api.github.com/gists'; 347 | 348 | /***/ }, 349 | /* 10 */ 350 | /***/ function(module, exports, __webpack_require__) { 351 | 352 | 'use strict'; 353 | 354 | Object.defineProperty(exports, "__esModule", { 355 | value: true 356 | }); 357 | exports.urlShortener = undefined; 358 | 359 | var _regenerator = __webpack_require__(2); 360 | 361 | var _regenerator2 = _interopRequireDefault(_regenerator); 362 | 363 | var _asyncToGenerator2 = __webpack_require__(1); 364 | 365 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 366 | 367 | var urlShortener = exports.urlShortener = function () { 368 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(gistUrl) { 369 | var form, response, shortUrl; 370 | return _regenerator2.default.wrap(function _callee$(_context) { 371 | while (1) { 372 | switch (_context.prev = _context.next) { 373 | case 0: 374 | form = new _formData2.default(); 375 | 376 | form.append('url', gistUrl); 377 | 378 | _context.next = 4; 379 | return (0, _nodeFetch2.default)(GIT_IO_URL, { method: 'post', body: form }); 380 | 381 | case 4: 382 | response = _context.sent; 383 | _context.next = 7; 384 | return (0, _fetchUtils.checkStatus)(response); 385 | 386 | case 7: 387 | _context.next = 9; 388 | return response.text(); 389 | 390 | case 9: 391 | shortUrl = _context.sent; 392 | return _context.abrupt('return', shortUrl); 393 | 394 | case 11: 395 | case 'end': 396 | return _context.stop(); 397 | } 398 | } 399 | }, _callee, this); 400 | })); 401 | 402 | return function urlShortener(_x) { 403 | return _ref.apply(this, arguments); 404 | }; 405 | }(); 406 | 407 | var _nodeFetch = __webpack_require__(7); 408 | 409 | var _nodeFetch2 = _interopRequireDefault(_nodeFetch); 410 | 411 | var _formData = __webpack_require__(18); 412 | 413 | var _formData2 = _interopRequireDefault(_formData); 414 | 415 | var _fetchUtils = __webpack_require__(4); 416 | 417 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 418 | 419 | var GIT_IO_URL = 'https://git.io/create'; 420 | 421 | /***/ }, 422 | /* 11 */ 423 | /***/ function(module, exports, __webpack_require__) { 424 | 425 | 'use strict'; 426 | 427 | Object.defineProperty(exports, "__esModule", { 428 | value: true 429 | }); 430 | exports.create = undefined; 431 | 432 | var _regenerator = __webpack_require__(2); 433 | 434 | var _regenerator2 = _interopRequireDefault(_regenerator); 435 | 436 | var _asyncToGenerator2 = __webpack_require__(1); 437 | 438 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 439 | 440 | var _fsPromise = __webpack_require__(6); 441 | 442 | var _fsPromise2 = _interopRequireDefault(_fsPromise); 443 | 444 | var _askForInput = __webpack_require__(8); 445 | 446 | var _askForInput2 = _interopRequireDefault(_askForInput); 447 | 448 | var _chalk = __webpack_require__(3); 449 | 450 | var _chalk2 = _interopRequireDefault(_chalk); 451 | 452 | var _mustache = __webpack_require__(21); 453 | 454 | var _mustache2 = _interopRequireDefault(_mustache); 455 | 456 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 457 | 458 | //import askForSelection from './helpers/ask-for-selection' 459 | var starterLocation = __dirname + '/../starter'; 460 | 461 | var getInput = function () { 462 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() { 463 | var title, homepage, twitter, github; 464 | return _regenerator2.default.wrap(function _callee$(_context) { 465 | while (1) { 466 | switch (_context.prev = _context.next) { 467 | case 0: 468 | _context.next = 2; 469 | return (0, _askForInput2.default)({ question: '◩ title: ' }); 470 | 471 | case 2: 472 | title = _context.sent; 473 | _context.next = 5; 474 | return (0, _askForInput2.default)({ question: '◩ your www: ' }); 475 | 476 | case 5: 477 | homepage = _context.sent; 478 | _context.next = 8; 479 | return (0, _askForInput2.default)({ question: '◩ twitter: ' }); 480 | 481 | case 8: 482 | twitter = _context.sent; 483 | _context.next = 11; 484 | return (0, _askForInput2.default)({ question: '◩ github: ' }); 485 | 486 | case 11: 487 | github = _context.sent; 488 | return _context.abrupt('return', { 489 | title: title, 490 | homepage: homepage, 491 | twitter: twitter, 492 | github: github 493 | }); 494 | 495 | case 13: 496 | case 'end': 497 | return _context.stop(); 498 | } 499 | } 500 | }, _callee, undefined); 501 | })); 502 | 503 | return function getInput() { 504 | return _ref.apply(this, arguments); 505 | }; 506 | }(); 507 | 508 | var checkIfFolderExists = function () { 509 | var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(folderName) { 510 | return _regenerator2.default.wrap(function _callee2$(_context2) { 511 | while (1) { 512 | switch (_context2.prev = _context2.next) { 513 | case 0: 514 | return _context2.abrupt('return', _fsPromise2.default.exists('./' + folderName)); 515 | 516 | case 1: 517 | case 'end': 518 | return _context2.stop(); 519 | } 520 | } 521 | }, _callee2, undefined); 522 | })); 523 | 524 | return function checkIfFolderExists(_x) { 525 | return _ref2.apply(this, arguments); 526 | }; 527 | }(); 528 | 529 | var moveStarterToFolder = function () { 530 | var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(folderName) { 531 | return _regenerator2.default.wrap(function _callee3$(_context3) { 532 | while (1) { 533 | switch (_context3.prev = _context3.next) { 534 | case 0: 535 | return _context3.abrupt('return', _fsPromise2.default.copy(starterLocation, './' + folderName)); 536 | 537 | case 1: 538 | case 'end': 539 | return _context3.stop(); 540 | } 541 | } 542 | }, _callee3, undefined); 543 | })); 544 | 545 | return function moveStarterToFolder(_x2) { 546 | return _ref3.apply(this, arguments); 547 | }; 548 | }(); 549 | 550 | var generateIndex = function () { 551 | var _ref4 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee4(folderName, title, homepage, twitter, github) { 552 | var indexLocation, template, rendered; 553 | return _regenerator2.default.wrap(function _callee4$(_context4) { 554 | while (1) { 555 | switch (_context4.prev = _context4.next) { 556 | case 0: 557 | indexLocation = './' + folderName + '/index.html'; 558 | _context4.next = 3; 559 | return _fsPromise2.default.readFile('./' + folderName + '/index.html', 'utf8'); 560 | 561 | case 3: 562 | template = _context4.sent; 563 | rendered = _mustache2.default.render(template, { 564 | title: title, 565 | homepage: homepage, 566 | twitter: twitter, 567 | github: github 568 | }); 569 | _context4.next = 7; 570 | return _fsPromise2.default.outputFile(indexLocation, rendered); 571 | 572 | case 7: 573 | return _context4.abrupt('return', _context4.sent); 574 | 575 | case 8: 576 | case 'end': 577 | return _context4.stop(); 578 | } 579 | } 580 | }, _callee4, undefined); 581 | })); 582 | 583 | return function generateIndex(_x3, _x4, _x5, _x6, _x7) { 584 | return _ref4.apply(this, arguments); 585 | }; 586 | }(); 587 | 588 | var create = exports.create = function () { 589 | var _ref5 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee5() { 590 | var _ref6, title, homepage, twitter, github, folderName, folderExists; 591 | 592 | return _regenerator2.default.wrap(function _callee5$(_context5) { 593 | while (1) { 594 | switch (_context5.prev = _context5.next) { 595 | case 0: 596 | process.stdout.write(_chalk2.default.green('◩ lagom: a simplistic presentation generator\n')); 597 | 598 | _context5.next = 3; 599 | return getInput(); 600 | 601 | case 3: 602 | _ref6 = _context5.sent; 603 | title = _ref6.title; 604 | homepage = _ref6.homepage; 605 | twitter = _ref6.twitter; 606 | github = _ref6.github; 607 | folderName = title.replace(/\s+/g, '-'); 608 | _context5.prev = 9; 609 | _context5.next = 12; 610 | return checkIfFolderExists(folderName); 611 | 612 | case 12: 613 | folderExists = _context5.sent; 614 | 615 | if (!folderExists) { 616 | _context5.next = 15; 617 | break; 618 | } 619 | 620 | throw new Error('folder already exists.'); 621 | 622 | case 15: 623 | _context5.next = 17; 624 | return moveStarterToFolder(folderName); 625 | 626 | case 17: 627 | _context5.next = 19; 628 | return generateIndex(folderName, title, homepage, twitter, github); 629 | 630 | case 19: 631 | 632 | process.stdout.write(_chalk2.default.green('◩ presentation: ') + 'generated\n'); 633 | process.stdout.write(_chalk2.default.green('◩ type: ') + _chalk2.default.bold('cd ' + folderName + '; lagom server')); 634 | process.stdout.write(_chalk2.default.green(' to start\n')); 635 | _context5.next = 27; 636 | break; 637 | 638 | case 24: 639 | _context5.prev = 24; 640 | _context5.t0 = _context5['catch'](9); 641 | 642 | process.stdout.write(_chalk2.default.red('\u25E9 ' + _context5.t0 + '\n')); 643 | 644 | case 27: 645 | case 'end': 646 | return _context5.stop(); 647 | } 648 | } 649 | }, _callee5, undefined, [[9, 24]]); 650 | })); 651 | 652 | return function create() { 653 | return _ref5.apply(this, arguments); 654 | }; 655 | }(); 656 | 657 | /***/ }, 658 | /* 12 */ 659 | /***/ function(module, exports, __webpack_require__) { 660 | 661 | 'use strict'; 662 | 663 | Object.defineProperty(exports, "__esModule", { 664 | value: true 665 | }); 666 | exports.deploy = undefined; 667 | 668 | var _promise = __webpack_require__(5); 669 | 670 | var _promise2 = _interopRequireDefault(_promise); 671 | 672 | var _regenerator = __webpack_require__(2); 673 | 674 | var _regenerator2 = _interopRequireDefault(_regenerator); 675 | 676 | var _asyncToGenerator2 = __webpack_require__(1); 677 | 678 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); 679 | 680 | var _fsPromise = __webpack_require__(6); 681 | 682 | var _fsPromise2 = _interopRequireDefault(_fsPromise); 683 | 684 | var _createGist = __webpack_require__(9); 685 | 686 | var _urlShortener = __webpack_require__(10); 687 | 688 | var _chalk = __webpack_require__(3); 689 | 690 | var _chalk2 = _interopRequireDefault(_chalk); 691 | 692 | var _inliner = __webpack_require__(19); 693 | 694 | var _inliner2 = _interopRequireDefault(_inliner); 695 | 696 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 697 | 698 | var printStatus = function () { 699 | var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(status) { 700 | return _regenerator2.default.wrap(function _callee$(_context) { 701 | while (1) { 702 | switch (_context.prev = _context.next) { 703 | case 0: 704 | process.stdout.write('\u25E9 status: ' + status + '\n'); 705 | 706 | case 1: 707 | case 'end': 708 | return _context.stop(); 709 | } 710 | } 711 | }, _callee, undefined); 712 | })); 713 | 714 | return function printStatus(_x) { 715 | return _ref.apply(this, arguments); 716 | }; 717 | }(); 718 | 719 | var getInlinedFile = function () { 720 | var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(fileName) { 721 | var options; 722 | return _regenerator2.default.wrap(function _callee2$(_context2) { 723 | while (1) { 724 | switch (_context2.prev = _context2.next) { 725 | case 0: 726 | options = { 727 | 'images': false, 728 | 'compressJS': true, 729 | 'collapseWhitespace': false, 730 | 'compressCSS': true, 731 | 'preserveComments': true 732 | }; 733 | return _context2.abrupt('return', new _promise2.default(function (resolve, reject) { 734 | 735 | return new _inliner2.default(fileName, options, function (error, html) { 736 | if (error) reject(error);else resolve(html); 737 | }).on('progress', printStatus); 738 | })); 739 | 740 | case 2: 741 | case 'end': 742 | return _context2.stop(); 743 | } 744 | } 745 | }, _callee2, undefined); 746 | })); 747 | 748 | return function getInlinedFile(_x2) { 749 | return _ref2.apply(this, arguments); 750 | }; 751 | }(); 752 | 753 | var deploy = exports.deploy = function () { 754 | var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3() { 755 | var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'index.html'; 756 | var fileExists, inlinedHTML, rawGistURL, shortenedUrl, hash1, hash2; 757 | return _regenerator2.default.wrap(function _callee3$(_context3) { 758 | while (1) { 759 | switch (_context3.prev = _context3.next) { 760 | case 0: 761 | fileExists = void 0, inlinedHTML = void 0, rawGistURL = void 0, shortenedUrl = void 0; 762 | 763 | process.stdout.write(_chalk2.default.green('\u25E9 lagom: deploy\n')); 764 | 765 | _context3.prev = 2; 766 | _context3.next = 5; 767 | return _fsPromise2.default.exists('./' + fileName); 768 | 769 | case 5: 770 | fileExists = _context3.sent; 771 | 772 | if (fileExists) { 773 | _context3.next = 8; 774 | break; 775 | } 776 | 777 | throw new Error(fileName + ' doesn\'t exist'); 778 | 779 | case 8: 780 | _context3.next = 10; 781 | return getInlinedFile('./' + fileName); 782 | 783 | case 10: 784 | inlinedHTML = _context3.sent; 785 | 786 | 787 | printStatus('creating gist'); 788 | 789 | _context3.next = 14; 790 | return (0, _createGist.createGist)(inlinedHTML); 791 | 792 | case 14: 793 | rawGistURL = _context3.sent; 794 | 795 | 796 | printStatus('shortening url'); 797 | 798 | _context3.prev = 16; 799 | _context3.next = 19; 800 | return (0, _urlShortener.urlShortener)(rawGistURL); 801 | 802 | case 19: 803 | shortenedUrl = _context3.sent; 804 | 805 | process.stdout.write(_chalk2.default.green('\u25E9 deployed: http://lagom.hook.io/?c=' + shortenedUrl + '\n')); 806 | _context3.next = 29; 807 | break; 808 | 809 | case 23: 810 | _context3.prev = 23; 811 | _context3.t0 = _context3['catch'](16); 812 | hash1 = rawGistURL.split('/')[4]; 813 | hash2 = rawGistURL.split('/')[6]; 814 | 815 | 816 | process.stdout.write(_chalk2.default.red('\u25E9 error: couldn\'t shorten url, fallbacking to regular full url.\n')); 817 | process.stdout.write(_chalk2.default.green('\u25E9 deployed: http://lagom.hook.io/?h1=' + hash1 + '&h2=' + hash2 + '\n')); 818 | 819 | case 29: 820 | _context3.next = 34; 821 | break; 822 | 823 | case 31: 824 | _context3.prev = 31; 825 | _context3.t1 = _context3['catch'](2); 826 | 827 | process.stdout.write(_chalk2.default.red('\u25E9 error: ' + _context3.t1.message + '\n')); 828 | 829 | case 34: 830 | case 'end': 831 | return _context3.stop(); 832 | } 833 | } 834 | }, _callee3, undefined, [[2, 31], [16, 23]]); 835 | })); 836 | 837 | return function deploy(_x3) { 838 | return _ref3.apply(this, arguments); 839 | }; 840 | }(); 841 | 842 | /***/ }, 843 | /* 13 */ 844 | /***/ function(module, exports, __webpack_require__) { 845 | 846 | 'use strict'; 847 | 848 | Object.defineProperty(exports, "__esModule", { 849 | value: true 850 | }); 851 | exports.help = undefined; 852 | 853 | var _chalk = __webpack_require__(3); 854 | 855 | var _chalk2 = _interopRequireDefault(_chalk); 856 | 857 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 858 | 859 | var help = exports.help = function help() { 860 | process.stdout.write(_chalk2.default.green('lagom create create a new presentation\n')); 861 | process.stdout.write(_chalk2.default.green('lagom server start live-reloading server\n')); 862 | process.stdout.write(_chalk2.default.green('lagom deploy deploy presentation to a gist \n')); 863 | process.stdout.write(_chalk2.default.green('lagom help show this help\n')); 864 | }; 865 | 866 | /***/ }, 867 | /* 14 */ 868 | /***/ function(module, exports, __webpack_require__) { 869 | 870 | "use strict"; 871 | 872 | Object.defineProperty(exports, "__esModule", { 873 | value: true 874 | }); 875 | exports.server = undefined; 876 | 877 | var _chalk = __webpack_require__(3); 878 | 879 | var _chalk2 = _interopRequireDefault(_chalk); 880 | 881 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 882 | 883 | var liveServer = __webpack_require__(20); 884 | 885 | var params = { 886 | port: 3000, 887 | file: "index.html", // When set, serve this file for every 404 (useful for single-page applications) 888 | logLevel: 0 }; 889 | 890 | var server = exports.server = function server() { 891 | process.stdout.write(_chalk2.default.green('◩ lagom-server is running')); 892 | liveServer.start(params); 893 | }; 894 | 895 | /***/ }, 896 | /* 15 */ 897 | /***/ function(module, exports) { 898 | 899 | module.exports = require("ansi-escapes"); 900 | 901 | /***/ }, 902 | /* 16 */ 903 | /***/ function(module, exports) { 904 | 905 | module.exports = require("babel-runtime/core-js/json/stringify"); 906 | 907 | /***/ }, 908 | /* 17 */ 909 | /***/ function(module, exports) { 910 | 911 | module.exports = require("babel-runtime/core-js/set"); 912 | 913 | /***/ }, 914 | /* 18 */ 915 | /***/ function(module, exports) { 916 | 917 | module.exports = require("form-data"); 918 | 919 | /***/ }, 920 | /* 19 */ 921 | /***/ function(module, exports) { 922 | 923 | module.exports = require("inliner"); 924 | 925 | /***/ }, 926 | /* 20 */ 927 | /***/ function(module, exports) { 928 | 929 | module.exports = require("live-server"); 930 | 931 | /***/ }, 932 | /* 21 */ 933 | /***/ function(module, exports) { 934 | 935 | module.exports = require("mustache"); 936 | 937 | /***/ } 938 | /******/ ]); --------------------------------------------------------------------------------