<%- include refresh-modal %>
<%- include signin-modal %>
<%- include help-modal %>
--
cgit v1.3.1
From b734eb9c85fc6b2cfe534206f0f1b01656d9acc3 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Mon, 10 Oct 2016 21:05:49 +0800
Subject: Try to fix memory leaks by clear OT server before disconnect note
---
lib/realtime.js | 3 +++
1 file changed, 3 insertions(+)
(limited to 'lib')
diff --git a/lib/realtime.js b/lib/realtime.js
index 0fcd2eaa..ea3735a6 100644
--- a/lib/realtime.js
+++ b/lib/realtime.js
@@ -543,6 +543,9 @@ function disconnect(socket) {
if (note.server.isDirty) {
updateNote(note, function (err, _note) {
if (err) return logger.error('disconnect note failed: ' + err);
+ // clear server before delete to avoid memory leaks
+ note.server.document = "";
+ note.server.operations = [];
delete note.server;
delete notes[noteId];
if (config.debug) {
--
cgit v1.3.1
From dfc8aeeba07966bc1ea116e20e3b2d0af27f6c47 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Mon, 10 Oct 2016 21:16:58 +0800
Subject: Add more environment variables for server configuration, update
related section in README.md
---
README.md | 33 +++++++++++++++++++++++++--------
lib/config.js | 48 ++++++++++++++++++++++++++++++++++--------------
2 files changed, 59 insertions(+), 22 deletions(-)
(limited to 'lib')
diff --git a/README.md b/README.md
index ea3ab5ad..4db70220 100644
--- a/README.md
+++ b/README.md
@@ -101,10 +101,27 @@ Environment variables (will overwrite other server configs)
| variables | example values | description |
| --------- | ------ | ----------- |
| NODE_ENV | `production` or `development` | set current environment (will apply corresponding settings in the `config.json`) |
-| DOMAIN | `hackmd.io` | domain name |
-| URL_PATH | `hackmd` | sub url path, like `www.example.com/` |
-| PORT | `80` | web app port |
| DEBUG | `true` or `false` | set debug mode, show more logs |
+| HMD_DOMAIN | `hackmd.io` | domain name |
+| HMD_URL_PATH | `hackmd` | sub url path, like `www.example.com/` |
+| HMD_PORT | `80` | web app port |
+| HMD_ALLOW_ORIGIN | `localhost, hackmd.io` | domain name whitelist (use comma to separate) |
+| HMD_PROTOCOL_USESSL | `true` or `false` | set to use ssl protocol for resources path (only applied when domain is set) |
+| HMD_URL_ADDPORT | `true` or `false` | set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set) |
+| HMD_FACEBOOK_CLIENTID | no example | Facebook API client id |
+| HMD_FACEBOOK_CLIENTSECRET | no example | Facebook API client secret |
+| HMD_TWITTER_CONSUMERKEY | no example | Twitter API consumer key |
+| HMD_TWITTER_CONSUMERSECRET | no example | Twitter API consumer secret |
+| HMD_GITHUB_CLIENTID | no example | GitHub API client id |
+| HMD_GITHUB_CLIENTSECRET | no example | GitHub API client secret |
+| HMD_GITLAB_BASEURL | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) |
+| HMD_GITLAB_CLIENTID | no example | GitLab API client id |
+| HMD_GITLAB_CLIENTSECRET | no example | GitLab API client secret |
+| HMD_DROPBOX_CLIENTID | no example | Dropbox API client id |
+| HMD_DROPBOX_CLIENTSECRET | no example | Dropbox API client secret |
+| HMD_GOOGLE_CLIENTID | no example | Google API client id |
+| HMD_GOOGLE_CLIENTSECRET | no example | Google API client secret |
+| HMD_IMGUR_CLIENTID | no example | Imgur API client id |
Server settings `config.json`
---
@@ -117,8 +134,8 @@ Server settings `config.json`
| port | `80` | web app port |
| alloworigin | `['localhost']` | domain name whitelist |
| usessl | `true` or `false` | set to use ssl server (if true will auto turn on `protocolusessl`) |
-| protocolusessl | `true` or `false` | set to use ssl protocol for resources path |
-| urladdport | `true` or `false` | set to add port on callback url (port 80 or 443 won't applied) |
+| protocolusessl | `true` or `false` | set to use ssl protocol for resources path (only applied when domain is set) |
+| urladdport | `true` or `false` | set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set) |
| usecdn | `true` or `false` | set to use CDN resources or not |
| db | `{ "dialect": "sqlite", "storage": "./db.hackmd.sqlite" }` | set the db configs, [see more here](http://sequelize.readthedocs.org/en/latest/api/sequelize/) |
| sslkeypath | `./cert/client.key` | ssl key path (only need when you set usessl) |
@@ -144,10 +161,10 @@ Server settings `config.json`
Third-party integration api key settings
---
-| service | file path | description |
+| service | settings location | description |
| ------- | --------- | ----------- |
-| facebook, twitter, github, gitlab, dropbox, google | `config.json` | for signin |
-| imgur | `config.json` | for image upload |
+| facebook, twitter, github, gitlab, dropbox, google | environment variables or `config.json` | for signin |
+| imgur | environment variables or `config.json` | for image upload |
| google drive, dropbox | `public/js/config.js` | for export and import |
Third-party integration oauth callback urls
diff --git a/lib/config.js b/lib/config.js
index 588128a7..46afea9e 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -7,16 +7,17 @@ var config = require(path.join(__dirname, '..', 'config.json'))[env];
var debug = process.env.DEBUG ? (process.env.DEBUG === 'true') : ((typeof config.debug === 'boolean') ? config.debug : (env === 'development'));
// url
-var domain = process.env.DOMAIN || config.domain || '';
-var urlpath = process.env.URL_PATH || config.urlpath || '';
-var port = process.env.PORT || config.port || 3000;
-var alloworigin = config.alloworigin || ['localhost'];
+var domain = process.env.DOMAIN || process.env.HMD_DOMAIN || config.domain || '';
+var urlpath = process.env.URL_PATH || process.env.HMD_URL_PATH || config.urlpath || '';
+var port = process.env.PORT || process.env.HMD_PORT || config.port || 3000;
+var alloworigin = process.env.HMD_ALLOW_ORIGIN ? process.env.HMD_ALLOW_ORIGIN.split(',') : (config.alloworigin || ['localhost']);
var usessl = !!config.usessl;
-var protocolusessl = (config.usessl === true && typeof config.protocolusessl === 'undefined') ? true : !!config.protocolusessl;
-var urladdport = !!config.urladdport;
+var protocolusessl = (usessl === true && typeof process.env.HMD_PROTOCOL_USESSL === 'undefined' && typeof config.protocolusessl === 'undefined')
+ ? true : (process.env.HMD_PROTOCOL_USESSL ? (process.env.HMD_PROTOCOL_USESSL === 'true') : !!config.protocolusessl);
+var urladdport = process.env.HMD_URL_ADDPORT ? (process.env.HMD_URL_ADDPORT === 'true') : !!config.urladdport;
-var usecdn = !!config.usecdn;
+var usecdn = process.env.HMD_USECDN ? (process.env.HMD_USECDN === 'true') : !!config.usecdn;
// db
var db = config.db || {
@@ -56,13 +57,32 @@ var heartbeattimeout = config.heartbeattimeout || 5000;
var documentmaxlength = config.documentmaxlength || 100000;
// auth
-var facebook = config.facebook || false;
-var twitter = config.twitter || false;
-var github = config.github || false;
-var gitlab = config.gitlab || false;
-var dropbox = config.dropbox || false;
-var google = config.google || false;
-var imgur = config.imgur || false;
+var facebook = (process.env.HMD_FACEBOOK_CLIENTID && process.env.HMD_FACEBOOK_CLIENTSECRET) ? {
+ clientID: process.env.HMD_FACEBOOK_CLIENTID,
+ clientSecret: process.env.HMD_FACEBOOK_CLIENTSECRET
+} : config.facebook || false;
+var twitter = (process.env.HMD_TWITTER_CONSUMERKEY && process.env.HMD_TWITTER_CONSUMERSECRET) ? {
+ consumerKey: process.env.HMD_TWITTER_CONSUMERKEY,
+ consumerSecret: process.env.HMD_TWITTER_CONSUMERSECRET
+} : config.twitter || false;
+var github = (process.env.HMD_GITHUB_CLIENTID && process.env.HMD_GITHUB_CLIENTSECRET) ? {
+ clientID: process.env.HMD_GITHUB_CLIENTID,
+ clientSecret: process.env.HMD_GITHUB_CLIENTSECRET
+} : config.github || false;
+var gitlab = (process.env.HMD_GITLAB_CLIENTID && process.env.HMD_GITLAB_CLIENTSECRET) ? {
+ baseURL: process.env.HMD_GITLAB_BASEURL,
+ clientID: process.env.HMD_GITLAB_CLIENTID,
+ clientSecret: process.env.HMD_GITLAB_CLIENTSECRET
+} : config.gitlab || false;
+var dropbox = (process.env.HMD_DROPBOX_CLIENTID && process.env.HMD_DROPBOX_CLIENTSECRET) ? {
+ clientID: process.env.HMD_DROPBOX_CLIENTID,
+ clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET
+} : config.dropbox || false;
+var google = (process.env.HMD_GOOGLE_CLIENTID && process.env.HMD_GOOGLE_CLIENTSECRET) ? {
+ clientID: process.env.HMD_GOOGLE_CLIENTID,
+ clientSecret: process.env.HMD_GOOGLE_CLIENTSECRET
+} : config.google || false;
+var imgur = process.env.HMD_IMGUR_CLIENTID || config.imgur || false;
function getserverurl() {
var url = '';
--
cgit v1.3.1
From bc74c1f0cb4e146d7944cea37fb1afbe6772fd71 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Tue, 11 Oct 2016 00:55:38 +0800
Subject: Fix doc updating revision not stringify and compress authorship
before save
---
lib/models/note.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'lib')
diff --git a/lib/models/note.js b/lib/models/note.js
index 6efa5d4f..7fdc5645 100644
--- a/lib/models/note.js
+++ b/lib/models/note.js
@@ -142,7 +142,7 @@ module.exports = function (sequelize, DataTypes) {
authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship);
}
note.update({
- authorship: authorship
+ authorship: LZString.compressToBase64(JSON.stringify(authorship))
}).then(function (note) {
return callback(null, note.id);
}).catch(function (err) {
--
cgit v1.3.1
From 510b1254323ad03a2ac21a93a4450d7fb67ab9a8 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Tue, 11 Oct 2016 01:22:08 +0800
Subject: Fix new note with empty content not saving to history and remove
debug code
---
lib/history.js | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
(limited to 'lib')
diff --git a/lib/history.js b/lib/history.js
index 119b7510..c3754e0b 100644
--- a/lib/history.js
+++ b/lib/history.js
@@ -113,8 +113,7 @@ function setHistory(userid, history) {
}
function updateHistory(userid, noteId, document) {
- var t0 = new Date().getTime();
- if (userid && noteId && document) {
+ if (userid && noteId && typeof document !== 'undefined') {
getHistory(userid, function (err, history) {
if (err || !history) return;
if (!caches[userid].history[noteId]) {
@@ -127,8 +126,6 @@ function updateHistory(userid, noteId, document) {
noteHistory.time = moment().format('MMMM Do YYYY, h:mm:ss a');
noteHistory.tags = noteInfo.tags;
caches[userid].isDirty = true;
- var t1 = new Date().getTime();
- console.warn(t1 - t0);
});
}
}
--
cgit v1.3.1
From 9a15cad42de2112c9c433b3199f39aca440f1581 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Tue, 11 Oct 2016 11:01:05 +0800
Subject: Mark as 0.4.5
---
lib/config.js | 4 +--
package.json | 2 +-
public/docs/release-notes.md | 60 ++++++++++++++++++++++++++++++++++++++++++++
public/js/common.js | 2 +-
4 files changed, 64 insertions(+), 4 deletions(-)
(limited to 'lib')
diff --git a/lib/config.js b/lib/config.js
index 46afea9e..63114975 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -97,8 +97,8 @@ function getserverurl() {
return url;
}
-var version = '0.4.4';
-var minimumCompatibleVersion = '0.4.4';
+var version = '0.4.5';
+var minimumCompatibleVersion = '0.4.5';
var maintenance = true;
var cwd = path.join(__dirname, '..');
diff --git a/package.json b/package.json
index 68b3e368..7051affb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hackmd",
- "version": "0.4.4",
+ "version": "0.4.5",
"description": "Realtime collaborative markdown notes on all platforms.",
"main": "app.js",
"license": "MIT",
diff --git a/public/docs/release-notes.md b/public/docs/release-notes.md
index 7067bb7e..afe843e5 100755
--- a/public/docs/release-notes.md
+++ b/public/docs/release-notes.md
@@ -1,6 +1,66 @@
Release Notes
===
+ 0.4.5 `latte` 2016-10-11 01:22
+---
+### Features
++ Add more environment variables for server configuration
++ Add setup script for getting started
++ Add support of deleting note
++ Add support of shortcut keys which can add and remove symbol surround text
++ Add support of shortcut keys for changing mode
++ Add support of i18n (English, Chinese, French, German, Japanese, Spanish, Portuguese, Greek, Italian, Turkish, Russian, Dutch, Croatian, Polish, Ukrainian)
++ Add support of note info API
++ Add support of disqus via yaml-metadata
+
+### Enhancements
+* Optimize png images by using zopflipng
+* Update CodeMirror to 5.19.0 and rename jade to pug
+* Update to add cache to history and improve its performance
+* Update default indent to use spaces instead of tabs
+* Improve syntax highlighting performance
+* Update to make client handle syncing error better, use delay to avoid wrong document revision
+* Update to allow CORS as API on revision actions
+* Update to support showing owner on the infobar
+* Update to prevent duplicate client push in queue to lower down server loading
+* Reduce update view debounce time to make preview refresh quicker
+* Update help modal cheatsheet font styles to make it more clear on spaces
+* Update to add revision saving policy
+* Update to support tiddlywiki and mediawiki syntax highlighting in editor
+* Update to support save mode to url and vise versa
+* Update edit and publish icon and change toggle icon for UX
+* Improve authorship markers update performance
+* Update slide mode to show extra info and support url actions
+* Change the last change user saving strategy
+* Update to support data uri in src attribute of image tag
+* Improve index layout and UX with UI adjustments
+* Update XSS policy to allow iframe and link with custom protocol
+* Update markdown styles to follow github latest layout styles
+* Update slide mode, now respect all meta settings and update default styles
+* Update to make ToC menu always accessible without scrolling
+* Update to make doc only update while filesystem content not match db content
+
+### Fixes
+* Fix README and features document format and grammar issues
+* Fix some potential memory leaks bugs
+* Fix history storage might not fallback correctly
+* Fix to make mathjax expression display in editor correctly (not italic)
+* Fix note title might have unstriped html tags
+* Fix client reconnect should resend last operation
+* Fix a bug when setting both maxAge and expires may cause user can't signin
+* Fix text complete extra tags for blockquote and referrals
+* Fix bug that when window close will make ajax fail and cause cookies set to wrong state
+* Fix markdown render might fall into regex infinite loop
+* Fix syntax error caused by element contain special characters
+* Fix reference error caused by some scripts loading order
+* Fix ToC id naming to avoid possible overlap with user ToC
+* Fix header nav bar rwd detect element should use div tag or it might glitch the layout
+* Fix textcomplete of extra tags for blockquote not match space character in the between
+* Fix text-shadow for text antialiased might cause IE or Edge text cutoff
+
+### Removes
+- Cancel updating history on page unload
+
0.4.4 `mocha` 2016-08-02 17:10
---
### Features
diff --git a/public/js/common.js b/public/js/common.js
index a14e6fc9..047df8af 100644
--- a/public/js/common.js
+++ b/public/js/common.js
@@ -4,7 +4,7 @@ var serverurl = window.location.protocol + '//' + (domain ? domain : window.loca
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.4.4';
+var version = '0.4.5';
var checkAuth = false;
var profile = null;
--
cgit v1.3.1
From c06b2f483898669b224321728321b7a3a8e9e37c Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Tue, 11 Oct 2016 16:46:50 +0800
Subject: Fix history time should save in UNIX timestamp to avoid time offset
issue
---
lib/history.js | 2 +-
public/js/history.js | 13 +++++++------
2 files changed, 8 insertions(+), 7 deletions(-)
(limited to 'lib')
diff --git a/lib/history.js b/lib/history.js
index c3754e0b..4a3bbe1e 100644
--- a/lib/history.js
+++ b/lib/history.js
@@ -123,7 +123,7 @@ function updateHistory(userid, noteId, document) {
var noteInfo = models.Note.parseNoteInfo(document);
noteHistory.id = noteId;
noteHistory.text = noteInfo.title;
- noteHistory.time = moment().format('MMMM Do YYYY, h:mm:ss a');
+ noteHistory.time = moment().valueOf();
noteHistory.tags = noteInfo.tags;
caches[userid].isDirty = true;
});
diff --git a/public/js/history.js b/public/js/history.js
index 9be68104..324a9da2 100644
--- a/public/js/history.js
+++ b/public/js/history.js
@@ -96,8 +96,8 @@ function clearDuplicatedHistory(notehistory) {
var id = notehistory[i].id.replace(/\=+$/, '');
var newId = newnotehistory[j].id.replace(/\=+$/, '');
if (id == newId || notehistory[i].id == newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) {
- var time = moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a');
- var newTime = moment(newnotehistory[j].time, 'MMMM Do YYYY, h:mm:ss a');
+ var 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'));
if(time >= newTime) {
newnotehistory[j] = notehistory[i];
}
@@ -247,7 +247,7 @@ function renderHistory(view) {
return {
id: id,
text: title,
- time: moment().format('MMMM Do YYYY, h:mm:ss a'),
+ time: moment().valueOf(),
tags: tags
};
}
@@ -358,9 +358,10 @@ function parseToHistory(list, notehistory, callback) {
else if (notehistory && notehistory.length > 0) {
for (var i = 0; i < notehistory.length; i++) {
//parse time to timestamp and fromNow
- notehistory[i].timestamp = moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a').valueOf();
- notehistory[i].fromNow = moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a').fromNow();
- notehistory[i].time = moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a').format('llll');
+ var 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].fromNow = timestamp.fromNow();
+ notehistory[i].time = timestamp.format('llll');
if (notehistory[i].id && list.get('id', notehistory[i].id).length == 0)
list.add(notehistory[i]);
}
--
cgit v1.3.1