Merge branch 'develop' into refactor-realtime

Signed-off-by: BoHong Li <raccoon@hackmd.io>

# Conflicts:
#	README.md
#	package.json
This commit is contained in:
BoHong Li 2019-07-30 18:20:09 +08:00
commit c628737411
No known key found for this signature in database
GPG Key ID: 06770355DC9ECD38
19 changed files with 494 additions and 49 deletions

View File

@ -1,8 +1,19 @@
CodiMD
===
[![CodiMD on Gitter][gitter-image]][gitter-url]
[![build status][travis-image]][travis-url]
[![version][github-version-badge]][github-release-page]
[![Gitter][gitter-image]][gitter-url]
[![POEditor][poeditor-image]][poeditor-url]
CodiMD lets you collaborate in real-time with markdown.
Built on [HackMD](https://hackmd.io) source code, CodiMD lets you host and control your team's content with speed and ease.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Table of Contents
- [CodiMD](#codimd)
- [CodiMD - The Open Source HackMD](#codimd---the-open-source-hackmd)
- [Documentation](#documentation)
- [Deployment](#deployment)
@ -15,17 +26,6 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
CodiMD
===
[![CodiMD on Gitter][gitter-image]][gitter-url]
[![build status][travis-image]][travis-url]
[![version][github-version-badge]][github-release-page]
[![POEditor][poeditor-image]][poeditor-url]
CodiMD lets you collaborate in real-time with markdown.
Built on [HackMD](https://hackmd.io) source code, CodiMD lets you host and control your team's content with speed and ease.
## CodiMD - The Open Source HackMD
[HackMD](https://hackmd.io) helps developers write better documents and build active communities with open collaboration.
HackMD is built with one promise - **You own and control all your content**:
@ -47,7 +47,7 @@ If you want to spin up an instance and start using immediately, see [Docker depl
If you want to contribute to the project, start with [manual deployment](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-manual-deployment).
### Configuration
CodiMD is highly customizable. Learn about all configuration options of networking, security, performance, resources, privilege, privacy, image storage, and authentication in [CodiMD Configuration](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-configuration).
CodiMD is highly customizable, learn about all configuration options of networking, security, performance, resources, privilege, privacy, image storage, and authentication in [CodiMD Configuration](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-configuration).
### Upgrading and Migration
Upgrade CodiMD from previous version? See [this guide](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-upgrade)
@ -61,10 +61,10 @@ All contributions are welcome! Even asking a question helps.
| Project | Contribution Types | Contribution Venue |
| ------- | ------------------ | ------------------ |
|**CodiMD**|:couple: Community chat|[Gitter](https://gitter.im/hackmdio/hackmd)|
|**CodiMD**|:couple: Community chat|[Gitter][gitter-url]|
||:bug: Issues, bugs, and feature requests|[Issue tracker](https://github.com/hackmdio/codimd/issues)|
||:books: Improve documentation|[Documentations](https://hackmd.io/c/codimd-documentation)|
||:pencil: Translation|[POEditor](https://poeditor.com/join/project/q0nuPWyztp)|
||:pencil: Translation|[POEditor][poeditor-url]|
||:coffee: Donation|[Buy us coffee](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=KDGS4PREHX6QQ&lc=US&item_name=HackMD&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted)|
|**HackMD**|:question: Issues related to [HackMD](https://hackmd.io/)|[Issue tracker](https://github.com/hackmdio/hackmd-io-issues/issues)|
||:pencil2: Translation|[hackmd-locales](https://github.com/hackmdio/hackmd-locales/tree/master/locales)|
@ -96,8 +96,8 @@ To stay up to date with your installation it's recommended to subscribe the [rel
[gitter-image]: https://img.shields.io/badge/gitter-hackmdio/codimd-blue.svg
[gitter-url]: https://gitter.im/hackmdio/hackmd
[travis-image]: https://travis-ci.com/hackmdio/codimd.svg?branch=develop
[travis-url]: https://travis-ci.org/hackmdio/codimd
[travis-image]: https://travis-ci.com/hackmdio/codimd.svg?branch=master
[travis-url]: https://travis-ci.com/hackmdio/codimd
[github-version-badge]: https://img.shields.io/github/release/hackmdio/codimd.svg
[github-release-page]: https://github.com/hackmdio/codimd/releases
[github-release-feed]: https://github.com/hackmdio/codimd/releases.atom

View File

@ -6,7 +6,7 @@
"Markdown",
"Notes"
],
"website": "https://codimd.org",
"website": "https://github.com/hackmdio/codimd",
"repository": "https://github.com/hackmdio/codimd",
"logo": "https://github.com/hackmdio/codimd/raw/master/public/codimd-icon-1024.png",
"success_url": "/",

View File

@ -56,6 +56,8 @@ module.exports = {
// socket.io
heartbeatInterval: 5000,
heartbeatTimeout: 10000,
// toobusy-js
responseMaxLag: 70,
// document
documentMaxLength: 100000,
// image upload setting, available options are imgur/s3/filesystem/azure

View File

@ -33,6 +33,7 @@ module.exports = {
dbURL: process.env.CMD_DB_URL,
sessionSecret: process.env.CMD_SESSION_SECRET,
sessionLife: toIntegerConfig(process.env.CMD_SESSION_LIFE),
responseMaxLag: toIntegerConfig(process.env.CMD_RESPONSE_MAX_LAG),
imageUploadType: process.env.CMD_IMAGE_UPLOAD_TYPE,
imgur: {
clientID: process.env.CMD_IMGUR_CLIENTID

View File

@ -28,6 +28,7 @@ module.exports = {
dbURL: process.env.HMD_DB_URL,
sessionSecret: process.env.HMD_SESSION_SECRET,
sessionLife: toIntegerConfig(process.env.HMD_SESSION_LIFE),
responseMaxLag: toIntegerConfig(process.env.HMD_RESPONSE_MAX_LAG),
imageUploadType: process.env.HMD_IMAGE_UPLOAD_TYPE,
imgur: {
clientID: process.env.HMD_IMGUR_CLIENTID

View File

@ -2,8 +2,11 @@
const toobusy = require('toobusy-js')
const config = require('../../config')
const response = require('../../response')
toobusy.maxLag(config.responseMaxLag)
module.exports = function (req, res, next) {
if (toobusy()) {
response.errorServiceUnavailable(res)

View File

@ -33,7 +33,7 @@ UserRouter.get('/me', function (req, res) {
return response.errorInternalError(res)
})
} else {
res.send({
res.status(401).send({
status: 'forbidden'
})
}

View File

@ -29,7 +29,7 @@
"test:ci": "npm run-script lint && npm run-script jsonlint && npm run-script coverage:ci"
},
"dependencies": {
"@hackmd/codemirror": "~5.41.2",
"@hackmd/codemirror": "~5.46.2",
"@hackmd/diff-match-patch": "~1.1.1",
"@hackmd/idle-js": "~1.0.1",
"@hackmd/imgur": "~0.4.1",
@ -48,6 +48,7 @@
"bootstrap-validator": "~0.11.8",
"chance": "~1.0.4",
"cheerio": "~0.22.0",
"compression": "~1.7.4",
"connect-flash": "~0.1.1",
"connect-session-sequelize": "~6.0.0",
"cookie": "~0.3.1",
@ -58,7 +59,7 @@
"express": "~4.16.4",
"express-session": "~1.16.1",
"file-saver": "~1.3.3",
"flowchart.js": "~1.6.4",
"flowchart.js": "~1.12.0",
"fork-awesome": "~1.1.3",
"formidable": "~1.2.1",
"gist-embed": "~2.6.0",
@ -94,7 +95,7 @@
"markdown-pdf": "~9.0.0",
"mathjax": "~2.7.0",
"mattermost-redux": "~5.9.0",
"mermaid": "~7.1.0",
"mermaid": "~8.2.3",
"method-override": "~2.3.7",
"minimist": "~1.2.0",
"minio": "~6.0.0",

View File

@ -0,0 +1,144 @@
var ElapsedTimeBar = {
// default value
barColor: 'rgb(200,0,0)',
pausedBarColor: 'rgba(200,0,0,.6)',
isPaused: false,
isFinished: false,
allottedTime: null,
timeProgressBar: null,
startTime: null,
pauseTime: null,
pauseTimeDuration: 0,
/**
* initialize elements
*/
handleReady() {
var config = Reveal.getConfig();
// activate this plugin if config.allottedTime exists.
if (!config.allottedTime) {
console.warn('Failed to start ElapsedTimeBar plugin. "allottedTime" property is required.');
return;
}
// set configurations
this.barColor = config.barColor || this.barColor;
this.pausedBarColor = config.pausedBarColor || this.pausedBarColor;
// calc barHeight from config.barHeight or page-progress container
var barHeight;
var pageProgressContainer = document.querySelector('.progress');
if (config.progressBarHeight) {
barHeight = parseInt(config.progressBarHeight, 10) + 'px';
// override height of page-progress container
pageProgressContainer && (pageProgressContainer.style.height = barHeight);
} else if (config.progress && pageProgressContainer) {
// get height from page-progress container
barHeight = pageProgressContainer.getBoundingClientRect().height + 'px';
} else {
// default
barHeight = '3px';
}
// create container of time-progress
var timeProgressContainer = document.createElement('div');
timeProgressContainer.classList.add('progress');
Object.entries({
display: 'block',
position: 'fixed',
bottom: config.progress ? barHeight : 0,
width: '100%',
height: barHeight
}).forEach(([k, v]) => {
timeProgressContainer.style[k] = v;
});
document.querySelector('.reveal').appendChild(timeProgressContainer);
// create content of time-progress
this.timeProgressBar = document.createElement('div');
Object.entries({
height: '100%',
willChange: 'width'
}).forEach(([k, v]) => {
this.timeProgressBar.style[k] = v;
});
timeProgressContainer.appendChild(this.timeProgressBar);
// start timer
this.start(config.allottedTime);
},
/**
* update repeatedly using requestAnimationFrame.
*/
loop() {
if (this.isPaused) return;
var now = +new Date();
var elapsedTime = now - this.startTime - this.pauseTimeDuration;
if (elapsedTime > this.allottedTime) {
this.timeProgressBar.style.width = '100%';
this.isFinished = true;
} else {
this.timeProgressBar.style.width = elapsedTime / this.allottedTime * 100 + '%';
requestAnimationFrame(this.loop.bind(this));
}
},
/**
* set color of progress bar
*/
setBarColor() {
if (this.isPaused) {
this.timeProgressBar.style.backgroundColor = this.pausedBarColor;
} else {
this.timeProgressBar.style.backgroundColor = this.barColor;
}
},
/**
* start(reset) timer with new allotted time.
* @param {number} allottedTime
* @param {number} [elapsedTime=0]
*/
start(allottedTime, elapsedTime = 0) {
this.isFinished = false;
this.isPaused = false;
this.allottedTime = allottedTime;
this.startTime = +new Date() - elapsedTime;
this.pauseTimeDuration = 0;
this.setBarColor();
this.loop();
},
reset() {
this.start(this.allottedTime);
},
pause() {
if (this.isPaused) return;
this.isPaused = true;
this.pauseTime = +new Date();
this.setBarColor();
},
resume() {
if (!this.isPaused) return;
// add paused time duration
this.isPaused = false;
this.pauseTimeDuration += new Date() - this.pauseTime;
this.pauseTime = null;
this.setBarColor();
this.loop();
}
};
if (Reveal.isReady()) {
ElapsedTimeBar.handleReady();
} else {
Reveal.addEventListener('ready', () => ElapsedTimeBar.handleReady());
}

View File

@ -0,0 +1,283 @@
var RevealSpotlight = window.RevealSpotlight || (function () {
//configs
var spotlightSize;
var toggleOnMouseDown;
var spotlightOnKeyPressAndHold;
var presentingCursor;
var spotlightCursor;
var initialPresentationMode;
var disablingUserSelect;
var fadeInAndOut;
var style;
var lockPointerInsideCanvas;
var getMousePos;
var drawBoard;
var isSpotlightOn = true;
var isCursorOn = true;
var lastMouseMoveEvent;
function onRevealJsReady(event) {
configure();
drawBoard = setupCanvas();
addWindowResizeListener();
addMouseMoveListener();
if (toggleOnMouseDown) {
addMouseToggleSpotlightListener();
}
if (spotlightOnKeyPressAndHold) {
addKeyPressAndHoldSpotlightListener(spotlightOnKeyPressAndHold);
}
setCursor(!initialPresentationMode);
setSpotlight(false);
}
function configure() {
var config = Reveal.getConfig().spotlight || {};
spotlightSize = config.size || 60;
presentingCursor = config.presentingCursor || "none";
spotlightCursor = config.spotlightCursor || "none";
var useAsPointer = config.useAsPointer || false;
var pointerColor = config.pointerColor || 'red';
lockPointerInsideCanvas = config.lockPointerInsideCanvas || false;
if(lockPointerInsideCanvas){
getMousePos = getMousePosByMovement;
} else {
getMousePos = getMousePosByBoundingClientRect;
}
// If using as pointer draw a transparent background and
// the mouse pointer in the specified color or default
var pointerStyle = {
backgroundFillStyle : "rgba(0, 0, 0, 0)",
mouseFillStyle : pointerColor
};
var spotlightStyle = {
backgroundFillStyle : "#000000A8",
mouseFillStyle : "#FFFFFFFF"
};
style = useAsPointer ? pointerStyle : spotlightStyle;
if (config.hasOwnProperty("toggleSpotlightOnMouseDown")) {
toggleOnMouseDown = config.toggleSpotlightOnMouseDown;
} else {
toggleOnMouseDown = true;
}
if (config.hasOwnProperty("initialPresentationMode")) {
initialPresentationMode = config.initialPresentationMode;
} else {
initialPresentationMode = toggleOnMouseDown;
}
if (config.hasOwnProperty("spotlightOnKeyPressAndHold")) {
spotlightOnKeyPressAndHold = config.spotlightOnKeyPressAndHold;
} else {
spotlightOnKeyPressAndHold = false;
}
if (config.hasOwnProperty("disablingUserSelect")) {
disablingUserSelect = config.disablingUserSelect;
} else {
disablingUserSelect = true;
}
if (config.hasOwnProperty("fadeInAndOut")) {
fadeInAndOut = config.fadeInAndOut;
} else {
fadeInAndOut = false;
}
}
function setupCanvas() {
var container = document.createElement('div');
container.id = "spotlight";
container.style.cssText = "position:absolute;top:0;left:0;bottom:0;right:0;z-index:99;";
if (fadeInAndOut) {
container.style.cssText += "transition: " + fadeInAndOut + "ms opacity;";
}
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
container.appendChild(canvas);
document.body.appendChild(container);
container.style.opacity = 0;
container.style['pointer-events'] = 'none';
return {
container,
canvas,
context
}
}
function addWindowResizeListener() {
window.addEventListener('resize', function (e) {
var canvas = drawBoard.canvas;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}, false);
}
function addMouseMoveListener() {
document.body.addEventListener('mousemove', function (e) {
if(isSpotlightOn) {
showSpotlight(e);
}
lastMouseMoveEvent = e;
}, false);
}
function addMouseToggleSpotlightListener() {
window.addEventListener("mousedown", function (e) {
if (!isCursorOn) {
setSpotlight(true, e);
}
}, false);
window.addEventListener("mouseup", function (e) {
if (!isCursorOn) {
setSpotlight(false, e);
}
}, false);
}
function addKeyPressAndHoldSpotlightListener(keyCode) {
window.addEventListener("keydown", function (e) {
if (!isCursorOn && !isSpotlightOn && e.keyCode === keyCode) {
setSpotlight(true, lastMouseMoveEvent);
}
}, false);
window.addEventListener("keyup", function (e) {
if (!isCursorOn && e.keyCode === keyCode) {
setSpotlight(false);
}
}, false);
}
function toggleSpotlight() {
setSpotlight(!isSpotlightOn, lastMouseMoveEvent);
}
function setSpotlight(isOn, mouseEvt) {
isSpotlightOn = isOn;
var container = drawBoard.container;
if (isOn) {
if (lockPointerInsideCanvas && document.pointerLockElement != drawBoard.canvas) {
drawBoard.canvas.requestPointerLock();
}
container.style.opacity = 1;
container.style['pointer-events'] = null;
document.body.style.cursor = spotlightCursor;
if (mouseEvt) {
showSpotlight(mouseEvt);
}
} else {
container.style.opacity = 0;
container.style['pointer-events'] = 'none';
document.body.style.cursor = presentingCursor;
}
}
function togglePresentationMode() {
setCursor(!isCursorOn);
}
function setCursor(isOn) {
isCursorOn = isOn;
if (isOn) {
if (disablingUserSelect) {
document.body.style.userSelect = null;
}
document.body.style.cursor = null;
} else {
if (disablingUserSelect) {
document.body.style.userSelect = "none";
}
document.body.style.cursor = presentingCursor;
}
}
function showSpotlight(mouseEvt) {
var canvas = drawBoard.canvas;
var context = drawBoard.context;
var mousePos = getMousePos(canvas, mouseEvt);
context.clearRect(0, 0, canvas.width, canvas.height);
// Create a canvas mask
var maskCanvas = document.createElement('canvas');
maskCanvas.width = canvas.width;
maskCanvas.height = canvas.height;
var maskCtx = maskCanvas.getContext('2d');
maskCtx.fillStyle = style.backgroundFillStyle;
maskCtx.fillRect(0, 0, maskCanvas.width, maskCanvas.height);
maskCtx.globalCompositeOperation = 'xor';
maskCtx.fillStyle = style.mouseFillStyle;
maskCtx.arc(mousePos.x, mousePos.y, spotlightSize, 0, 2 * Math.PI);
maskCtx.fill();
context.drawImage(maskCanvas, 0, 0);
}
var mX = 0;
var mY = 0;
function getMousePosByMovement(canvas, evt) {
var movementX = evt.movementX || 0;
var movementY = evt.movementY || 0;
mX += movementX;
mY += movementY;
if (mX > canvas.clientWidth) {
mX = canvas.clientWidth;
}
if (mY > canvas.clientHeight) {
mY = canvas.clientHeight;
}
if (mX < 0) {
mX = 0;
}
if (mY < 0) {
mY = 0;
}
return {
x: mX,
y: mY
};
}
function getMousePosByBoundingClientRect(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
Reveal.addEventListener('ready', onRevealJsReady);
this.toggleSpotlight = toggleSpotlight;
this.togglePresentationMode = togglePresentationMode;
return this;
})();

View File

@ -8,7 +8,7 @@ This means that you can write notes with other people on your **desktop**, **tab
You can sign-in via multiple auth providers like **Facebook**, **Twitter**, **GitHub** and many more on the [_homepage_](/).
If you experience any _issues_, feel free to report it on [**GitHub**](https://github.com/hackmdio/codimd/issues).
Or meet us on [**Matrix.org**](https://riot.im/app/#/room/#codimd:matrix.org) for dev-talk and interactive help.
Or meet us on [**Gitter**](https://gitter.im/hackmdio/hackmd) for dev-talk and interactive help.
**Thank you very much!**
Workspace

View File

@ -387,19 +387,14 @@ export function finishView (view) {
var $value = $(value)
const $ele = $(value).closest('pre')
window.mermaid.mermaidAPI.parse($value.text())
window.mermaid.parse($value.text())
$ele.addClass('mermaid')
$ele.html($value.text())
window.mermaid.init(undefined, $ele)
} catch (err) {
var errormessage = err
if (err.str) {
errormessage = err.str
}
$value.unwrap()
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(errormessage)}</div>`)
console.warn(errormessage)
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(err.str)}</div>`)
console.warn(err)
}
})
// abc.js

View File

@ -74,6 +74,21 @@ const defaultOptions = {
const meta = JSON.parse($('#meta').text())
var options = meta.slideOptions || {}
if (options.hasOwnProperty('spotlight')) {
defaultOptions.dependencies.push({
src: `${serverurl}/build/reveal.js/plugin/spotlight/spotlight.js`
})
}
if (options.hasOwnProperty('allottedTime') || options.hasOwnProperty('allottedMinutes')) {
defaultOptions.dependencies.push({
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
})
if (options.hasOwnProperty('allottedMinutes')) {
options.allottedTime = options.allottedMinutes * 60 * 1000
}
}
const view = $('.reveal')
// text language

View File

@ -10,7 +10,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js" integrity="sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js" integrity="sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/7.1.0/mermaid.min.js" integrity="sha256-M3OC0Q6g4/+Q4j73OvnsnA+lMkdAE5KgupRHqTiPbnI=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.2.3/mermaid.min.js" integrity="sha256-4s3fF5e1iWRLtiV7mRev7n17oALqqDHbWrNqF3/r7jU=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/js/emojify.min.js" integrity="sha256-VAB5tAlKBvgaxw8oJ1crWMVbdmBVl4mP/2M8MNRl+4E=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js" integrity="sha256-Cv5v4i4SuYvwRYzIONifZjoc99CkwfncROMSWat1cVA=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js" integrity="sha256-ji09tECORKvr8xB9iCl8DJ8iNMLriDchC1+p+yt1hSs=" crossorigin="anonymous"></script>

View File

@ -151,10 +151,10 @@
<option value="sr">српски</option>
</select>
<p>
<%- __('Powered by %s', '<a href="https://codimd.org">CodiMD</a>') %> | <a href="<%- serverURL %>/s/release-notes" target="_blank" rel="noopener"><%= __('Releases') %></a>| <a href="<%- sourceURL %>" target="_blank" rel="noopener"><%= __('Source Code') %></a><% if(privacyStatement) { %> | <a href="<%- serverURL %>/s/privacy" target="_blank" rel="noopener"><%= __('Privacy') %></a><% } %><% if(termsOfUse) { %> | <a href="<%- serverURL %>/s/terms-of-use" target="_blank" rel="noopener"><%= __('Terms of Use') %></a><% } %>
<%- __('Powered by %s', '<a href="https://github.com/hackmdio/codimd">CodiMD</a>') %> | <a href="<%- serverURL %>/s/release-notes" target="_blank" rel="noopener"><%= __('Releases') %></a>| <a href="<%- sourceURL %>" target="_blank" rel="noopener"><%= __('Source Code') %></a><% if(privacyStatement) { %> | <a href="<%- serverURL %>/s/privacy" target="_blank" rel="noopener"><%= __('Privacy') %></a><% } %><% if(termsOfUse) { %> | <a href="<%- serverURL %>/s/terms-of-use" target="_blank" rel="noopener"><%= __('Terms of Use') %></a><% } %>
</p>
<h6 class="social-foot">
<%- __('Follow us on %s and %s.', '<a href="https://github.com/hackmdio/CodiMD" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub</a>, <a href="https://riot.im/app/#/room/#codimd:matrix.org" target="_blank" rel="noopener"><i class="fa fa-comments"></i> Riot</a>', '<a href="https://translate.codimd.org" target="_blank" rel="noopener"><i class="fa fa-globe"></i> POEditor</a>') %>
<%- __('Follow us on %s and %s.', '<a href="https://github.com/hackmdio/CodiMD" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub</a>, <a href="https://gitter.im/hackmdio/hackmd" target="_blank" rel="noopener"><i class="fa fa-comments"></i> Gitter</a>', '<a href="https://poeditor.com/join/project/q0nuPWyztp" target="_blank" rel="noopener"><i class="fa fa-globe"></i> POEditor</a>') %>
</h6>
</div>
</div>

View File

@ -82,7 +82,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js" integrity="sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js" integrity="sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/7.1.0/mermaid.min.js" integrity="sha256-M3OC0Q6g4/+Q4j73OvnsnA+lMkdAE5KgupRHqTiPbnI=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.2.3/mermaid.min.js" integrity="sha256-4s3fF5e1iWRLtiV7mRev7n17oALqqDHbWrNqF3/r7jU=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/js/emojify.min.js" integrity="sha256-VAB5tAlKBvgaxw8oJ1crWMVbdmBVl4mP/2M8MNRl+4E=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js" integrity="sha256-1O3BtOwnPyyRzOszK6P+gqaRoXHV6JXj8HkjZmPYhCI=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous" defer></script>

View File

@ -17,9 +17,9 @@
<div class="panel-body">
<a href="https://github.com/hackmdio/codimd/issues" target="_blank"><i class="fa fa-tag fa-fw"></i> <%= __('Report an issue') %></a>
<br>
<a href="https://riot.im/app/#/room/#codimd:matrix.org" target="_blank"><i class="fa fa-hashtag fa-fw"></i> <%= __('Meet us on %s', 'Matrix') %></a>
<a href="https://gitter.im/hackmdio/hackmd" target="_blank"><i class="fa fa-hashtag fa-fw"></i> <%= __('Meet us on %s', 'Gitter') %></a>
<br>
<a href="https://translate.codimd.org" target="_blank"><i class="fa fa-language fa-fw"></i> <%= __('Help us translating on %s', 'POEditor') %></a>
<a href="https://poeditor.com/join/project/q0nuPWyztp" target="_blank"><i class="fa fa-language fa-fw"></i> <%= __('Help us translating on %s', 'POEditor') %></a>
</div>
</div>
<div class="panel panel-default">

View File

@ -98,7 +98,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js" integrity="sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js" integrity="sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/7.1.0/mermaid.min.js" integrity="sha256-M3OC0Q6g4/+Q4j73OvnsnA+lMkdAE5KgupRHqTiPbnI=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.2.3/mermaid.min.js" integrity="sha256-4s3fF5e1iWRLtiV7mRev7n17oALqqDHbWrNqF3/r7jU=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/js/emojify.min.js" integrity="sha256-VAB5tAlKBvgaxw8oJ1crWMVbdmBVl4mP/2M8MNRl+4E=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js" integrity="sha256-1O3BtOwnPyyRzOszK6P+gqaRoXHV6JXj8HkjZmPYhCI=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous" defer></script>

View File

@ -207,7 +207,7 @@ module.exports = {
'script-loader!codemirrorInlineAttachment',
'script-loader!ot',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?RevealMarkdown!reveal-markdown',
path.join(__dirname, 'public/js/index.js')
],
@ -255,7 +255,7 @@ module.exports = {
'script-loader!codemirrorInlineAttachment',
'script-loader!ot',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?Viz!viz.js',
'script-loader!abcjs',
'expose-loader?io!socket.io-client',
@ -265,7 +265,7 @@ module.exports = {
pretty: [
'babel-polyfill',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?RevealMarkdown!reveal-markdown',
path.join(__dirname, 'public/js/pretty.js')
],
@ -290,7 +290,7 @@ module.exports = {
'expose-loader?emojify!emojify.js',
'script-loader!gist-embed',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?Viz!viz.js',
'script-loader!abcjs',
'expose-loader?RevealMarkdown!reveal-markdown',
@ -300,7 +300,7 @@ module.exports = {
'babel-polyfill',
'bootstrap-tooltip',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?RevealMarkdown!reveal-markdown',
path.join(__dirname, 'public/js/slide.js')
],
@ -328,7 +328,7 @@ module.exports = {
'expose-loader?emojify!emojify.js',
'script-loader!gist-embed',
'flowchart.js',
'script-loader!js-sequence-diagrams',
'imports-loader?Raphael=raphael!js-sequence-diagrams',
'expose-loader?Viz!viz.js',
'script-loader!abcjs',
'headjs',