mirror of https://github.com/status-im/codimd.git
Merge branch 'develop' into refactor-realtime
Signed-off-by: BoHong Li <raccoon@hackmd.io> # Conflicts: # README.md # package.json
This commit is contained in:
commit
c628737411
44
README.md
44
README.md
|
@ -1,31 +1,31 @@
|
|||
<!-- 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)
|
||||
- [Configuration](#configuration)
|
||||
- [Upgrading and Migration](#upgrading-and-migration)
|
||||
- [Developer](#developer)
|
||||
- [Contribution and Discussion](#contribution-and-discussion)
|
||||
- [Browser Support](#browser-support)
|
||||
- [License](#license)
|
||||
|
||||
<!-- 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]
|
||||
[![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 - The Open Source HackMD](#codimd---the-open-source-hackmd)
|
||||
- [Documentation](#documentation)
|
||||
- [Deployment](#deployment)
|
||||
- [Configuration](#configuration)
|
||||
- [Upgrading and Migration](#upgrading-and-migration)
|
||||
- [Developer](#developer)
|
||||
- [Contribution and Discussion](#contribution-and-discussion)
|
||||
- [Browser Support](#browser-support)
|
||||
- [License](#license)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## 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¤cy_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
|
||||
|
|
2
app.json
2
app.json
|
@ -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": "/",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -33,7 +33,7 @@ UserRouter.get('/me', function (req, res) {
|
|||
return response.errorInternalError(res)
|
||||
})
|
||||
} else {
|
||||
res.send({
|
||||
res.status(401).send({
|
||||
status: 'forbidden'
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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;
|
||||
})();
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue