Merge pull request #326 from hackmdio/es6-integration

ES6 integration
This commit is contained in:
Max Wu 2017-01-21 14:31:41 +08:00 committed by GitHub
commit 6dfc186691
21 changed files with 864 additions and 933 deletions

8
.babelrc Normal file
View file

@ -0,0 +1,8 @@
{
"presets": [
"es2015"
],
"plugins": [
"transform-runtime"
]
}

View file

@ -16,7 +16,6 @@
], ],
"array-callback-return": "error", "array-callback-return": "error",
"arrow-body-style": "error", "arrow-body-style": "error",
"arrow-parens": "error",
"arrow-spacing": "error", "arrow-spacing": "error",
"block-scoped-var": "off", "block-scoped-var": "off",
"block-spacing": "error", "block-spacing": "error",
@ -123,7 +122,7 @@
"no-extend-native": "error", "no-extend-native": "error",
"no-extra-bind": "error", "no-extra-bind": "error",
"no-extra-label": "error", "no-extra-label": "error",
"no-extra-parens": "error", "no-extra-parens": "warn",
"no-floating-decimal": "error", "no-floating-decimal": "error",
"no-global-assign": "error", "no-global-assign": "error",
"no-implicit-coercion": "error", "no-implicit-coercion": "error",
@ -195,7 +194,7 @@
"no-unneeded-ternary": "error", "no-unneeded-ternary": "error",
"no-unsafe-negation": "error", "no-unsafe-negation": "error",
"no-unused-expressions": "error", "no-unused-expressions": "error",
"no-use-before-define": "error", "no-use-before-define": "warn",
"no-useless-call": "error", "no-useless-call": "error",
"no-useless-computed-key": "error", "no-useless-computed-key": "error",
"no-useless-concat": "error", "no-useless-concat": "error",

1
.gitignore vendored
View file

@ -18,7 +18,6 @@ backups/
# ignore config files # ignore config files
config.json config.json
public/js/config.js
.sequelizerc .sequelizerc
# ignore webpack build # ignore webpack build

View file

@ -59,7 +59,7 @@ Get started
2. Enter the directory and type `bin/setup`, which will install npm dependencies and create configs. The setup script is written in Bash, you would need bash as a prerequisite. 2. Enter the directory and type `bin/setup`, which will install npm dependencies and create configs. The setup script is written in Bash, you would need bash as a prerequisite.
3. Setup the configs, see more below 3. Setup the configs, see more below
4. Setup environment variables which will overwrite the configs 4. Setup environment variables which will overwrite the configs
5. Build front-end bundle by `npm run build:prod` (use `npm run build:dev` if you are in development) 5. Build front-end bundle by `npm run build` (use `npm run dev` if you are in development)
6. Run the server as you like (node, forever, pm2) 6. Run the server as you like (node, forever, pm2)
Upgrade guide Upgrade guide
@ -70,7 +70,7 @@ If you are upgrading HackMD from an older version, follow these steps:
1. Fully stop your old server first (important) 1. Fully stop your old server first (important)
2. `git pull` or do whatever that updates the files 2. `git pull` or do whatever that updates the files
3. `npm install` to update dependencies 3. `npm install` to update dependencies
4. Build front-end bundle by `npm run build:prod` (use `npm run build:dev` if you are in development) 4. Build front-end bundle by `npm run build` (use `npm run dev` if you are in development)
5. Modify the file named `.sequelizerc`, change the value of the variable `url` with your db connection string 5. Modify the file named `.sequelizerc`, change the value of the variable `url` with your db connection string
For example: `postgres://username:password@localhost:5432/hackmd` For example: `postgres://username:password@localhost:5432/hackmd`
6. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema 6. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema
@ -97,19 +97,9 @@ Configuration files
There are some configs you need to change in the files below There are some configs you need to change in the files below
``` ```
./config.json --- for server settings ./config.json ----application settings
./public/js/config.js --- for client settings
``` ```
Client settings `config.js`
---
| variables | example values | description |
| --------- | ------ | ----------- |
| debug | `true` or `false` | set debug mode, show more logs |
| domain | `localhost` | domain name |
| urlpath | `hackmd` | sub url path, like: `www.example.com/<urlpath>` |
Environment variables (will overwrite other server configs) Environment variables (will overwrite other server configs)
--- ---
@ -158,7 +148,7 @@ Environment variables (will overwrite other server configs)
| HMD_S3_REGION | `ap-northeast-1` | AWS S3 region | | HMD_S3_REGION | `ap-northeast-1` | AWS S3 region |
| HMD_S3_BUCKET | no example | AWS S3 bucket name | | HMD_S3_BUCKET | no example | AWS S3 bucket name |
Server settings `config.json` Application settings `config.json`
--- ---
| variables | example values | description | | variables | example values | description |
@ -207,7 +197,7 @@ Third-party integration api key settings
| ------- | --------- | ----------- | | ------- | --------- | ----------- |
| facebook, twitter, github, gitlab, dropbox, google, ldap | environment variables or `config.json` | for signin | | facebook, twitter, github, gitlab, dropbox, google, ldap | environment variables or `config.json` | for signin |
| imgur | environment variables or `config.json` | for image upload | | imgur | environment variables or `config.json` | for image upload |
| google drive, dropbox | `public/js/config.js` | for export and import | | google drive(`google/apiKey`, `google/clientID`), dropbox(`dropbox/appKey`) | `config.json` | for export and import |
Third-party integration oauth callback urls Third-party integration oauth callback urls
--- ---

View file

@ -28,8 +28,6 @@ EOF
EOF EOF
cp public/js/config.js.example public/js/config.js
# build app # build app
npm run build:prod npm run build
fi fi

View file

@ -21,10 +21,6 @@ if [ ! -f config.json ]; then
cp config.json.example config.json cp config.json.example config.json
fi fi
if [ ! -f publis/js/config.js ]; then
cp public/js/config.js.example public/js/config.js
fi
if [ ! -f .sequelizerc ]; then if [ ! -f .sequelizerc ]; then
cp .sequelizerc.example .sequelizerc cp .sequelizerc.example .sequelizerc
fi fi

View file

@ -45,11 +45,13 @@
}, },
"dropbox": { "dropbox": {
"clientID": "change this", "clientID": "change this",
"clientSecret": "change this" "clientSecret": "change this",
"appKey": "change this"
}, },
"google": { "google": {
"clientID": "change this", "clientID": "change this",
"clientSecret": "change this" "clientSecret": "change this",
"apiKey": "change this"
}, },
"ldap": { "ldap": {
"url": "ldap://change_this", "url": "ldap://change_this",

View file

@ -90,11 +90,11 @@ var gitlab = (process.env.HMD_GITLAB_CLIENTID && process.env.HMD_GITLAB_CLIENTSE
var dropbox = (process.env.HMD_DROPBOX_CLIENTID && process.env.HMD_DROPBOX_CLIENTSECRET) ? { var dropbox = (process.env.HMD_DROPBOX_CLIENTID && process.env.HMD_DROPBOX_CLIENTSECRET) ? {
clientID: process.env.HMD_DROPBOX_CLIENTID, clientID: process.env.HMD_DROPBOX_CLIENTID,
clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET
} : config.dropbox || false; } : (config.dropbox && config.dropbox.clientID && config.dropbox.clientSecret && config.dropbox) || false;
var google = (process.env.HMD_GOOGLE_CLIENTID && process.env.HMD_GOOGLE_CLIENTSECRET) ? { var google = (process.env.HMD_GOOGLE_CLIENTID && process.env.HMD_GOOGLE_CLIENTSECRET) ? {
clientID: process.env.HMD_GOOGLE_CLIENTID, clientID: process.env.HMD_GOOGLE_CLIENTID,
clientSecret: process.env.HMD_GOOGLE_CLIENTSECRET clientSecret: process.env.HMD_GOOGLE_CLIENTSECRET
} : config.google || false; } : (config.google && config.google.clientID && config.google.clientSecret && config.google) || false;
var ldap = config.ldap || ( var ldap = config.ldap || (
process.env.HMD_LDAP_URL || process.env.HMD_LDAP_URL ||
process.env.HMD_LDAP_BINDDN || process.env.HMD_LDAP_BINDDN ||

View file

@ -5,8 +5,8 @@
"main": "app.js", "main": "app.js",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"build:dev": "webpack --config webpack.config.js --progress --colors --watch", "dev": "webpack --config webpack.config.js --progress --colors --watch",
"build:prod": "webpack --config webpack.production.js --progress --colors", "build": "webpack --config webpack.production.js --progress --colors",
"postinstall": "bin/heroku", "postinstall": "bin/heroku",
"start": "node app.js" "start": "node app.js"
}, },
@ -140,6 +140,12 @@
"url": "https://github.com/hackmdio/hackmd.git" "url": "https://github.com/hackmdio/hackmd.git"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.18.0",
"babel-runtime": "^6.20.0",
"copy-webpack-plugin": "^4.0.1", "copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.26.1", "css-loader": "^0.26.1",
"ejs-loader": "^0.3.0", "ejs-loader": "^0.3.0",

View file

@ -1,118 +0,0 @@
var config = require('./config');
var domain = config.domain; // domain name
var urlpath = config.urlpath; // sub url path, like: www.example.com/<urlpath>
var debug = config.debug;
var GOOGLE_API_KEY = config.GOOGLE_API_KEY;
var GOOGLE_CLIENT_ID = config.GOOGLE_CLIENT_ID;
var DROPBOX_APP_KEY = config.DROPBOX_APP_KEY;
//common
var port = window.location.port;
window.serverurl = window.location.protocol + '//' + (domain ? domain : window.location.hostname) + (port ? ':' + port : '') + (urlpath ? '/' + urlpath : '');
var noteid = urlpath ? window.location.pathname.slice(urlpath.length + 1, window.location.pathname.length).split('/')[1] : window.location.pathname.split('/')[1];
var noteurl = serverurl + '/' + noteid;
var version = '0.5.0';
var checkAuth = false;
var profile = null;
var lastLoginState = getLoginState();
var lastUserId = getUserId();
window.loginStateChangeEvent = null;
function resetCheckAuth() {
checkAuth = false;
}
function setLoginState(bool, id) {
Cookies.set('loginstate', bool, {
expires: 365
});
if (id) {
Cookies.set('userid', id, {
expires: 365
});
} else {
Cookies.remove('userid');
}
lastLoginState = bool;
lastUserId = id;
checkLoginStateChanged();
}
function checkLoginStateChanged() {
if (getLoginState() != lastLoginState || getUserId() != lastUserId) {
if(loginStateChangeEvent) setTimeout(loginStateChangeEvent, 100);
return true;
} else {
return false;
}
}
function getLoginState() {
var state = Cookies.get('loginstate');
return state === "true" || state === true;
}
function getUserId() {
return Cookies.get('userid');
}
function clearLoginState() {
Cookies.remove('loginstate');
}
function checkIfAuth(yesCallback, noCallback) {
var cookieLoginState = getLoginState();
if (checkLoginStateChanged()) checkAuth = false;
if (!checkAuth || typeof cookieLoginState == 'undefined') {
$.get(serverurl + '/me')
.done(function (data) {
if (data && data.status == 'ok') {
profile = data;
yesCallback(profile);
setLoginState(true, data.id);
} else {
noCallback();
setLoginState(false);
}
})
.fail(function () {
noCallback();
})
.always(function () {
checkAuth = true;
});
} else if (cookieLoginState) {
yesCallback(profile);
} else {
noCallback();
}
}
module.exports = {
domain: domain,
urlpath: urlpath,
debug: debug,
GOOGLE_API_KEY: GOOGLE_API_KEY,
GOOGLE_CLIENT_ID: GOOGLE_CLIENT_ID,
DROPBOX_APP_KEY: DROPBOX_APP_KEY,
port: port,
noteid: noteid,
noteurl: noteurl,
version: version,
checkAuth: checkAuth,
profile: profile,
lastLoginState: lastLoginState,
lastUserId: lastUserId,
/* export functions */
resetCheckAuth: resetCheckAuth,
setLoginState: setLoginState,
checkLoginStateChanged: checkLoginStateChanged,
getLoginState: getLoginState,
getUserId: getUserId,
clearLoginState: clearLoginState,
checkIfAuth: checkIfAuth
};

View file

@ -1,11 +0,0 @@
module.exports = {
domain: '', // domain name
urlpath: '', // sub url path, like: www.example.com/<urlpath>
// settings
debug: false,
GOOGLE_API_KEY: '',
GOOGLE_CLIENT_ID: '',
DROPBOX_APP_KEY: ''
};

View file

@ -3,37 +3,39 @@ require('./locale');
require('../css/cover.css'); require('../css/cover.css');
require('../css/site.css'); require('../css/site.css');
var common = require('./common'); import {
var checkIfAuth = common.checkIfAuth; checkIfAuth,
var urlpath = common.urlpath; clearLoginState,
var resetCheckAuth = common.resetCheckAuth; getLoginState,
var getLoginState = common.getLoginState; resetCheckAuth,
var clearLoginState = common.clearLoginState; setloginStateChangeEvent
} from './lib/common/login';
var historyModule = require('./history'); import {
var parseStorageToHistory = historyModule.parseStorageToHistory; clearDuplicatedHistory,
var parseHistory = historyModule.parseHistory; deleteServerHistory,
var getStorageHistory = historyModule.getStorageHistory; getHistory,
var getHistory = historyModule.getHistory; getStorageHistory,
var saveHistory = historyModule.saveHistory; parseHistory,
var removeHistory = historyModule.removeHistory; parseServerToHistory,
var postHistoryToServer = historyModule.postHistoryToServer; parseStorageToHistory,
var deleteServerHistory = historyModule.deleteServerHistory; postHistoryToServer,
var parseServerToHistory = historyModule.parseServerToHistory; removeHistory,
var saveStorageHistoryToServer = historyModule.saveStorageHistoryToServer; saveHistory,
var clearDuplicatedHistory = historyModule.clearDuplicatedHistory; saveStorageHistoryToServer
} from './history';
var saveAs = require('file-saver').saveAs; import { saveAs } from 'file-saver';
var List = require('list.js'); import List from 'list.js';
var S = require('string'); import S from 'string';
var options = { const options = {
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'], valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
item: '<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">\ item: '<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">\
<span class="id" style="display:none;"></span>\ <span class="id" style="display:none;"></span>\
<a href="#">\ <a href="#">\
<div class="item">\ <div class="item">\
<div class="ui-history-pin fa fa-thumb-tack fa-fw"></div>\ <div class="ui-history-pin fa fa-thumb-tack fa-fw"></div>\
<div class="ui-history-close fa fa-close fa-fw" data-toggle="modal" data-target=".delete-modal"></div>\ <div class="ui-history-close fa fa-close fa-fw" data-toggle="modal" data-target=".delete-modal"></div>\
<div class="content">\ <div class="content">\
<h4 class="text"></h4>\ <h4 class="text"></h4>\
@ -55,15 +57,16 @@ var options = {
}) })
] ]
}; };
var historyList = new List('history', options); const historyList = new List('history', options);
migrateHistoryFromTempCallback = pageInit; migrateHistoryFromTempCallback = pageInit;
loginStateChangeEvent = pageInit; setloginStateChangeEvent(pageInit);
pageInit(); pageInit();
function pageInit() { function pageInit() {
checkIfAuth( checkIfAuth(
function (data) { data => {
$('.ui-signin').hide(); $('.ui-signin').hide();
$('.ui-or').hide(); $('.ui-or').hide();
$('.ui-welcome').show(); $('.ui-welcome').show();
@ -74,7 +77,7 @@ function pageInit() {
$(".ui-history").click(); $(".ui-history").click();
parseServerToHistory(historyList, parseHistoryCallback); parseServerToHistory(historyList, parseHistoryCallback);
}, },
function () { () => {
$('.ui-signin').show(); $('.ui-signin').show();
$('.ui-or').show(); $('.ui-or').show();
$('.ui-welcome').hide(); $('.ui-welcome').hide();
@ -103,7 +106,7 @@ $(".ui-home").click(function (e) {
} }
}); });
$(".ui-history").click(function (e) { $(".ui-history").click(() => {
if (!$("#history").is(':visible')) { if (!$("#history").is(':visible')) {
$(".section:visible").hide(); $(".section:visible").hide();
$("#history").fadeIn(); $("#history").fadeIn();
@ -118,7 +121,7 @@ function checkHistoryList() {
} else if ($("#history-list").children().length == 0) { } else if ($("#history-list").children().length == 0) {
$('.pagination').hide(); $('.pagination').hide();
$(".ui-nohistory").slideDown(); $(".ui-nohistory").slideDown();
getStorageHistory(function (data) { getStorageHistory(data => {
if (data && data.length > 0 && getLoginState() && historyList.items.length == 0) { if (data && data.length > 0 && getLoginState() && historyList.items.length == 0) {
$(".ui-import-from-browser").slideDown(); $(".ui-import-from-browser").slideDown();
} }
@ -128,35 +131,35 @@ function checkHistoryList() {
function parseHistoryCallback(list, notehistory) { function parseHistoryCallback(list, notehistory) {
checkHistoryList(); checkHistoryList();
//sort by pinned then timestamp //sort by pinned then timestamp
list.sort('', { list.sort('', {
sortFunction: function (a, b) { sortFunction(a, b) {
var notea = a.values(); const notea = a.values();
var noteb = b.values(); const noteb = b.values();
if (notea.pinned && !noteb.pinned) { if (notea.pinned && !noteb.pinned) {
return -1; return -1;
} else if (!notea.pinned && noteb.pinned) { } else if (!notea.pinned && noteb.pinned) {
return 1; return 1;
} else { } else {
if (notea.timestamp > noteb.timestamp) { if (notea.timestamp > noteb.timestamp) {
return -1; return -1;
} else if (notea.timestamp < noteb.timestamp) { } else if (notea.timestamp < noteb.timestamp) {
return 1; return 1;
} else { } else {
return 0; return 0;
} }
} }
} }
}); });
// parse filter tags // parse filter tags
var filtertags = []; const filtertags = [];
for (var i = 0, l = list.items.length; i < l; i++) { for (let i = 0, l = list.items.length; i < l; i++) {
var tags = list.items[i]._values.tags; const tags = list.items[i]._values.tags;
if (tags && tags.length > 0) { if (tags && tags.length > 0) {
for (var j = 0; j < tags.length; j++) { for (let j = 0; j < tags.length; j++) {
//push info filtertags if not found //push info filtertags if not found
var found = false; let found = false;
if (filtertags.indexOf(tags[j]) != -1) if (filtertags.includes(tags[j]))
found = true; found = true;
if (!found) if (!found)
filtertags.push(tags[j]); filtertags.push(tags[j]);
@ -167,17 +170,17 @@ function parseHistoryCallback(list, notehistory) {
} }
// update items whenever list updated // update items whenever list updated
historyList.on('updated', function (e) { historyList.on('updated', e => {
for (var i = 0, l = e.items.length; i < l; i++) { for (let i = 0, l = e.items.length; i < l; i++) {
var item = e.items[i]; const item = e.items[i];
if (item.visible()) { if (item.visible()) {
var itemEl = $(item.elm); const itemEl = $(item.elm);
var values = item._values; const values = item._values;
var a = itemEl.find("a"); const a = itemEl.find("a");
var pin = itemEl.find(".ui-history-pin"); const pin = itemEl.find(".ui-history-pin");
var tagsEl = itemEl.find(".tags"); const tagsEl = itemEl.find(".tags");
//parse link to element a //parse link to element a
a.attr('href', serverurl + '/' + values.id); a.attr('href', `${serverurl}/${values.id}`);
//parse pinned //parse pinned
if (values.pinned) { if (values.pinned) {
pin.addClass('active'); pin.addClass('active');
@ -185,12 +188,12 @@ historyList.on('updated', function (e) {
pin.removeClass('active'); pin.removeClass('active');
} }
//parse tags //parse tags
var tags = values.tags; const tags = values.tags;
if (tags && tags.length > 0 && tagsEl.children().length <= 0) { if (tags && tags.length > 0 && tagsEl.children().length <= 0) {
var labels = []; const labels = [];
for (var j = 0; j < tags.length; j++) { for (let j = 0; j < tags.length; j++) {
//push into the item label //push into the item label
labels.push("<span class='label label-default'>" + tags[j] + "</span>"); labels.push(`<span class='label label-default'>${tags[j]}</span>`);
} }
tagsEl.html(labels.join(' ')); tagsEl.html(labels.join(' '));
} }
@ -204,21 +207,21 @@ historyList.on('updated', function (e) {
function historyCloseClick(e) { function historyCloseClick(e) {
e.preventDefault(); e.preventDefault();
var id = $(this).closest("a").siblings("span").html(); const id = $(this).closest("a").siblings("span").html();
var value = historyList.get('id', id)[0]._values; const value = historyList.get('id', id)[0]._values;
$('.ui-delete-modal-msg').text('Do you really want to delete below history?'); $('.ui-delete-modal-msg').text('Do you really want to delete below history?');
$('.ui-delete-modal-item').html('<i class="fa fa-file-text"></i> ' + value.text + '<br><i class="fa fa-clock-o"></i> ' + value.time); $('.ui-delete-modal-item').html(`<i class="fa fa-file-text"></i> ${value.text}<br><i class="fa fa-clock-o"></i> ${value.time}`);
clearHistory = false; clearHistory = false;
deleteId = id; deleteId = id;
} }
function historyPinClick(e) { function historyPinClick(e) {
e.preventDefault(); e.preventDefault();
var $this = $(this); const $this = $(this);
var id = $this.closest("a").siblings("span").html(); const id = $this.closest("a").siblings("span").html();
var item = historyList.get('id', id)[0]; const item = historyList.get('id', id)[0];
var values = item._values; const values = item._values;
var pinned = values.pinned; let pinned = values.pinned;
if (!values.pinned) { if (!values.pinned) {
pinned = true; pinned = true;
item._values.pinned = true; item._values.pinned = true;
@ -226,10 +229,10 @@ function historyPinClick(e) {
pinned = false; pinned = false;
item._values.pinned = false; item._values.pinned = false;
} }
checkIfAuth(function () { checkIfAuth(() => {
postHistoryToServer(id, { postHistoryToServer(id, {
pinned: pinned pinned
}, function (err, result) { }, (err, result) => {
if (!err) { if (!err) {
if (pinned) if (pinned)
$this.addClass('active'); $this.addClass('active');
@ -237,9 +240,9 @@ function historyPinClick(e) {
$this.removeClass('active'); $this.removeClass('active');
} }
}); });
}, function () { }, () => {
getHistory(function (notehistory) { getHistory(notehistory => {
for(var i = 0; i < notehistory.length; i++) { for(let i = 0; i < notehistory.length; i++) {
if (notehistory[i].id == id) { if (notehistory[i].id == id) {
notehistory[i].pinned = pinned; notehistory[i].pinned = pinned;
break; break;
@ -258,10 +261,10 @@ function historyPinClick(e) {
setInterval(updateItemFromNow, 60000); setInterval(updateItemFromNow, 60000);
function updateItemFromNow() { function updateItemFromNow() {
var items = $('.item').toArray(); const items = $('.item').toArray();
for (var i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
var item = $(items[i]); const item = $(items[i]);
var timestamp = parseInt(item.find('.timestamp').text()); const timestamp = parseInt(item.find('.timestamp').text());
item.find('.fromNow').text(moment(timestamp).fromNow()); item.find('.fromNow').text(moment(timestamp).fromNow());
} }
} }
@ -270,8 +273,8 @@ var clearHistory = false;
var deleteId = null; var deleteId = null;
function deleteHistory() { function deleteHistory() {
checkIfAuth(function () { checkIfAuth(() => {
deleteServerHistory(deleteId, function (err, result) { deleteServerHistory(deleteId, (err, result) => {
if (!err) { if (!err) {
if (clearHistory) { if (clearHistory) {
historyList.clear(); historyList.clear();
@ -285,7 +288,7 @@ function deleteHistory() {
deleteId = null; deleteId = null;
clearHistory = false; clearHistory = false;
}); });
}, function () { }, () => {
if (clearHistory) { if (clearHistory) {
saveHistory([]); saveHistory([]);
historyList.clear(); historyList.clear();
@ -293,8 +296,8 @@ function deleteHistory() {
deleteId = null; deleteId = null;
} else { } else {
if (!deleteId) return; if (!deleteId) return;
getHistory(function (notehistory) { getHistory(notehistory => {
var newnotehistory = removeHistory(deleteId, notehistory); const newnotehistory = removeHistory(deleteId, notehistory);
saveHistory(newnotehistory); saveHistory(newnotehistory);
historyList.remove('id', deleteId); historyList.remove('id', deleteId);
checkHistoryList(); checkHistoryList();
@ -306,36 +309,36 @@ function deleteHistory() {
}); });
} }
$(".ui-delete-modal-confirm").click(function () { $(".ui-delete-modal-confirm").click(() => {
deleteHistory(); deleteHistory();
}); });
$(".ui-import-from-browser").click(function () { $(".ui-import-from-browser").click(() => {
saveStorageHistoryToServer(function () { saveStorageHistoryToServer(() => {
parseStorageToHistory(historyList, parseHistoryCallback); parseStorageToHistory(historyList, parseHistoryCallback);
}); });
}); });
$(".ui-save-history").click(function () { $(".ui-save-history").click(() => {
getHistory(function (data) { getHistory(data => {
var history = JSON.stringify(data); const history = JSON.stringify(data);
var blob = new Blob([history], { const blob = new Blob([history], {
type: "application/json;charset=utf-8" type: "application/json;charset=utf-8"
}); });
saveAs(blob, 'hackmd_history_' + moment().format('YYYYMMDDHHmmss')); saveAs(blob, `hackmd_history_${moment().format('YYYYMMDDHHmmss')}`);
}); });
}); });
$(".ui-open-history").bind("change", function (e) { $(".ui-open-history").bind("change", e => {
var files = e.target.files || e.dataTransfer.files; const files = e.target.files || e.dataTransfer.files;
var file = files[0]; const file = files[0];
var reader = new FileReader(); const reader = new FileReader();
reader.onload = function () { reader.onload = () => {
var notehistory = JSON.parse(reader.result); const notehistory = JSON.parse(reader.result);
//console.log(notehistory); //console.log(notehistory);
if (!reader.result) return; if (!reader.result) return;
getHistory(function (data) { getHistory(data => {
var mergedata = data.concat(notehistory); let mergedata = data.concat(notehistory);
mergedata = clearDuplicatedHistory(mergedata); mergedata = clearDuplicatedHistory(mergedata);
saveHistory(mergedata); saveHistory(mergedata);
parseHistory(historyList, parseHistoryCallback); parseHistory(historyList, parseHistoryCallback);
@ -345,18 +348,18 @@ $(".ui-open-history").bind("change", function (e) {
reader.readAsText(file); reader.readAsText(file);
}); });
$(".ui-clear-history").click(function () { $(".ui-clear-history").click(() => {
$('.ui-delete-modal-msg').text('Do you really want to clear all history?'); $('.ui-delete-modal-msg').text('Do you really want to clear all history?');
$('.ui-delete-modal-item').html('There is no turning back.'); $('.ui-delete-modal-item').html('There is no turning back.');
clearHistory = true; clearHistory = true;
deleteId = null; deleteId = null;
}); });
$(".ui-refresh-history").click(function () { $(".ui-refresh-history").click(() => {
var lastTags = $(".ui-use-tags").select2('val'); const lastTags = $(".ui-use-tags").select2('val');
$(".ui-use-tags").select2('val', ''); $(".ui-use-tags").select2('val', '');
historyList.filter(); historyList.filter();
var lastKeyword = $('.search').val(); const lastKeyword = $('.search').val();
$('.search').val(''); $('.search').val('');
historyList.search(); historyList.search();
$('#history-list').slideUp('fast'); $('#history-list').slideUp('fast');
@ -364,7 +367,7 @@ $(".ui-refresh-history").click(function () {
resetCheckAuth(); resetCheckAuth();
historyList.clear(); historyList.clear();
parseHistory(historyList, function (list, notehistory) { parseHistory(historyList, (list, notehistory) => {
parseHistoryCallback(list, notehistory); parseHistoryCallback(list, notehistory);
$(".ui-use-tags").select2('val', lastTags); $(".ui-use-tags").select2('val', lastTags);
$(".ui-use-tags").trigger('change'); $(".ui-use-tags").trigger('change');
@ -375,16 +378,16 @@ $(".ui-refresh-history").click(function () {
}); });
}); });
$(".ui-logout").click(function () { $(".ui-logout").click(() => {
clearLoginState(); clearLoginState();
location.href = serverurl + '/logout'; location.href = `${serverurl}/logout`;
}); });
var filtertags = []; let filtertags = [];
$(".ui-use-tags").select2({ $(".ui-use-tags").select2({
placeholder: $(".ui-use-tags").attr('placeholder'), placeholder: $(".ui-use-tags").attr('placeholder'),
multiple: true, multiple: true,
data: function () { data() {
return { return {
results: filtertags results: filtertags
}; };
@ -394,7 +397,7 @@ $('.select2-input').css('width', 'inherit');
buildTagsFilter([]); buildTagsFilter([]);
function buildTagsFilter(tags) { function buildTagsFilter(tags) {
for (var i = 0; i < tags.length; i++) for (let i = 0; i < tags.length; i++)
tags[i] = { tags[i] = {
id: i, id: i,
text: S(tags[i]).unescapeHTML().s text: S(tags[i]).unescapeHTML().s
@ -402,17 +405,17 @@ function buildTagsFilter(tags) {
filtertags = tags; filtertags = tags;
} }
$(".ui-use-tags").on('change', function () { $(".ui-use-tags").on('change', function () {
var tags = []; const tags = [];
var data = $(this).select2('data'); const data = $(this).select2('data');
for (var i = 0; i < data.length; i++) for (let i = 0; i < data.length; i++)
tags.push(data[i].text); tags.push(data[i].text);
if (tags.length > 0) { if (tags.length > 0) {
historyList.filter(function (item) { historyList.filter(item => {
var values = item.values(); const values = item.values();
if (!values.tags) return false; if (!values.tags) return false;
var found = false; let found = false;
for (var i = 0; i < tags.length; i++) { for (let i = 0; i < tags.length; i++) {
if (values.tags.indexOf(tags[i]) != -1) { if (values.tags.includes(tags[i])) {
found = true; found = true;
break; break;
} }
@ -425,6 +428,6 @@ $(".ui-use-tags").on('change', function () {
checkHistoryList(); checkHistoryList();
}); });
$('.search').keyup(function () { $('.search').keyup(() => {
checkHistoryList(); checkHistoryList();
}); });

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,13 @@
var store = require('store'); import store from 'store';
var S = require('string'); import S from 'string';
var common = require('./common'); import {
var checkIfAuth = common.checkIfAuth; checkIfAuth
var urlpath = common.urlpath; } from './lib/common/login';
var getLoginState = common.getLoginState;
import {
urlpath
} from './lib/config';
window.migrateHistoryFromTempCallback = null; window.migrateHistoryFromTempCallback = null;
@ -12,22 +15,22 @@ migrateHistoryFromTemp();
function migrateHistoryFromTemp() { function migrateHistoryFromTemp() {
if (url('#tempid')) { if (url('#tempid')) {
$.get(serverurl + '/temp', { $.get(`${serverurl}/temp`, {
tempid: url('#tempid') tempid: url('#tempid')
}) })
.done(function (data) { .done(data => {
if (data && data.temp) { if (data && data.temp) {
getStorageHistory(function (olddata) { getStorageHistory(olddata => {
if (!olddata || olddata.length == 0) { if (!olddata || olddata.length == 0) {
saveHistoryToStorage(JSON.parse(data.temp)); saveHistoryToStorage(JSON.parse(data.temp));
} }
}); });
} }
}) })
.always(function () { .always(() => {
var hash = location.hash.split('#')[1]; let hash = location.hash.split('#')[1];
hash = hash.split('&'); hash = hash.split('&');
for (var i = 0; i < hash.length; i++) for (let i = 0; i < hash.length; i++)
if (hash[i].indexOf('tempid') == 0) { if (hash[i].indexOf('tempid') == 0) {
hash.splice(i, 1); hash.splice(i, 1);
i--; i--;
@ -40,12 +43,12 @@ function migrateHistoryFromTemp() {
} }
} }
function saveHistory(notehistory) { export function saveHistory(notehistory) {
checkIfAuth( checkIfAuth(
function () { () => {
saveHistoryToServer(notehistory); saveHistoryToServer(notehistory);
}, },
function () { () => {
saveHistoryToStorage(notehistory); saveHistoryToStorage(notehistory);
} }
); );
@ -65,7 +68,7 @@ function saveHistoryToCookie(notehistory) {
} }
function saveHistoryToServer(notehistory) { function saveHistoryToServer(notehistory) {
$.post(serverurl + '/history', { $.post(`${serverurl}/history`, {
history: JSON.stringify(notehistory) history: JSON.stringify(notehistory)
}); });
} }
@ -75,37 +78,37 @@ function saveCookieHistoryToStorage(callback) {
callback(); callback();
} }
function saveStorageHistoryToServer(callback) { export function saveStorageHistoryToServer(callback) {
var data = store.get('notehistory'); const data = store.get('notehistory');
if (data) { if (data) {
$.post(serverurl + '/history', { $.post(`${serverurl}/history`, {
history: data history: data
}) })
.done(function (data) { .done(data => {
callback(data); callback(data);
}); });
} }
} }
function saveCookieHistoryToServer(callback) { function saveCookieHistoryToServer(callback) {
$.post(serverurl + '/history', { $.post(`${serverurl}/history`, {
history: Cookies.get('notehistory') history: Cookies.get('notehistory')
}) })
.done(function (data) { .done(data => {
callback(data); callback(data);
}); });
} }
function clearDuplicatedHistory(notehistory) { export function clearDuplicatedHistory(notehistory) {
var newnotehistory = []; const newnotehistory = [];
for (var i = 0; i < notehistory.length; i++) { for (let i = 0; i < notehistory.length; i++) {
var found = false; let found = false;
for (var j = 0; j < newnotehistory.length; j++) { for (let j = 0; j < newnotehistory.length; j++) {
var id = notehistory[i].id.replace(/\=+$/, ''); const id = notehistory[i].id.replace(/\=+$/, '');
var newId = newnotehistory[j].id.replace(/\=+$/, ''); const newId = newnotehistory[j].id.replace(/\=+$/, '');
if (id == newId || notehistory[i].id == newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) { if (id == newId || notehistory[i].id == newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) {
var time = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a')); const time = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
var newTime = (typeof newnotehistory[i].time === 'number' ? moment(newnotehistory[i].time) : moment(newnotehistory[i].time, 'MMMM Do YYYY, h:mm:ss a')); const newTime = (typeof newnotehistory[i].time === 'number' ? moment(newnotehistory[i].time) : moment(newnotehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
if(time >= newTime) { if(time >= newTime) {
newnotehistory[j] = notehistory[i]; newnotehistory[j] = notehistory[i];
} }
@ -123,42 +126,42 @@ function addHistory(id, text, time, tags, pinned, notehistory) {
// only add when note id exists // only add when note id exists
if (id) { if (id) {
notehistory.push({ notehistory.push({
id: id, id,
text: text, text,
time: time, time,
tags: tags, tags,
pinned: pinned pinned
}); });
} }
return notehistory; return notehistory;
} }
function removeHistory(id, notehistory) { export function removeHistory(id, notehistory) {
for (var i = 0; i < notehistory.length; i++) { for (let i = 0; i < notehistory.length; i++) {
if (notehistory[i].id == id) { if (notehistory[i].id == id) {
notehistory.splice(i, 1); notehistory.splice(i, 1);
i--; i -= 1;
} }
} }
return notehistory; return notehistory;
} }
//used for inner //used for inner
function writeHistory(title, tags) { export function writeHistory(title, tags) {
checkIfAuth( checkIfAuth(
function () { () => {
// no need to do this anymore, this will count from server-side // no need to do this anymore, this will count from server-side
// writeHistoryToServer(title, tags); // writeHistoryToServer(title, tags);
}, },
function () { () => {
writeHistoryToStorage(title, tags); writeHistoryToStorage(title, tags);
} }
); );
} }
function writeHistoryToServer(title, tags) { function writeHistoryToServer(title, tags) {
$.get(serverurl + '/history') $.get(`${serverurl}/history`)
.done(function (data) { .done(data => {
try { try {
if (data.history) { if (data.history) {
var notehistory = data.history; var notehistory = data.history;
@ -171,10 +174,10 @@ function writeHistoryToServer(title, tags) {
if (!notehistory) if (!notehistory)
notehistory = []; notehistory = [];
var newnotehistory = generateHistory(title, tags, notehistory); const newnotehistory = generateHistory(title, tags, notehistory);
saveHistoryToServer(newnotehistory); saveHistoryToServer(newnotehistory);
}) })
.fail(function (xhr, status, error) { .fail((xhr, status, error) => {
console.error(xhr.responseText); console.error(xhr.responseText);
}); });
} }
@ -188,13 +191,13 @@ function writeHistoryToCookie(title, tags) {
if (!notehistory) if (!notehistory)
notehistory = []; notehistory = [];
var newnotehistory = generateHistory(title, tags, notehistory); const newnotehistory = generateHistory(title, tags, notehistory);
saveHistoryToCookie(newnotehistory); saveHistoryToCookie(newnotehistory);
} }
function writeHistoryToStorage(title, tags) { function writeHistoryToStorage(title, tags) {
if (store.enabled) { if (store.enabled) {
var data = store.get('notehistory'); let data = store.get('notehistory');
if (data) { if (data) {
if (typeof data == "string") if (typeof data == "string")
data = JSON.parse(data); data = JSON.parse(data);
@ -204,7 +207,7 @@ function writeHistoryToStorage(title, tags) {
if (!notehistory) if (!notehistory)
notehistory = []; notehistory = [];
var newnotehistory = generateHistory(title, tags, notehistory); const newnotehistory = generateHistory(title, tags, notehistory);
saveHistoryToStorage(newnotehistory); saveHistoryToStorage(newnotehistory);
} else { } else {
writeHistoryToCookie(title, tags); writeHistoryToCookie(title, tags);
@ -212,32 +215,30 @@ function writeHistoryToStorage(title, tags) {
} }
if (!Array.isArray) { if (!Array.isArray) {
Array.isArray = function(arg) { Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]';
return Object.prototype.toString.call(arg) === '[object Array]';
};
} }
function renderHistory(title, tags) { function renderHistory(title, tags) {
//console.debug(tags); //console.debug(tags);
var id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]; const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1];
return { return {
id: id, id,
text: title, text: title,
time: moment().valueOf(), time: moment().valueOf(),
tags: tags tags
}; };
} }
function generateHistory(title, tags, notehistory) { function generateHistory(title, tags, notehistory) {
var info = renderHistory(title, tags); const info = renderHistory(title, tags);
//keep any pinned data //keep any pinned data
var pinned = false; let pinned = false;
for (var i = 0; i < notehistory.length; i++) { for (let i = 0; i < notehistory.length; i++) {
if (notehistory[i].id == info.id && notehistory[i].pinned) { if (notehistory[i].id == info.id && notehistory[i].pinned) {
pinned = true; pinned = true;
break; break;
} }
} }
notehistory = removeHistory(info.id, notehistory); notehistory = removeHistory(info.id, notehistory);
notehistory = addHistory(info.id, info.text, info.time, info.tags, pinned, notehistory); notehistory = addHistory(info.id, info.text, info.time, info.tags, pinned, notehistory);
notehistory = clearDuplicatedHistory(notehistory); notehistory = clearDuplicatedHistory(notehistory);
@ -245,25 +246,25 @@ function generateHistory(title, tags, notehistory) {
} }
//used for outer //used for outer
function getHistory(callback) { export function getHistory(callback) {
checkIfAuth( checkIfAuth(
function () { () => {
getServerHistory(callback); getServerHistory(callback);
}, },
function () { () => {
getStorageHistory(callback); getStorageHistory(callback);
} }
); );
} }
function getServerHistory(callback) { function getServerHistory(callback) {
$.get(serverurl + '/history') $.get(`${serverurl}/history`)
.done(function (data) { .done(data => {
if (data.history) { if (data.history) {
callback(data.history); callback(data.history);
} }
}) })
.fail(function (xhr, status, error) { .fail((xhr, status, error) => {
console.error(xhr.responseText); console.error(xhr.responseText);
}); });
} }
@ -272,9 +273,9 @@ function getCookieHistory(callback) {
callback(Cookies.getJSON('notehistory')); callback(Cookies.getJSON('notehistory'));
} }
function getStorageHistory(callback) { export function getStorageHistory(callback) {
if (store.enabled) { if (store.enabled) {
var data = store.get('notehistory'); let data = store.get('notehistory');
if (data) { if (data) {
if (typeof data == "string") if (typeof data == "string")
data = JSON.parse(data); data = JSON.parse(data);
@ -286,37 +287,37 @@ function getStorageHistory(callback) {
} }
} }
function parseHistory(list, callback) { export function parseHistory(list, callback) {
checkIfAuth( checkIfAuth(
function () { () => {
parseServerToHistory(list, callback); parseServerToHistory(list, callback);
}, },
function () { () => {
parseStorageToHistory(list, callback); parseStorageToHistory(list, callback);
} }
); );
} }
function parseServerToHistory(list, callback) { export function parseServerToHistory(list, callback) {
$.get(serverurl + '/history') $.get(`${serverurl}/history`)
.done(function (data) { .done(data => {
if (data.history) { if (data.history) {
parseToHistory(list, data.history, callback); parseToHistory(list, data.history, callback);
} }
}) })
.fail(function (xhr, status, error) { .fail((xhr, status, error) => {
console.error(xhr.responseText); console.error(xhr.responseText);
}); });
} }
function parseCookieToHistory(list, callback) { function parseCookieToHistory(list, callback) {
var notehistory = Cookies.getJSON('notehistory'); const notehistory = Cookies.getJSON('notehistory');
parseToHistory(list, notehistory, callback); parseToHistory(list, notehistory, callback);
} }
function parseStorageToHistory(list, callback) { export function parseStorageToHistory(list, callback) {
if (store.enabled) { if (store.enabled) {
var data = store.get('notehistory'); let data = store.get('notehistory');
if (data) { if (data) {
if (typeof data == "string") if (typeof data == "string")
data = JSON.parse(data); data = JSON.parse(data);
@ -332,9 +333,9 @@ function parseToHistory(list, notehistory, callback) {
if (!callback) return; if (!callback) return;
else if (!list || !notehistory) callback(list, notehistory); else if (!list || !notehistory) callback(list, notehistory);
else if (notehistory && notehistory.length > 0) { else if (notehistory && notehistory.length > 0) {
for (var i = 0; i < notehistory.length; i++) { for (let i = 0; i < notehistory.length; i++) {
//parse time to timestamp and fromNow //parse time to timestamp and fromNow
var timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a')); const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
notehistory[i].timestamp = timestamp.valueOf(); notehistory[i].timestamp = timestamp.valueOf();
notehistory[i].fromNow = timestamp.fromNow(); notehistory[i].fromNow = timestamp.fromNow();
notehistory[i].time = timestamp.format('llll'); notehistory[i].time = timestamp.format('llll');
@ -349,42 +350,23 @@ function parseToHistory(list, notehistory, callback) {
callback(list, notehistory); callback(list, notehistory);
} }
function postHistoryToServer(noteId, data, callback) { export function postHistoryToServer(noteId, data, callback) {
$.post(serverurl + '/history/' + noteId, data) $.post(`${serverurl}/history/${noteId}`, data)
.done(function (result) { .done(result => callback(null, result))
return callback(null, result); .fail((xhr, status, error) => {
})
.fail(function (xhr, status, error) {
console.error(xhr.responseText); console.error(xhr.responseText);
return callback(error, null); return callback(error, null);
}); });
} }
function deleteServerHistory(noteId, callback) { export function deleteServerHistory(noteId, callback) {
$.ajax({ $.ajax({
url: serverurl + '/history' + (noteId ? '/' + noteId : ""), url: `${serverurl}/history${noteId ? '/' + noteId : ""}`,
type: 'DELETE' type: 'DELETE'
}) })
.done(function (result) { .done(result => callback(null, result))
return callback(null, result); .fail((xhr, status, error) => {
})
.fail(function (xhr, status, error) {
console.error(xhr.responseText); console.error(xhr.responseText);
return callback(error, null); return callback(error, null);
}); });
} }
module.exports = {
writeHistory: writeHistory,
parseHistory: parseHistory,
getStorageHistory: getStorageHistory,
getHistory: getHistory,
saveHistory: saveHistory,
removeHistory: removeHistory,
parseStorageToHistory: parseStorageToHistory,
postHistoryToServer: postHistoryToServer,
deleteServerHistory: deleteServerHistory,
parseServerToHistory: parseServerToHistory,
saveStorageHistoryToServer: saveStorageHistoryToServer,
clearDuplicatedHistory: clearDuplicatedHistory
}

View file

@ -17,51 +17,58 @@ var _ = require("lodash");
var List = require('list.js'); var List = require('list.js');
var common = require('./common.js'); import {
var urlpath = common.urlpath; checkLoginStateChanged,
var noteid = common.noteid; setloginStateChangeEvent
var debug = common.debug; } from './lib/common/login';
var version = common.version;
var GOOGLE_API_KEY = common.GOOGLE_API_KEY;
var GOOGLE_CLIENT_ID = common.GOOGLE_CLIENT_ID;
var DROPBOX_APP_KEY = common.DROPBOX_APP_KEY;
var noteurl = common.noteurl;
var checkLoginStateChanged = common.checkLoginStateChanged; import {
debug,
DROPBOX_APP_KEY,
GOOGLE_API_KEY,
GOOGLE_CLIENT_ID,
noteid,
noteurl,
urlpath,
version
} from './lib/config';
var extra = require('./extra'); import {
var md = extra.md; autoLinkify,
var updateLastChange = extra.updateLastChange; deduplicatedHeaderId,
var postProcess = extra.postProcess; exportToHTML,
var finishView = extra.finishView; exportToRawHTML,
var autoLinkify = extra.autoLinkify; finishView,
var generateToc = extra.generateToc; generateToc,
var smoothHashScroll = extra.smoothHashScroll; isValidURL,
var deduplicatedHeaderId = extra.deduplicatedHeaderId; md,
var renderTOC = extra.renderTOC; parseMeta,
var renderTitle = extra.renderTitle; postProcess,
var renderFilename = extra.renderFilename; renderFilename,
var renderTags = extra.renderTags; renderTOC,
var isValidURL = extra.isValidURL; renderTags,
var scrollToHash = extra.scrollToHash; renderTitle,
var updateLastChangeUser = extra.updateLastChangeUser; scrollToHash,
var updateOwner = extra.updateOwner; smoothHashScroll,
var parseMeta = extra.parseMeta; updateLastChange,
var exportToHTML = extra.exportToHTML; updateLastChangeUser,
var exportToRawHTML = extra.exportToRawHTML; updateOwner
} from './extra';
var syncScroll = require('./syncscroll'); import {
var setupSyncAreas = syncScroll.setupSyncAreas; clearMap,
var clearMap = syncScroll.clearMap; setupSyncAreas,
var syncScrollToEdit = syncScroll.syncScrollToEdit; syncScrollToEdit,
var syncScrollToView = syncScroll.syncScrollToView; syncScrollToView
} from './syncscroll';
var historyModule = require('./history'); import {
var writeHistory = historyModule.writeHistory; writeHistory,
var deleteServerHistory = historyModule.deleteServerHistory; deleteServerHistory,
var getHistory = historyModule.getHistory; getHistory,
var saveHistory = historyModule.saveHistory; saveHistory,
var removeHistory = historyModule.removeHistory; removeHistory
} from './history';
var renderer = require('./render'); var renderer = require('./render');
var preventXSS = renderer.preventXSS; var preventXSS = renderer.preventXSS;
@ -963,10 +970,10 @@ function setNeedRefresh() {
showStatus(statusType.offline); showStatus(statusType.offline);
} }
loginStateChangeEvent = function () { setloginStateChangeEvent(function () {
setRefreshModal('user-state-changed'); setRefreshModal('user-state-changed');
setNeedRefresh(); setNeedRefresh();
}; });
//visibility //visibility
var wasFocus = false; var wasFocus = false;
@ -3717,6 +3724,7 @@ function checkCursorMenuInner() {
var offsetLeft = 0; var offsetLeft = 0;
var offsetTop = defaultTextHeight; var offsetTop = defaultTextHeight;
// set up side down // set up side down
window.upSideDown = false;
var lastUpSideDown = upSideDown = false; var lastUpSideDown = upSideDown = false;
// only do when have width and height // only do when have width and height
if (width > 0 && height > 0) { if (width > 0 && height > 0) {

View file

@ -0,0 +1,89 @@
import { serverurl } from '../config';
let checkAuth = false;
let profile = null;
let lastLoginState = getLoginState();
let lastUserId = getUserId();
var loginStateChangeEvent = null;
export function setloginStateChangeEvent(func) {
loginStateChangeEvent = func;
}
export function resetCheckAuth() {
checkAuth = false;
}
export function setLoginState(bool, id) {
Cookies.set('loginstate', bool, {
expires: 365
});
if (id) {
Cookies.set('userid', id, {
expires: 365
});
} else {
Cookies.remove('userid');
}
lastLoginState = bool;
lastUserId = id;
checkLoginStateChanged();
}
export function checkLoginStateChanged() {
if (getLoginState() != lastLoginState || getUserId() != lastUserId) {
if (loginStateChangeEvent) setTimeout(loginStateChangeEvent, 100);
return true;
} else {
return false;
}
}
export function getLoginState() {
const state = Cookies.get('loginstate');
return state === "true" || state === true;
}
export function getUserId() {
return Cookies.get('userid');
}
export function clearLoginState() {
Cookies.remove('loginstate');
}
export function checkIfAuth(yesCallback, noCallback) {
const cookieLoginState = getLoginState();
if (checkLoginStateChanged()) checkAuth = false;
if (!checkAuth || typeof cookieLoginState == 'undefined') {
$.get(`${serverurl}/me`)
.done(data => {
if (data && data.status == 'ok') {
profile = data;
yesCallback(profile);
setLoginState(true, data.id);
} else {
noCallback();
setLoginState(false);
}
})
.fail(() => {
noCallback();
})
.always(() => {
checkAuth = true;
});
} else if (cookieLoginState) {
yesCallback(profile);
} else {
noCallback();
}
}
export default {
checkAuth,
profile,
lastLoginState,
lastUserId,
loginStateChangeEvent
};

View file

@ -0,0 +1,19 @@
import configJson from '../../../../config.json'; // root path json config
const config = 'production' === process.env.NODE_ENV ? configJson.production : configJson.development;
export const GOOGLE_API_KEY = (config.google && config.google.apiKey) || '';
export const GOOGLE_CLIENT_ID = (config.google && config.google.clientID) || '';
export const DROPBOX_APP_KEY = (config.dropbox && config.dropbox.appKey) || '';
export const domain = config.domain || ''; // domain name
export const urlpath = config.urlpath || ''; // sub url path, like: www.example.com/<urlpath>
export const debug = config.debug || false;
export const port = window.location.port;
export const serverurl = `${window.location.protocol}//${domain ? domain : window.location.hostname}${port ? ':' + port : ''}${urlpath ? '/' + urlpath : ''}`;
window.serverurl = serverurl;
export const noteid = urlpath ? window.location.pathname.slice(urlpath.length + 1, window.location.pathname.length).split('/')[1] : window.location.pathname.split('/')[1];
export const noteurl = `${serverurl}/${noteid}`;
export const version = '0.5.0';

View file

@ -4,32 +4,34 @@ require('../css/site.css');
require('highlight.js/styles/github-gist.css'); require('highlight.js/styles/github-gist.css');
var extra = require('./extra'); import {
var md = extra.md; autoLinkify,
var finishView = extra.finishView; deduplicatedHeaderId,
var autoLinkify = extra.autoLinkify; finishView,
var deduplicatedHeaderId = extra.deduplicatedHeaderId; generateToc,
var renderTOC = extra.renderTOC; md,
var generateToc = extra.generateToc; parseMeta,
var smoothHashScroll = extra.smoothHashScroll; postProcess,
var postProcess = extra.postProcess; renderTOC,
var updateLastChange = extra.updateLastChange; scrollToHash,
var parseMeta = extra.parseMeta; smoothHashScroll,
var scrollToHash = extra.scrollToHash; updateLastChange
var preventXSS = require('./render').preventXSS; } from './extra';
var markdown = $("#doc.markdown-body"); import { preventXSS } from './render';
var text = markdown.text();
var lastMeta = md.meta; const markdown = $("#doc.markdown-body");
const text = markdown.text();
const lastMeta = md.meta;
md.meta = {}; md.meta = {};
delete md.metaError; delete md.metaError;
var rendered = md.render(text); let rendered = md.render(text);
if (md.meta.type && md.meta.type === 'slide') { if (md.meta.type && md.meta.type === 'slide') {
var slideOptions = { const slideOptions = {
separator: '^(\r\n?|\n)---(\r\n?|\n)$', separator: '^(\r\n?|\n)---(\r\n?|\n)$',
verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$' verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$'
}; };
var slides = RevealMarkdown.slidify(text, slideOptions); const slides = RevealMarkdown.slidify(text, slideOptions);
markdown.html(slides); markdown.html(slides);
RevealMarkdown.initialize(); RevealMarkdown.initialize();
// prevent XSS // prevent XSS
@ -47,10 +49,11 @@ if (md.meta.type && md.meta.type === 'slide') {
} }
// prevent XSS // prevent XSS
rendered = preventXSS(rendered); rendered = preventXSS(rendered);
var result = postProcess(rendered); const result = postProcess(rendered);
markdown.html(result.html()); markdown.html(result.html());
} }
$(document.body).show(); $(document.body).show();
finishView(markdown); finishView(markdown);
autoLinkify(markdown); autoLinkify(markdown);
deduplicatedHeaderId(markdown); deduplicatedHeaderId(markdown);
@ -61,17 +64,18 @@ smoothHashScroll();
createtime = lastchangeui.time.attr('data-createtime'); createtime = lastchangeui.time.attr('data-createtime');
lastchangetime = lastchangeui.time.attr('data-updatetime'); lastchangetime = lastchangeui.time.attr('data-updatetime');
updateLastChange(); updateLastChange();
var url = window.location.pathname;
$('.ui-edit').attr('href', url + '/edit'); const url = window.location.pathname;
var toc = $('.ui-toc'); $('.ui-edit').attr('href', `${url}/edit`);
var tocAffix = $('.ui-affix-toc'); const toc = $('.ui-toc');
var tocDropdown = $('.ui-toc-dropdown'); const tocAffix = $('.ui-affix-toc');
const tocDropdown = $('.ui-toc-dropdown');
//toc //toc
tocDropdown.click(function (e) { tocDropdown.click(e => {
e.stopPropagation(); e.stopPropagation();
}); });
var enoughForAffixToc = true; let enoughForAffixToc = true;
function generateScrollspy() { function generateScrollspy() {
$(document.body).scrollspy({ $(document.body).scrollspy({
@ -90,18 +94,18 @@ function generateScrollspy() {
function windowResize() { function windowResize() {
//toc right //toc right
var paddingRight = parseFloat(markdown.css('padding-right')); const paddingRight = parseFloat(markdown.css('padding-right'));
var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight)); const right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));
toc.css('right', right + 'px'); toc.css('right', `${right}px`);
//affix toc left //affix toc left
var newbool; let newbool;
var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2; const rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;
//for ipad or wider device //for ipad or wider device
if (rightMargin >= 133) { if (rightMargin >= 133) {
newbool = true; newbool = true;
var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2; const affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;
var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin; const left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;
tocAffix.css('left', left + 'px'); tocAffix.css('left', `${left}px`);
} else { } else {
newbool = false; newbool = false;
} }
@ -110,10 +114,10 @@ function windowResize() {
generateScrollspy(); generateScrollspy();
} }
} }
$(window).resize(function () { $(window).resize(() => {
windowResize(); windowResize();
}); });
$(document).ready(function () { $(document).ready(() => {
windowResize(); windowResize();
generateScrollspy(); generateScrollspy();
setTimeout(scrollToHash, 0); setTimeout(scrollToHash, 0);
@ -121,13 +125,13 @@ $(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
}); });
function scrollToTop() { export function scrollToTop() {
$('body, html').stop(true, true).animate({ $('body, html').stop(true, true).animate({
scrollTop: 0 scrollTop: 0
}, 100, "linear"); }, 100, "linear");
} }
function scrollToBottom() { export function scrollToBottom() {
$('body, html').stop(true, true).animate({ $('body, html').stop(true, true).animate({
scrollTop: $(document.body)[0].scrollHeight scrollTop: $(document.body)[0].scrollHeight
}, 100, "linear"); }, 100, "linear");
@ -135,8 +139,3 @@ function scrollToBottom() {
window.scrollToTop = scrollToTop; window.scrollToTop = scrollToTop;
window.scrollToBottom = scrollToBottom; window.scrollToBottom = scrollToBottom;
module.exports = {
scrollToBottom: scrollToBottom,
scrollToTop: scrollToTop
}

View file

@ -1,67 +1,65 @@
require('../css/extra.css'); require('../css/extra.css');
require('../css/site.css'); require('../css/site.css');
var extraModule = require('./extra'); import { md, updateLastChange, finishView } from './extra';
var md = extraModule.md;
var updateLastChange = extraModule.updateLastChange;
var finishView = extraModule.finishView;
var preventXSS = require('./render').preventXSS; import { preventXSS } from './render';
var body = $(".slides").text(); const body = $(".slides").text();
createtime = lastchangeui.time.attr('data-createtime'); createtime = lastchangeui.time.attr('data-createtime');
lastchangetime = lastchangeui.time.attr('data-updatetime'); lastchangetime = lastchangeui.time.attr('data-updatetime');
updateLastChange(); updateLastChange();
var url = window.location.pathname; const url = window.location.pathname;
$('.ui-edit').attr('href', url + '/edit'); $('.ui-edit').attr('href', `${url}/edit`);
$(document).ready(function () { $(document).ready(() => {
//tooltip //tooltip
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
}); });
function extend() { function extend() {
var target = {}; const target = {};
for (var i = 0; i < arguments.length; i++) {
var source = arguments[i]; for (const source of arguments) {
for (var key in source) { for (const key in source) {
if (source.hasOwnProperty(key)) { if (source.hasOwnProperty(key)) {
target[key] = source[key]; target[key] = source[key];
} }
} }
} }
return target; return target;
} }
// Optional libraries used to extend on reveal.js // Optional libraries used to extend on reveal.js
var deps = [{ const deps = [{
src: serverurl + '/build/reveal.js/lib/js/classList.js', src: `${serverurl}/build/reveal.js/lib/js/classList.js`,
condition: function() { condition() {
return !document.body.classList; return !document.body.classList;
} }
}, { }, {
src: serverurl + '/js/reveal-markdown.js', src: `${serverurl}/js/reveal-markdown.js`,
callback: function () { callback() {
var slideOptions = { const slideOptions = {
separator: '^(\r\n?|\n)---(\r\n?|\n)$', separator: '^(\r\n?|\n)---(\r\n?|\n)$',
verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$' verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$'
}; };
var slides = RevealMarkdown.slidify(body, slideOptions); const slides = RevealMarkdown.slidify(body, slideOptions);
$(".slides").html(slides); $(".slides").html(slides);
RevealMarkdown.initialize(); RevealMarkdown.initialize();
$(".slides").show(); $(".slides").show();
} }
}, { }, {
src: serverurl + '/build/reveal.js/plugin/notes/notes.js', src: `${serverurl}/build/reveal.js/plugin/notes/notes.js`,
async: true, async: true,
condition: function() { condition() {
return !!document.body.classList; return !!document.body.classList;
} }
}]; }];
// default options to init reveal.js // default options to init reveal.js
var defaultOptions = { const defaultOptions = {
controls: true, controls: true,
progress: true, progress: true,
slideNumber: true, slideNumber: true,
@ -72,10 +70,10 @@ var defaultOptions = {
}; };
// options from yaml meta // options from yaml meta
var meta = JSON.parse($("#meta").text()); const meta = JSON.parse($("#meta").text());
var options = meta.slideOptions || {}; var options = meta.slideOptions || {};
var view = $('.reveal'); const view = $('.reveal');
//text language //text language
if (meta.lang && typeof meta.lang == "string") { if (meta.lang && typeof meta.lang == "string") {
@ -97,24 +95,24 @@ if (typeof meta.breaks === 'boolean' && !meta.breaks) {
} }
// options from URL query string // options from URL query string
var queryOptions = Reveal.getQueryHash() || {}; const queryOptions = Reveal.getQueryHash() || {};
var options = extend(defaultOptions, options, queryOptions); var options = extend(defaultOptions, options, queryOptions);
Reveal.initialize(options); Reveal.initialize(options);
window.viewAjaxCallback = function () { window.viewAjaxCallback = () => {
Reveal.layout(); Reveal.layout();
}; };
function renderSlide(event) { function renderSlide(event) {
if (window.location.search.match( /print-pdf/gi )) { if (window.location.search.match( /print-pdf/gi )) {
var slides = $('.slides'); const slides = $('.slides');
var title = document.title; var title = document.title;
finishView(slides); finishView(slides);
document.title = title; document.title = title;
Reveal.layout(); Reveal.layout();
} else { } else {
var markdown = $(event.currentSlide); const markdown = $(event.currentSlide);
if (!markdown.attr('data-rendered')) { if (!markdown.attr('data-rendered')) {
var title = document.title; var title = document.title;
finishView(markdown); finishView(markdown);
@ -125,16 +123,16 @@ function renderSlide(event) {
} }
} }
Reveal.addEventListener('ready', function (event) { Reveal.addEventListener('ready', event => {
renderSlide(event); renderSlide(event);
var markdown = $(event.currentSlide); const markdown = $(event.currentSlide);
// force browser redraw // force browser redraw
setTimeout(function () { setTimeout(() => {
markdown.hide().show(0); markdown.hide().show(0);
}, 0); }, 0);
}); });
Reveal.addEventListener('slidechanged', renderSlide); Reveal.addEventListener('slidechanged', renderSlide);
var isMacLike = navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) ? true : false; const isMacLike = navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) ? true : false;
if (!isMacLike) $('.container').addClass('hidescrollbar'); if (!isMacLike) $('.container').addClass('hidescrollbar');

View file

@ -1,12 +1,13 @@
// Inject line numbers for sync scroll. // Inject line numbers for sync scroll.
var extra = require('./extra'); import markdownitContainer from 'markdown-it-container';
var md = extra.md;
import { md } from './extra';
function addPart(tokens, idx) { function addPart(tokens, idx) {
if (tokens[idx].map && tokens[idx].level === 0) { if (tokens[idx].map && tokens[idx].level === 0) {
var startline = tokens[idx].map[0] + 1; const startline = tokens[idx].map[0] + 1;
var endline = tokens[idx].map[1]; const endline = tokens[idx].map[1];
tokens[idx].attrJoin('class', 'part'); tokens[idx].attrJoin('class', 'part');
tokens[idx].attrJoin('data-startline', startline); tokens[idx].attrJoin('data-startline', startline);
tokens[idx].attrJoin('data-endline', endline); tokens[idx].attrJoin('data-endline', endline);
@ -16,48 +17,48 @@ function addPart(tokens, idx) {
md.renderer.rules.blockquote_open = function (tokens, idx, options, env, self) { md.renderer.rules.blockquote_open = function (tokens, idx, options, env, self) {
tokens[idx].attrJoin('class', 'raw'); tokens[idx].attrJoin('class', 'raw');
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.table_open = function (tokens, idx, options, env, self) { md.renderer.rules.table_open = function (tokens, idx, options, env, self) {
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.bullet_list_open = function (tokens, idx, options, env, self) { md.renderer.rules.bullet_list_open = function (tokens, idx, options, env, self) {
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.list_item_open = function (tokens, idx, options, env, self) { md.renderer.rules.list_item_open = function (tokens, idx, options, env, self) {
tokens[idx].attrJoin('class', 'raw'); tokens[idx].attrJoin('class', 'raw');
if (tokens[idx].map) { if (tokens[idx].map) {
var startline = tokens[idx].map[0] + 1; const startline = tokens[idx].map[0] + 1;
var endline = tokens[idx].map[1]; const endline = tokens[idx].map[1];
tokens[idx].attrJoin('data-startline', startline); tokens[idx].attrJoin('data-startline', startline);
tokens[idx].attrJoin('data-endline', endline); tokens[idx].attrJoin('data-endline', endline);
} }
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.ordered_list_open = function (tokens, idx, options, env, self) { md.renderer.rules.ordered_list_open = function (tokens, idx, options, env, self) {
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.link_open = function (tokens, idx, options, env, self) { md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.paragraph_open = function (tokens, idx, options, env, self) { md.renderer.rules.paragraph_open = function (tokens, idx, options, env, self) {
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.heading_open = function (tokens, idx, options, env, self) { md.renderer.rules.heading_open = function (tokens, idx, options, env, self) {
tokens[idx].attrJoin('class', 'raw'); tokens[idx].attrJoin('class', 'raw');
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
}; };
md.renderer.rules.fence = function (tokens, idx, options, env, self) { md.renderer.rules.fence = (tokens, idx, options, env, self) => {
var token = tokens[idx], const token = tokens[idx];
info = token.info ? md.utils.unescapeAll(token.info).trim() : '', const info = token.info ? md.utils.unescapeAll(token.info).trim() : '';
langName = '', let langName = '';
highlighted; let highlighted;
if (info) { if (info) {
langName = info.split(/\s+/g)[0]; langName = info.split(/\s+/g)[0];
@ -74,38 +75,33 @@ md.renderer.rules.fence = function (tokens, idx, options, env, self) {
} }
if (highlighted.indexOf('<pre') === 0) { if (highlighted.indexOf('<pre') === 0) {
return highlighted + '\n'; return `${highlighted}\n`;
} }
if (tokens[idx].map && tokens[idx].level === 0) { if (tokens[idx].map && tokens[idx].level === 0) {
var startline = tokens[idx].map[0] + 1; const startline = tokens[idx].map[0] + 1;
var endline = tokens[idx].map[1]; const endline = tokens[idx].map[1];
return '<pre class="part" data-startline="' + startline + '" data-endline="' + endline + '"><code' + self.renderAttrs(token) + '>' return `<pre class="part" data-startline="${startline}" data-endline="${endline}"><code${self.renderAttrs(token)}>${highlighted}</code></pre>\n`;
+ highlighted
+ '</code></pre>\n';
} }
return '<pre><code' + self.renderAttrs(token) + '>' return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\n`;
+ highlighted
+ '</code></pre>\n';
}; };
md.renderer.rules.code_block = function (tokens, idx, options, env, self) { md.renderer.rules.code_block = (tokens, idx, options, env, self) => {
if (tokens[idx].map && tokens[idx].level === 0) { if (tokens[idx].map && tokens[idx].level === 0) {
var startline = tokens[idx].map[0] + 1; const startline = tokens[idx].map[0] + 1;
var endline = tokens[idx].map[1]; const endline = tokens[idx].map[1];
return '<pre class="part" data-startline="' + startline + '" data-endline="' + endline + '"><code>' + md.utils.escapeHtml(tokens[idx].content) + '</code></pre>\n'; return `<pre class="part" data-startline="${startline}" data-endline="${endline}"><code>${md.utils.escapeHtml(tokens[idx].content)}</code></pre>\n`;
} }
return '<pre><code>' + md.utils.escapeHtml(tokens[idx].content) + '</code></pre>\n'; return `<pre><code>${md.utils.escapeHtml(tokens[idx].content)}</code></pre>\n`;
}; };
function renderContainer(tokens, idx, options, env, self) { function renderContainer(tokens, idx, options, env, self) {
tokens[idx].attrJoin('role', 'alert'); tokens[idx].attrJoin('role', 'alert');
tokens[idx].attrJoin('class', 'alert'); tokens[idx].attrJoin('class', 'alert');
tokens[idx].attrJoin('class', 'alert-' + tokens[idx].info.trim()); tokens[idx].attrJoin('class', `alert-${tokens[idx].info.trim()}`);
addPart(tokens, idx); addPart(tokens, idx);
return self.renderToken.apply(self, arguments); return self.renderToken(...arguments);
} }
var markdownitContainer = require('markdown-it-container');
md.use(markdownitContainer, 'success', { render: renderContainer }); md.use(markdownitContainer, 'success', { render: renderContainer });
md.use(markdownitContainer, 'info', { render: renderContainer }); md.use(markdownitContainer, 'info', { render: renderContainer });
md.use(markdownitContainer, 'warning', { render: renderContainer }); md.use(markdownitContainer, 'warning', { render: renderContainer });
@ -117,18 +113,18 @@ window.syncscroll = true;
window.preventSyncScrollToEdit = false; window.preventSyncScrollToEdit = false;
window.preventSyncScrollToView = false; window.preventSyncScrollToView = false;
var editScrollThrottle = 5; const editScrollThrottle = 5;
var viewScrollThrottle = 5; const viewScrollThrottle = 5;
var buildMapThrottle = 100; const buildMapThrottle = 100;
var viewScrolling = false; let viewScrolling = false;
var editScrolling = false; let editScrolling = false;
var editArea = null; let editArea = null;
var viewArea = null; let viewArea = null;
var markdownArea = null; let markdownArea = null;
function setupSyncAreas(edit, view, markdown) { export function setupSyncAreas(edit, view, markdown) {
editArea = edit; editArea = edit;
viewArea = view; viewArea = view;
markdownArea = markdown; markdownArea = markdown;
@ -136,26 +132,24 @@ function setupSyncAreas(edit, view, markdown) {
viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle)); viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle));
} }
var scrollMap, lineHeightMap, viewTop, viewBottom; let scrollMap, lineHeightMap, viewTop, viewBottom;
window.viewAjaxCallback = clearMap; export function clearMap() {
function clearMap() {
scrollMap = null; scrollMap = null;
lineHeightMap = null; lineHeightMap = null;
viewTop = null; viewTop = null;
viewBottom = null; viewBottom = null;
} }
window.viewAjaxCallback = clearMap;
var buildMap = _.throttle(buildMapInner, buildMapThrottle); const buildMap = _.throttle(buildMapInner, buildMapThrottle);
// Build offsets for each line (lines can be wrapped) // Build offsets for each line (lines can be wrapped)
// That's a bit dirty to process each line everytime, but ok for demo. // That's a bit dirty to process each line everytime, but ok for demo.
// Optimizations are required only for big texts. // Optimizations are required only for big texts.
function buildMapInner(callback) { function buildMapInner(callback) {
if (!viewArea || !markdownArea) return; if (!viewArea || !markdownArea) return;
var i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, let i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, acc, _scrollMap;
acc, _scrollMap;
offset = viewArea.scrollTop() - viewArea.offset().top; offset = viewArea.scrollTop() - viewArea.offset().top;
_scrollMap = []; _scrollMap = [];
@ -165,10 +159,10 @@ function buildMapInner(callback) {
viewBottom = viewArea[0].scrollHeight - viewArea.height(); viewBottom = viewArea[0].scrollHeight - viewArea.height();
acc = 0; acc = 0;
var lines = editor.getValue().split('\n'); const lines = editor.getValue().split('\n');
var lineHeight = editor.defaultTextHeight(); const lineHeight = editor.defaultTextHeight();
for (i = 0; i < lines.length; i++) { for (i = 0; i < lines.length; i++) {
var str = lines[i]; const str = lines[i];
_lineHeightMap.push(acc); _lineHeightMap.push(acc);
@ -177,7 +171,7 @@ function buildMapInner(callback) {
continue; continue;
} }
var h = editor.heightAtLine(i + 1) - editor.heightAtLine(i); const h = editor.heightAtLine(i + 1) - editor.heightAtLine(i);
acc += Math.round(h / lineHeight); acc += Math.round(h / lineHeight);
} }
_lineHeightMap.push(acc); _lineHeightMap.push(acc);
@ -191,10 +185,10 @@ function buildMapInner(callback) {
// make the first line go top // make the first line go top
_scrollMap[0] = viewTop; _scrollMap[0] = viewTop;
var parts = markdownArea.find('.part').toArray(); const parts = markdownArea.find('.part').toArray();
for (i = 0; i < parts.length; i++) { for (i = 0; i < parts.length; i++) {
var $el = $(parts[i]), const $el = $(parts[i]);
t = $el.attr('data-startline') - 1; let t = $el.attr('data-startline') - 1;
if (t === '') { if (t === '') {
return; return;
} }
@ -229,9 +223,9 @@ function buildMapInner(callback) {
} }
// sync view scroll progress to edit // sync view scroll progress to edit
var viewScrollingTimer = null; let viewScrollingTimer = null;
function syncScrollToEdit(event, preventAnimate) { export function syncScrollToEdit(event, preventAnimate) {
if (currentMode != modeType.both || !syncscroll || !editArea) return; if (currentMode != modeType.both || !syncscroll || !editArea) return;
if (preventSyncScrollToEdit) { if (preventSyncScrollToEdit) {
if (typeof preventSyncScrollToEdit === 'number') { if (typeof preventSyncScrollToEdit === 'number') {
@ -242,15 +236,15 @@ function syncScrollToEdit(event, preventAnimate) {
return; return;
} }
if (!scrollMap || !lineHeightMap) { if (!scrollMap || !lineHeightMap) {
buildMap(function () { buildMap(() => {
syncScrollToEdit(event, preventAnimate); syncScrollToEdit(event, preventAnimate);
}); });
return; return;
} }
if (editScrolling) return; if (editScrolling) return;
var scrollTop = viewArea[0].scrollTop; const scrollTop = viewArea[0].scrollTop;
var lineIndex = 0; let lineIndex = 0;
for (var i = 0, l = scrollMap.length; i < l; i++) { for (var i = 0, l = scrollMap.length; i < l; i++) {
if (scrollMap[i] > scrollTop) { if (scrollMap[i] > scrollTop) {
break; break;
@ -258,8 +252,8 @@ function syncScrollToEdit(event, preventAnimate) {
lineIndex = i; lineIndex = i;
} }
} }
var lineNo = 0; let lineNo = 0;
var lineDiff = 0; let lineDiff = 0;
for (var i = 0, l = lineHeightMap.length; i < l; i++) { for (var i = 0, l = lineHeightMap.length; i < l; i++) {
if (lineHeightMap[i] > lineIndex) { if (lineHeightMap[i] > lineIndex) {
break; break;
@ -269,14 +263,14 @@ function syncScrollToEdit(event, preventAnimate) {
} }
} }
var posTo = 0; let posTo = 0;
var topDiffPercent = 0; let topDiffPercent = 0;
var posToNextDiff = 0; let posToNextDiff = 0;
var scrollInfo = editor.getScrollInfo(); const scrollInfo = editor.getScrollInfo();
var textHeight = editor.defaultTextHeight(); const textHeight = editor.defaultTextHeight();
var preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight; const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight;
var preLastLineNo = Math.round(preLastLineHeight / textHeight); const preLastLineNo = Math.round(preLastLineHeight / textHeight);
var preLastLinePos = scrollMap[preLastLineNo]; const preLastLinePos = scrollMap[preLastLineNo];
if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) { if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {
posTo = preLastLineHeight; posTo = preLastLineHeight;
@ -293,7 +287,7 @@ function syncScrollToEdit(event, preventAnimate) {
if (preventAnimate) { if (preventAnimate) {
editArea.scrollTop(posTo); editArea.scrollTop(posTo);
} else { } else {
var posDiff = Math.abs(scrollInfo.top - posTo); const posDiff = Math.abs(scrollInfo.top - posTo);
var duration = posDiff / 50; var duration = posDiff / 50;
duration = duration >= 100 ? duration : 100; duration = duration >= 100 ? duration : 100;
editArea.stop(true, true).animate({ editArea.stop(true, true).animate({
@ -311,9 +305,9 @@ function viewScrollingTimeoutInner() {
} }
// sync edit scroll progress to view // sync edit scroll progress to view
var editScrollingTimer = null; let editScrollingTimer = null;
function syncScrollToView(event, preventAnimate) { export function syncScrollToView(event, preventAnimate) {
if (currentMode != modeType.both || !syncscroll || !viewArea) return; if (currentMode != modeType.both || !syncscroll || !viewArea) return;
if (preventSyncScrollToView) { if (preventSyncScrollToView) {
if (typeof preventSyncScrollToView === 'number') { if (typeof preventSyncScrollToView === 'number') {
@ -324,20 +318,20 @@ function syncScrollToView(event, preventAnimate) {
return; return;
} }
if (!scrollMap || !lineHeightMap) { if (!scrollMap || !lineHeightMap) {
buildMap(function () { buildMap(() => {
syncScrollToView(event, preventAnimate); syncScrollToView(event, preventAnimate);
}); });
return; return;
} }
if (viewScrolling) return; if (viewScrolling) return;
var lineNo, posTo; let lineNo, posTo;
var topDiffPercent, posToNextDiff; let topDiffPercent, posToNextDiff;
var scrollInfo = editor.getScrollInfo(); const scrollInfo = editor.getScrollInfo();
var textHeight = editor.defaultTextHeight(); const textHeight = editor.defaultTextHeight();
lineNo = Math.floor(scrollInfo.top / textHeight); lineNo = Math.floor(scrollInfo.top / textHeight);
// if reach the last line, will start lerp to the bottom // if reach the last line, will start lerp to the bottom
var diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight); const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight);
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) { if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
topDiffPercent = diffToBottom / textHeight; topDiffPercent = diffToBottom / textHeight;
posTo = scrollMap[lineNo + 1]; posTo = scrollMap[lineNo + 1];
@ -353,7 +347,7 @@ function syncScrollToView(event, preventAnimate) {
if (preventAnimate) { if (preventAnimate) {
viewArea.scrollTop(posTo); viewArea.scrollTop(posTo);
} else { } else {
var posDiff = Math.abs(viewArea.scrollTop() - posTo); const posDiff = Math.abs(viewArea.scrollTop() - posTo);
var duration = posDiff / 50; var duration = posDiff / 50;
duration = duration >= 100 ? duration : 100; duration = duration >= 100 ? duration : 100;
viewArea.stop(true, true).animate({ viewArea.stop(true, true).animate({
@ -369,10 +363,3 @@ function syncScrollToView(event, preventAnimate) {
function editScrollingTimeoutInner() { function editScrollingTimeoutInner() {
editScrolling = false; editScrolling = false;
} }
module.exports = {
setupSyncAreas: setupSyncAreas,
clearMap: clearMap,
syncScrollToEdit: syncScrollToEdit,
syncScrollToView: syncScrollToView
};

View file

@ -372,6 +372,10 @@ module.exports = {
loaders: [{ loaders: [{
test: /\.json$/, test: /\.json$/,
loader: 'json-loader' loader: 'json-loader'
}, {
test: /\.js$/,
loader: 'babel',
exclude: [/node_modules/, /public\/vendor/]
}, { }, {
test: /\.css$/, test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader') loader: ExtractTextPlugin.extract('style-loader', 'css-loader')