├── .gitignore ├── LICENSE ├── README.md ├── lib ├── blotter.js ├── engine.js └── index.js ├── package-lock.json ├── package.json ├── template └── index.ejs ├── test ├── example.ink ├── example.ink.json └── style │ └── style.less ├── webpack.config.js └── webpack.config.module.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test/build 3 | test/style/style.css 4 | build/ 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Bruno Dias 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blotter 2 | 3 | Blotter is a a front-end engine for publishing [Ink](https://github.com/inkle/ink) stories on the web. It uses [inkjs](https://github.com/y-lohse/inkjs) as its core Ink engine and sole dependency for a pure JavaScript implementation of a simple user interface. 4 | 5 | Currently, Blotter is a proof-of-concept project. See [gall](http://github.com/sequitur/gall) for a turnkey way of using Blotter in a project. 6 | 7 | ## Usage 8 | 9 | ### As a standalone js file 10 | 11 | Use Gall. This information is provided mostly for documentation purposes. 12 | 13 | If not using Gall, get the bundled Blotter file from the repository or npm and inline or include it at the end of your html page's body. The page should contain the following structure in its body: 14 | 15 | - body 16 | - div#content-container 17 | - div#story-stage 18 | - div#choices 19 | 20 | You will also need a CSS that at the very least applies certain transitions and animations to content elements, since Blotter uses CSS animations to time itself when inserting content into the page. See the Gall scaffold for a Less file with examples of how this should work. 21 | 22 | The other thing you need is to inline the compiled json from your ink story, output by inklecate, into the head of the html file. You need a ` 9 | 12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |
20 | 21 | 22 | 23 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/example.ink: -------------------------------------------------------------------------------- 1 | Blotter Game Example #

2 | This is a simple example game written with Ink and compiled using __Inkle__'s own Inky IDE. 3 | * [Continue] 4 | -> choices 5 | = choices 6 | * [About Ink] 7 | About Ink #

8 | _Ink_ is an open source scripting language for writing interactive narratives, developed originally by Inkle. 9 | -> choices 10 | * [About Inkjs] 11 | About Inkjs #

12 | _Inkjs_ is an isomorphic javascript port of Ink, for both Node and the browser. 13 | -> choices 14 | * [About Blotter] 15 | About Blotter #

16 | _Blotter_ is a frontend engine for Inkjs meant to run on the web or within hybrid platforms like Electron and Cordova. It uses inkjs as its core game engine, and is otherwise a dependencyless implementation of a front-end interface for Ink stories. 17 | It includes some basic formatting features, including _emphasis_, __strong__, 'smart' "quotes", and dashes - both en and -- em. 18 | -> choices 19 | * [Test Tags] 20 | About Tags #

21 | Blotter supports _tags,_ as per the Ink feature, both as markers for elements (like the _h2_ element above) and as markers of class (like this red paragraph). # .red 22 | Of course, you can mix and match tags freely, like this red italic line. # .red # .italic 23 | Or this red title. # .red #

24 | -> choices 25 | * [Test Scrolling] 26 | Scrolling Test #

27 | This is a longer passage of text ot test scrolling functionality. 28 | Integer ut augue sed a bibendum commodo sociis a in tellus parturient urna vestibulum scelerisque condimentum a cras fringilla dolor nostra dictum id suspendisse arcu interdum. Donec diam nec feugiat facilisi ipsum conubia sit scelerisque suspendisse euismod a consectetur condimentum adipiscing lacus ullamcorper curae dui velit proin fringilla torquent imperdiet. Neque fermentum convallis taciti sociis odio a a nisl a a accumsan mi ut porttitor at scelerisque tristique fames ullamcorper dictumst eu parturient condimentum parturient. Adipiscing adipiscing a condimentum eu vestibulum luctus mi penatibus ante hac inceptos ornare ultrices magnis nunc a cras. 29 | 30 | Ullamcorper sed placerat diam varius tempus adipiscing vestibulum netus tristique a mi torquent ut potenti. Scelerisque nisi netus interdum a a suspendisse a et condimentum maecenas ullamcorper neque felis bibendum sagittis accumsan dignissim sed condimentum adipiscing nam condimentum ullamcorper facilisis. Id sodales consectetur parturient suspendisse felis eros eu blandit consectetur erat ut ridiculus faucibus a commodo mus a maecenas. Rhoncus suspendisse lorem sapien vestibulum consectetur donec eros facilisi nec dapibus parturient diam in velit a varius ad nisi scelerisque phasellus adipiscing leo sapien a ridiculus molestie. 31 | 32 | Dictumst lectus habitant purus curabitur magna nisl in vulputate adipiscing dignissim a egestas mi scelerisque vestibulum suspendisse dictumst a pretium a. Placerat tristique in tincidunt facilisi molestie lacus in adipiscing a cras parturient mattis primis quam curae integer et libero amet. A praesent et parturient himenaeos a porttitor mi diam porta mus fermentum amet dignissim volutpat. 33 | 34 | Egestas praesent arcu a taciti eget gravida condimentum elit pulvinar himenaeos ullamcorper condimentum ultricies lorem parturient a a lobortis integer odio magna velit. Euismod penatibus torquent ullamcorper quis neque convallis a nunc magnis aenean elit a parturient laoreet a feugiat est parturient pretium hendrerit enim a a ante elit curabitur adipiscing a. Quam eu scelerisque litora gravida venenatis faucibus a urna vestibulum commodo condimentum convallis nisl condimentum orci consectetur adipiscing aenean suspendisse ut cras augue primis posuere a. Bibendum vestibulum parturient faucibus urna nec a vestibulum urna parturient vestibulum adipiscing nibh aliquet in parturient consectetur felis suspendisse. 35 | 36 | Sed imperdiet hac neque eu nisl donec parturient lectus ullamcorper turpis semper ut a odio varius nunc mollis vestibulum ad viverra bibendum nec ut. A augue senectus facilisis tincidunt adipiscing vivamus at a ullamcorper class mattis tempor dictumst scelerisque a id vestibulum vitae a bibendum. Condimentum molestie morbi id parturient ac bibendum donec risus parturient habitasse natoque nec auctor urna blandit hac volutpat parturient lobortis. A suspendisse penatibus id est adipiscing convallis cum suspendisse torquent a ut parturient sociis id adipiscing non ut ullamcorper sem parturient ad neque lobortis nostra sem. 37 | 38 | A a diam inceptos a a blandit pharetra tristique integer pulvinar hac molestie vulputate ullamcorper sit mauris quam a a ultrices. Leo conubia suspendisse magna tellus tincidunt adipiscing aenean rhoncus a eget a id ullamcorper a ullamcorper fermentum ac accumsan molestie praesent suspendisse vestibulum a montes nisi cras. Ac platea dolor urna orci ac vivamus inceptos a condimentum per vulputate arcu malesuada vestibulum a parturient nam sociis nullam vestibulum dignissim a consectetur. Penatibus magnis id euismod duis porttitor suspendisse lacus etiam etiam parturient porta a a rhoncus nascetur platea ad adipiscing scelerisque. Parturient facilisis scelerisque ut risus a blandit iaculis platea non montes a ullamcorper consectetur fusce pretium consectetur dapibus parturient. Parturient aenean parturient porttitor adipiscing egestas litora augue est consectetur amet a congue laoreet laoreet scelerisque class parturient lacinia vulputate. 39 | -> choices 40 | * -> ending 41 | = ending 42 | This concludes the Blotter test. 43 | -> END 44 | -------------------------------------------------------------------------------- /test/example.ink.json: -------------------------------------------------------------------------------- 1 | {"inkVersion":17,"root":["^Blotter Game Example ",{"#":"

"},"\n","^This is a simple example game written with Ink and compiled using __Inkle__'s own Inky IDE.","\n",["ev","str","^Continue","/str","/ev",{"*":"5.c","flg":20},{"c":["\n","\n",{"->":"choices"},{"#f":5}]}],"done",{"choices":[["ev","str","^About Ink","/str","/ev",{"*":".^.c","flg":20},{"c":["\n","\n","^About Ink ",{"#":"

"},"\n","^_Ink_ is an open source scripting language for writing interactive narratives, developed originally by Inkle.","\n",{"->":".^.^.^"},{"#f":5}]}],["ev","str","^About Inkjs","/str","/ev",{"*":".^.c","flg":20},{"c":["\n","\n","^About Inkjs ",{"#":"

"},"\n","^_Inkjs_ is an isomorphic javascript port of Ink, for both Node and the browser.","\n",{"->":".^.^.^"},{"#f":5}]}],["ev","str","^About Blotter","/str","/ev",{"*":".^.c","flg":20},{"c":["\n","\n","^About Blotter ",{"#":"

"},"\n","^_Blotter_ is a frontend engine for Inkjs meant to run on the web or within hybrid platforms like Electron and Cordova. It uses inkjs as its core game engine, and is otherwise a dependencyless implementation of a front-end interface for Ink stories.","\n","^It includes some basic formatting features, including _emphasis_, __strong__, 'smart' \"quotes\", and dashes - both en and -- em.","\n",{"->":".^.^.^"},{"#f":5}]}],["ev","str","^Test Tags","/str","/ev",{"*":".^.c","flg":20},{"c":["\n","\n","^About Tags ",{"#":"

"},"\n","^Blotter supports _tags,_ as per the Ink feature, both as markers for elements (like the _h2_ element above) and as markers of class (like this red paragraph). ",{"#":".red"},"\n","^Of course, you can mix and match tags freely, like this red italic line. ",{"#":".red"},{"#":".italic"},"\n","^Or this red title. ",{"#":".red"},{"#":"

"},"\n",{"->":".^.^.^"},{"#f":5}]}],["ev","str","^Test Scrolling","/str","/ev",{"*":".^.c","flg":20},{"c":["\n","\n","^Scrolling Test ",{"#":"

"},"\n","^This is a longer passage of text ot test scrolling functionality.","\n","^Integer ut augue sed a bibendum commodo sociis a in tellus parturient urna vestibulum scelerisque condimentum a cras fringilla dolor nostra dictum id suspendisse arcu interdum. Donec diam nec feugiat facilisi ipsum conubia sit scelerisque suspendisse euismod a consectetur condimentum adipiscing lacus ullamcorper curae dui velit proin fringilla torquent imperdiet. Neque fermentum convallis taciti sociis odio a a nisl a a accumsan mi ut porttitor at scelerisque tristique fames ullamcorper dictumst eu parturient condimentum parturient. Adipiscing adipiscing a condimentum eu vestibulum luctus mi penatibus ante hac inceptos ornare ultrices magnis nunc a cras.","\n","^Ullamcorper sed placerat diam varius tempus adipiscing vestibulum netus tristique a mi torquent ut potenti. Scelerisque nisi netus interdum a a suspendisse a et condimentum maecenas ullamcorper neque felis bibendum sagittis accumsan dignissim sed condimentum adipiscing nam condimentum ullamcorper facilisis. Id sodales consectetur parturient suspendisse felis eros eu blandit consectetur erat ut ridiculus faucibus a commodo mus a maecenas. Rhoncus suspendisse lorem sapien vestibulum consectetur donec eros facilisi nec dapibus parturient diam in velit a varius ad nisi scelerisque phasellus adipiscing leo sapien a ridiculus molestie.","\n","^Dictumst lectus habitant purus curabitur magna nisl in vulputate adipiscing dignissim a egestas mi scelerisque vestibulum suspendisse dictumst a pretium a. Placerat tristique in tincidunt facilisi molestie lacus in adipiscing a cras parturient mattis primis quam curae integer et libero amet. A praesent et parturient himenaeos a porttitor mi diam porta mus fermentum amet dignissim volutpat.","\n","^Egestas praesent arcu a taciti eget gravida condimentum elit pulvinar himenaeos ullamcorper condimentum ultricies lorem parturient a a lobortis integer odio magna velit. Euismod penatibus torquent ullamcorper quis neque convallis a nunc magnis aenean elit a parturient laoreet a feugiat est parturient pretium hendrerit enim a a ante elit curabitur adipiscing a. Quam eu scelerisque litora gravida venenatis faucibus a urna vestibulum commodo condimentum convallis nisl condimentum orci consectetur adipiscing aenean suspendisse ut cras augue primis posuere a. Bibendum vestibulum parturient faucibus urna nec a vestibulum urna parturient vestibulum adipiscing nibh aliquet in parturient consectetur felis suspendisse.","\n","^Sed imperdiet hac neque eu nisl donec parturient lectus ullamcorper turpis semper ut a odio varius nunc mollis vestibulum ad viverra bibendum nec ut. A augue senectus facilisis tincidunt adipiscing vivamus at a ullamcorper class mattis tempor dictumst scelerisque a id vestibulum vitae a bibendum. Condimentum molestie morbi id parturient ac bibendum donec risus parturient habitasse natoque nec auctor urna blandit hac volutpat parturient lobortis. A suspendisse penatibus id est adipiscing convallis cum suspendisse torquent a ut parturient sociis id adipiscing non ut ullamcorper sem parturient ad neque lobortis nostra sem.","\n","^A a diam inceptos a a blandit pharetra tristique integer pulvinar hac molestie vulputate ullamcorper sit mauris quam a a ultrices. Leo conubia suspendisse magna tellus tincidunt adipiscing aenean rhoncus a eget a id ullamcorper a ullamcorper fermentum ac accumsan molestie praesent suspendisse vestibulum a montes nisi cras. Ac platea dolor urna orci ac vivamus inceptos a condimentum per vulputate arcu malesuada vestibulum a parturient nam sociis nullam vestibulum dignissim a consectetur. Penatibus magnis id euismod duis porttitor suspendisse lacus etiam etiam parturient porta a a rhoncus nascetur platea ad adipiscing scelerisque. Parturient facilisis scelerisque ut risus a blandit iaculis platea non montes a ullamcorper consectetur fusce pretium consectetur dapibus parturient. Parturient aenean parturient porttitor adipiscing egestas litora augue est consectetur amet a congue laoreet laoreet scelerisque class parturient lacinia vulputate.","\n",{"->":".^.^.^"},{"#f":5}]}],[{"*":".^.c","flg":24},{"c":["\n",{"->":"ending"},"\n",{"#f":5}]}],{"#f":3}],"ending":["^This concludes the Blotter test.","\n","end",{"#f":3}],"#f":3}],"listDefs":{}} -------------------------------------------------------------------------------- /test/style/style.less: -------------------------------------------------------------------------------- 1 | @import 'https://fonts.googleapis.com/css?family=Cormorant+Garamond:400,400i'; 2 | 3 | body,html { 4 | font-family: 'Cormorant Garamond', serif; 5 | font-size: 22px; 6 | } 7 | 8 | @keyframes fadein { 9 | from { 10 | opacity: 0; 11 | } 12 | to { 13 | opacity: 1; 14 | } 15 | } 16 | 17 | #content-container { 18 | height: 95vh; 19 | max-width: 40rem; 20 | margin: auto; 21 | #story-stage { 22 | height: calc(100% - 3rem); 23 | margin: 0; 24 | padding: 0; 25 | overflow-y: auto; 26 | p,h1,h2,h3,h4,h5,h6 { 27 | animation: 1s fadein; 28 | } 29 | 30 | } 31 | 32 | #choices { 33 | height: 3rem; 34 | margin: 0; 35 | padding: 0; 36 | .choices { 37 | animation: .5s fadein; 38 | display: flex; 39 | flex-flow: row wrap; 40 | margin: 0; 41 | padding: 0; 42 | 43 | li { 44 | background: #ddc; 45 | height: 1.5rem; 46 | line-height: 1.5rem; 47 | display: block; 48 | list-style: none; 49 | margin: .1rem; 50 | font-size: 1.5rem; 51 | padding: .25rem; 52 | flex-grow: 1; 53 | text-align: center; 54 | cursor: pointer; 55 | 56 | &:hover { 57 | background: #ccd; 58 | } 59 | } 60 | 61 | &.old { 62 | opacity: 0; 63 | transition: opacity .5s; 64 | } 65 | } 66 | } 67 | } 68 | 69 | .red { 70 | color: red; 71 | } 72 | 73 | .italic { 74 | font-style: italic; 75 | } 76 | 77 | /* Hide scrollbars in webkit... */ 78 | ::-webkit-scrollbar { 79 | display: none; 80 | } 81 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | 3 | module.exports = { 4 | entry: { 5 | blotter: './lib/blotter.js', 6 | }, 7 | output: { 8 | path: './build', 9 | filename: '[name].js', 10 | publicPath: '/' 11 | }, 12 | loaders: [ 13 | { 14 | test: /\.js$/, 15 | exclude: /(node_modules|bower_components)/, 16 | loader: 'babel', // 'babel-loader' is also a valid name to reference 17 | query: { 18 | presets: ['es2015'] 19 | } 20 | } 21 | ], 22 | plugins: [ 23 | new HtmlWebpackPlugin({ 24 | template: 'template/index.ejs', 25 | inject: false 26 | }) 27 | ] 28 | }; 29 | -------------------------------------------------------------------------------- /webpack.config.module.js: -------------------------------------------------------------------------------- 1 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | 3 | module.exports = { 4 | entry: { 5 | index: './lib/index.js' 6 | }, 7 | output: { 8 | path: './build', 9 | filename: '[name].js', 10 | publicPath: '/', 11 | library: 'ink-blotter', 12 | libraryTarget: 'commonjs2' 13 | }, 14 | loaders: [ 15 | { 16 | test: /\.js$/, 17 | exclude: /(node_modules|bower_components)/, 18 | loader: 'babel', // 'babel-loader' is also a valid name to reference 19 | query: { 20 | presets: ['es2015'] 21 | } 22 | } 23 | ] 24 | }; 25 | --------------------------------------------------------------------------------