diff --git a/.editorconfig b/.editorconfig index b82ac3e..f5ebc44 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,4 +6,4 @@ insert_final_newline = false trim_trailing_whitespace = true charset = utf-8 indent_size = 4 -indent_style = tab +indent_style = tab \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..623f4db --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,90 @@ +{ + "rules": { + "dot-notation": [ + 2 + ], + "indent": [ + 2, + "tab", + { + "SwitchCase": 1, + "ObjectExpression": "first" + } + ], + "quotes": [ + 2, + "double" + ], + "linebreak-style": [ + 2, + "unix" + ], + "no-console": [ + 2, + { + "allow": ["warn", "error"] + } + ], + "no-eq-null":[ + 2 + ], + "no-eval":[ + 2 + ], + "no-implied-eval":[ + 2 + ], + "no-redeclare": [ + 2, + { + "builtinGlobals": true + } + ], + "one-var": [ + 2, + "never" + ], + "prefer-const":[ + 2 + ], + "semi": [ + 2, + "always" + ], + "keyword-spacing":[ + 2, + { + "before": true, + "after": true, + "overrides": { + "if": { + "before": false + }, + "for": { + "before": false + }, + "while": { + "before": false + } + } + } + ], + "space-before-blocks":[ + 2, + "always" + ], + "space-before-function-paren": [ + 2, + "always" + ], + "strict":[ + 2, + "global" + ] + }, + "env": { + "es6": true, + "browser": true + }, + "extends": "eslint:recommended" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index c39cc26..2357bf9 100755 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .thumbs .Thumbs .buildconfig +package-lock.json /node_modules /cache /src diff --git a/.htaccess b/.htaccess index 0724b0b..0010bd9 100755 --- a/.htaccess +++ b/.htaccess @@ -51,9 +51,6 @@ Deny from env=block_bad_bots php_value session.cookie_httponly true -# Prevent Iframe -Header set X-Frame-Options DENY - # Disable server signature ServerSignature Off diff --git a/.htmlhintrc b/.htmlhintrc new file mode 100644 index 0000000..f8e53ab --- /dev/null +++ b/.htmlhintrc @@ -0,0 +1,18 @@ +{ + "tagname-lowercase": true, + "attr-lowercase": true, + "attr-value-double-quotes": true, + "doctype-first": true, + "tag-pair": true, + "spec-char-escape": true, + "id-unique": true, + "src-not-empty": true, + "attr-no-duplication": true, + "tag-pair": true, + "tag-self-close": false, + "title-require": true, + "doctype-html5": true, + "inline-style-disabled": true, + "space-tab-mixed-disabled": "tab", + "alt-require": true +} \ No newline at end of file diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..35ebc7d --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,25 @@ +{ + "rules": { + "block-closing-brace-empty-line-before": "never", + "block-closing-brace-newline-after": "always", + "declaration-block-semicolon-newline-after": "always", + "block-opening-brace-space-before": "always", + "color-hex-case": "lower", + "color-named": "never", + "color-no-invalid-hex": true, + "function-comma-newline-after": "never-multi-line", + "function-comma-space-after": "always", + "no-duplicate-selectors": true, + "no-eol-whitespace": true, + "indentation": "tab", + "number-leading-zero": "always", + "property-no-unknown": [ true, { + "ignoreProperties": [ + "composes" + ] + }], + "selector-list-comma-newline-after": "always", + "unit-case": "lower", + "unit-whitelist": ["em", "rem", "s", "vmax", "vmin", "vh", "vw", "%", "px"] + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index 0da681e..30242e1 100755 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 - 2017 Diego Islas Ocampo +Copyright (c) 2015 - 2018 Diego Islas Ocampo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ce9f8c8..4b2a926 100755 --- a/README.md +++ b/README.md @@ -1,22 +1,67 @@ # Monogatari Built to bring Visual Novels to the modern web and take them to the next level, making it easy for anyone to create and distribute Visual Novels in a simple way so that anyone can enjoy them on pretty much anywhere, create games with features that no one has ever imagined... it is time for Visual Novels to Evolve. +Website: https://monogatari.io/ + +Demo: https://monogatari.io/demo/ + ## Features - Responsive out of the box -- Plays nice with electron for Desktop apps and phonegap for mobile apps +- Plays nice with Electron for Desktop apps and Cordova for mobile apps - Simple Syntax +- Progressive Web App Features allowing offline game play +- Allows you to use any kind of media supported by browsers +- Compatible with all major browsers +- Includes libraries for animations and particle effects +- Allows saving/loading games - Extensible, you just can't imagine how much! -Website: https://monogatari.io/ +## What do I need to get Started? +The first thing about Monogatari that you should probably know is that with it, your visual novel is a web page first and a game later. That means that Monogatari has been created specifically for the web, putting things like responsiveness (the fact that your game will adapt to any screen or device size) first. You don't necessarily need to think of your game this way as well, but you'll certainly take the most out of Monogatari if you do. + +### Set up your environment + +To develop in Monogatari you would need the same as to develop a webpage, you just need a text editor capable of editing HTML, Javascript and CSS, which means that pretty much any text editor should work, even Windows NotePad but to make it easier, you probably want one with code syntax highlighting. + +Some recommended (and free) ones include: + +* [Atom](https://atom.io/) +* [Brackets](http://brackets.io/) +* [Visual Studio Code](https://code.visualstudio.com) + +Take a look at them and pick the one you like the most and feel comfortable with, this will be your main tool from now on. + +Now, you can always open a website by just clicking the file (index.html) and opening it with your browser, however there are small aspects of Monogatari that work better when served through a web server. You don't need anything fancy for this, in fact there's a perfectly fine web server you can [download from the Chrome Store](https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb) + +As previously mentioned, the use of a web server is completely optional, you can just open your game with the browser as a file and it will run just fine, the web server will allow you to test features such as the Service Workers, needed for Monogatari's offline support and asset preloading. + +### Workflow + +Ok so now you have the environment set up, you have some idea on what the files you got are for so how can you start developing your game? + +1. Try the game first, open the index.html file inside the directory you just unzipped and play the sample game through. +2. Once you've played it once, open the directory (the one you unzipped) with the editor you chose to start making changes. +3. Open the script.js file with your editor, find the variable called ˋscriptˋ, as you'll see, all the dialogs you just saw are just a simple list in there. More information can be found in [the documentation](https://monogatari.io/documentation/script/text/). +4. Change one of the dialogs, save the file and reload the game (just like you reload a website). +5. Play it again and you'll see the dialog changed just like you made it. +6. Now try adding more dialog to it and you'll quickly get how things are done. +7. Once you've gotten yourself used to adding dialogs, [add a scene](https://monogatari.io/documentation/script/scenes/) as a challenge, that means you'll have to add your image file to the ˋimg/scenes/ directoryˋ, more instructions are on the link. + +If you manage to do all that, congratulations! You just made your first game and are probably more familiarized with the workflow you'll be using, just make changes, save, reload, try and repeat! ## Documentation -You can see the documentation in https://monogatari.io/documentation/ +You can take a look at the documentation in https://monogatari.io/documentation/ -You can also contribute to the documentation in the [Website repository](https://github.com/Hyuchia/MonogatariWebsite) +You can also contribute to it in the [Documentation repository](https://github.com/Monogatari/Documentation) -## Contributing -If you have contributed to this project, or in the webpage, please make sure you are listed in the contributors list of the website, you can add yourself in the [contributors file](https://github.com/Hyuchia/MonogatariWebsite/blob/master/templates/contributors.html) of the website +## Get in Touch +If you have any doubt, problem or just want some help please contact me, I'll be glad to help in any way I can. Even though Monogatari is simple enough and you can find many resources online, I know it can be hard to get started and sometimes the documentation is not clear enough, so really, contact me anytime! + +You can join the [Discord Server](https://discord.gg/gWSeDTz), send me an email, DM me at [Twitter](https://twitter.com/Hyuchia), and [Mastodon](https://mastodon.social/@HyuchiaDiego) as well. + +## Contributing +Contributions are always welcome! If you have contributed to this project, or in the website, please make sure you are listed in the contributors list of the website, you can add yourself in the [contributors file](https://github.com/Monogatari/Website/blob/master/templates/contributors.html) of the website ## License -Monogatari is a Free Open Source Software project released under the [MIT License](https://raw.githubusercontent.com/Hyuchia/Monogatari/master/LICENSE). \ No newline at end of file +Monogatari is a Free Open Source Software project released under the [MIT License](https://raw.githubusercontent.com/Monogatari/Monogatari/master/LICENSE). \ No newline at end of file diff --git a/electron.js b/electron.js index d9a278c..be1a125 100755 --- a/electron.js +++ b/electron.js @@ -1,15 +1,30 @@ -const {app, BrowserWindow} = require('electron'); -const path = require('path'); -const url = require('url'); +/** + * ======================================= + * Monogatari Electron Configuration + * ======================================= + **/ -// Keep a global reference of the window object, if you don't, the window will +"use strict"; + +/* global require */ +/* global process */ +/* global __dirname */ + +const {app, BrowserWindow} = require("electron"); +const path = require("path"); +const url = require("url"); + +// Keep a global reference of the window object, if you don"t, the window will // be closed automatically when the JavaScript object is garbage collected. let win; -function createWindow() { +function createWindow () { // Create the browser window. win = new BrowserWindow({ + // Title that will be shown in the window (Your game's title) + title: "", + // Set the minimal window size minWidth: 640, minHeight: 360, @@ -29,23 +44,22 @@ function createWindow() { // Full Screen options fullscrenable: true, - fullscreen: false, // Set an icon for the window - icon: __dirname + '/img/icons/icon_128x128.png' + icon: __dirname + "/img/icons/icon_128x128.png" }); // and load the index.html of the app. win.loadURL(url.format( { - pathname: path.join(__dirname, 'index.html'), - protocol: 'file:', + pathname: path.join(__dirname, "index.html"), + protocol: "file:", slashes: true } )); // Emitted when the window is closed. - win.on('closed', () => { + win.on("closed", () => { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. @@ -56,24 +70,24 @@ function createWindow() { // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. -app.on('ready', createWindow); +app.on("ready", createWindow); // Quit when all windows are closed. -app.on('window-all-closed', () => { +app.on("window-all-closed", () => { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin') { + if (process.platform !== "darwin") { app.quit(); } }); -app.on('activate', () => { - // On OS X it's common to re-create a window in the app when the +app.on("activate", () => { + // On OS X it"s common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (win === null) { createWindow(); } }); -// In this file you can include the rest of your app's specific main process +// In this file you can include the rest of your app"s specific main process // code. You can also put them in separate files and require them here. \ No newline at end of file diff --git a/error/400.html b/error/400.html index 8643d9d..5e217e8 100755 --- a/error/400.html +++ b/error/400.html @@ -4,39 +4,53 @@ Bad Request - - + +

Bad Request

-

The request is invalid.

+

The received request is invalid or malformed.

+
\ No newline at end of file diff --git a/error/401.html b/error/401.html index 608b8b9..4a76307 100755 --- a/error/401.html +++ b/error/401.html @@ -2,41 +2,55 @@ - Authentication Required - - + +

Authentication Required

-

Sorry, the content you are trying to access requires user's authentication.

+

Sorry, the content you are trying to access requires credentials authentication.

+
\ No newline at end of file diff --git a/error/403.html b/error/403.html index ec51fdc..fd1a4ad 100755 --- a/error/403.html +++ b/error/403.html @@ -1,47 +1,56 @@ - - Forbidden - - - + - -

Accessing Forbidden Content

-

Sorry, the content you are trying to access is forbidden.

- +
+

Accesing Forbidden Content

+

Sorry, the content you are trying to access is forbidden.

+
- \ No newline at end of file diff --git a/error/404.html b/error/404.html index 349fe59..fa6542e 100755 --- a/error/404.html +++ b/error/404.html @@ -1,47 +1,56 @@ - - - Page not Found - + Page Not Found - - + - -

Page not Found

-

Sorry, the page you are trying to access does not exist.

- +
+

Page Not Found

+

Sorry, the page you are trying to access does not exist.

+
- \ No newline at end of file diff --git a/error/405.html b/error/405.html new file mode 100644 index 0000000..3fc9e92 --- /dev/null +++ b/error/405.html @@ -0,0 +1,56 @@ + + + + + Method Not Allowed + + + + + + +
+

Method Not Allowed

+

The request method is not allowed for the requested resource.

+
+ + \ No newline at end of file diff --git a/error/408.html b/error/408.html new file mode 100644 index 0000000..f1dd63e --- /dev/null +++ b/error/408.html @@ -0,0 +1,56 @@ + + + + + Request Timeout + + + + + + +
+

Request Timeout

+

The server timed out waiting for the request.

+
+ + \ No newline at end of file diff --git a/error/429.html b/error/429.html new file mode 100644 index 0000000..4f5a8ff --- /dev/null +++ b/error/429.html @@ -0,0 +1,56 @@ + + + + + Too Many Requests + + + + + + +
+

Too Many Requests

+

Sorry, the user has sent too many requests in a given amount of time.

+
+ + \ No newline at end of file diff --git a/error/500.html b/error/500.html index 78d7e97..9103e72 100755 --- a/error/500.html +++ b/error/500.html @@ -1,47 +1,56 @@ - - Server Error - - - + - +

Server Error

-

Sorry, it seems there's been an error. Please try later.

- +

Sorry, it seems there's been an error. Please try later.

+
- \ No newline at end of file diff --git a/error/503.html b/error/503.html new file mode 100644 index 0000000..3d3bb73 --- /dev/null +++ b/error/503.html @@ -0,0 +1,56 @@ + + + + + Service Unavailable + + + + + + +
+

Service Unavailable

+

Sorry, the server is currently unavailable or under mantainance, try again later.

+
+ + \ No newline at end of file diff --git a/fonts/FontAwesome.otf b/fonts/FontAwesome.otf old mode 100755 new mode 100644 diff --git a/fonts/fontawesome-webfont.eot b/fonts/fontawesome-webfont.eot old mode 100755 new mode 100644 diff --git a/fonts/fontawesome-webfont.svg b/fonts/fontawesome-webfont.svg old mode 100755 new mode 100644 diff --git a/fonts/fontawesome-webfont.ttf b/fonts/fontawesome-webfont.ttf old mode 100755 new mode 100644 diff --git a/fonts/fontawesome-webfont.woff b/fonts/fontawesome-webfont.woff old mode 100755 new mode 100644 diff --git a/fonts/fontawesome-webfont.woff2 b/fonts/fontawesome-webfont.woff2 old mode 100755 new mode 100644 diff --git a/gulpfile.js b/gulpfile.js index 376cbbe..1228fbf 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,62 +1,73 @@ -const gulp = require('gulp'); -const prettify = require('gulp-jsbeautifier'); -const imagemin = require('gulp-imagemin'); -const packageJson = require('./package.json'); -const zip = require('gulp-zip'); -const cssnano = require('gulp-cssnano'); -const download = require("gulp-download-stream"); -const runSequence = require('run-sequence'); -gulp.task('default', () => { +/* global require */ + +"use strict"; + +const gulp = require("gulp"); +const prettify = require("gulp-jsbeautifier"); +const imagemin = require("gulp-imagemin"); +const packageJson = require("./package.json"); +const zip = require("gulp-zip"); +const cssnano = require("gulp-cssnano"); +const download = require("gulp-download-stream"); +const runSequence = require("run-sequence"); +const eslint = require("gulp-eslint"); +const stylelint = require("gulp-stylelint"); +const htmlhint = require("gulp-htmlhint"); +const concat = require("gulp-concat"); +const rename = require("gulp-rename"); +const closureCompiler = require("google-closure-compiler").gulp(); + +gulp.task("default", () => { // place code for your default task here }); -gulp.task('prettify', () => { - gulp.src(['./style/*.css', '!style/*.min.css']) +gulp.task("prettify", () => { + gulp.src(["./style/*.css", "!style/*.min.css"]) .pipe(prettify({ indent_level: 4, - indent_char: '\t', + indent_char: "\t", indent_size: 1 })) - .pipe(gulp.dest('./style/')); + .pipe(gulp.dest("./style/")); - gulp.src(['./*.html', './*.js']) + gulp.src(["./*.html", "./*.js"]) .pipe(prettify({ indent_level: 4, - indent_char: '\t', + indent_char: "\t", indent_size: 1 })) - .pipe(gulp.dest('./')) + .pipe(gulp.dest("./")); - gulp.src(['./js/*.js', '!js/*.min.js']) + gulp.src(["./js/*.js", "!js/*.min.js"]) .pipe(prettify({ indent_level: 4, - indent_char: '\t', + indent_char: "\t", indent_size: 1 })) - .pipe(gulp.dest('./js/')) + .pipe(gulp.dest("./js/")); }); -gulp.task('optimize', () => { - gulp.src(['./img/**/*.jpg', './img/**/*.jpeg', './img/**/*.png', './img/**/*.gif', './img/**/*.svg']) +gulp.task("optimize", () => { + gulp.src(["./img/**/*.jpg", "./img/**/*.jpeg", "./img/**/*.png", "./img/**/*.gif", "./img/**/*.svg"]) .pipe(imagemin()) - .pipe(gulp.dest(function(file) { + .pipe(gulp.dest(function (file) { return file.base; - })) + })); }); -gulp.task('release', () => { - return gulp.src(['./**', '!./**/.DS_Store', '!./**/.thumbs', '!./**/.gitignore', '!./**/.editorconfig', - '!./**/.buildconfig', '!.git/**', '!node_modules/**', '!build/**', '!.git', '!node_modules', '!build' - ], { - dot: true - }) - .pipe(zip('Monogatari-v' + packageJson.version + '.zip')) - .pipe(gulp.dest('dist')); +gulp.task("release", () => { + return gulp.src(["./**", "!./**/.DS_Store", "!./**/.thumbs", "!./**/.gitignore", "!./**/.editorconfig", + "!./**/.buildconfig", "!.git/**", "!node_modules/**", "!build/**", "!.git", "!node_modules", "!build" + ], { + dot: true + }) + .pipe(zip("Monogatari-v" + packageJson.version + ".zip")) + .pipe(gulp.dest("dist")); }); // Update Dependencies -gulp.task('download-deps', () => { +gulp.task("download-deps", () => { // Artemis JS download("https://raw.githubusercontent.com/AegisFramework/Artemis/master/dist/artemis.min.js").pipe(gulp.dest("js/")); @@ -73,16 +84,16 @@ gulp.task('download-deps', () => { // Animate CSS download({ file: "animate.min.css", - url: "https://raw.githubusercontent.com/daneden/animate.css/master/animate.css" + url: "https://raw.githubusercontent.com/daneden/animate.css/master/animate.min.css" }).pipe(gulp.dest("style/")); // CSS Shake - download("https://raw.githubusercontent.com/elrumordelaluz/csshake/master/dist/csshake.min.css").pipe(gulp.dest("style/")); + download("https://raw.githubusercontent.com/Monogatari/csshake/master/dist/csshake.min.css").pipe(gulp.dest("style/")); - // Normalize CSS + // Kayros download({ - file: "normalize.min.css", - url: "https://raw.githubusercontent.com/necolas/normalize.css/master/normalize.css" + file: "kayros.min.css", + url: "https://raw.githubusercontent.com/AegisFramework/Kayros/master/dist/kayros.min.css" }).pipe(gulp.dest("style/")); // Font Awesome @@ -116,17 +127,8 @@ gulp.task('download-deps', () => { download("https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/fonts/fontawesome-webfont.svg").pipe(gulp.dest("fonts/")); }); -gulp.task('minify-deps', () => { - gulp.src('style/animate.min.css') - .pipe(cssnano()) - .pipe(gulp.dest("style/")); - gulp.src('style/normalize.min.css') - .pipe(cssnano()) - .pipe(gulp.dest("style/")); -}); - -gulp.task('download-monogatari', () => { +gulp.task("download-monogatari", () => { // Monogatari CSS download("https://raw.githubusercontent.com/Hyuchia/Monogatari/master/style/monogatari.css").pipe(gulp.dest("style/")); @@ -135,6 +137,98 @@ gulp.task('download-monogatari', () => { download("https://raw.githubusercontent.com/Hyuchia/Monogatari/master/js/monogatari.js").pipe(gulp.dest("js/")); }); -gulp.task('update', () => { - runSequence(['download-deps', 'download-monogatari']); +gulp.task("update", () => { + runSequence(["download-deps", "download-monogatari"]); +}); + +gulp.task("lint:js", () => { + return gulp.src(["./js/*.js", "!js/*.min.js"]) + .pipe(eslint({ fix: true })) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}); + +gulp.task("lint:css", () => { + return gulp.src(["./style/*.css", "!style/*.min.css"]) + .pipe(stylelint({ + failAfterError: true, + reporters: [{ + formatter: "string", + console: true + }] + })); }); + +gulp.task("lint:html", () => { + return gulp.src("./*.html") + .pipe(htmlhint()) + .pipe(htmlhint.reporter()) + .pipe(htmlhint.failAfterError()); +}); + +gulp.task("lint", ["lint:js", "lint:css", "lint:html"]); + +gulp.task("package:js", () => { + return gulp.src([ + "js/pollyfill.min.js", + "js/jquery.min.js", + "js/particles.min.js", + "js/typed.min.js", + "js/artemis.min.js", + "js/strings.js", + "js/options.js", + "js/storage.js", + "js/script.js", + "js/monogatari.js", + "js/main.js" + ]) + .pipe(concat({ path: packageJson.name + ".js", stat: { mode: "0664" }, newLine: "\r\n"})) + .pipe(closureCompiler({ + compilation_level: "WHITESPACE_ONLY", + language_in: "ECMASCRIPT6_STRICT", + language_out: "ECMASCRIPT5_STRICT", + js_output_file: packageJson.name + ".min.js" + })) + .pipe(gulp.dest("build/")); +}); + +gulp.task("package:style", () => { + return gulp.src([ + "style/cssshake.min.css", + "style/animate.min.css", + "style/font-awesome.min.css", + "style/kayros.min.css", + "style/monogatari.css", + "style/main.css" + ]) + .pipe(concat({ path: packageJson.name + ".css", stat: { mode: "0664" }, newLine: "\r\n\r\n"})) + .pipe(cssnano({zindex: false})) + .pipe(rename({ extname: ".min.css" })) + .pipe(gulp.dest("build/")); +}); + +gulp.task("package:misc", () => { + return gulp.src([ + "./**", + "!./**/.DS_Store", + "!./**/.thumbs", + "!./**/.md", + "!./**/.gitignore", + "!./**/.editorconfig", + "!./**/.buildconfig", + "!.git/**", + "!node_modules/**", + "!build/**", + "!.git", + "!node_modules", + "!build", + "!style", + "!js", + "!build/**", + "!style/**", + "!js/**" + ]) + .pipe(gulp.dest("build/")); +}); + +gulp.task("package", ["package:js", "package:style", "package:misc"]); \ No newline at end of file diff --git a/index.html b/index.html index 6de58cb..f086576 100755 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ - + @@ -24,9 +24,9 @@ - + - + @@ -59,7 +59,7 @@ - + @@ -68,19 +68,21 @@ - + + + - + @@ -91,25 +93,49 @@