Merge remote-tracking branch 'upstream/master' into DepauMD
|
@ -17,3 +17,9 @@ trim_trailing_whitespace = false
|
||||||
[{.travis.yml,npm-shrinkwrap.json,package.json}]
|
[{.travis.yml,npm-shrinkwrap.json,package.json}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[locales/*.json]
|
||||||
|
# this is the exact style poeditor.com exports, so this should prevent churn.
|
||||||
|
insert_final_newline = false
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
1
.gitignore
vendored
|
@ -8,7 +8,6 @@ composer.lock
|
||||||
.idea/
|
.idea/
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
hackmd_io
|
|
||||||
newrelic_agent.log
|
newrelic_agent.log
|
||||||
logs/
|
logs/
|
||||||
tmp/
|
tmp/
|
||||||
|
|
|
@ -30,13 +30,6 @@ jobs:
|
||||||
script:
|
script:
|
||||||
- shellcheck bin/heroku bin/setup
|
- shellcheck bin/heroku bin/setup
|
||||||
language: generic
|
language: generic
|
||||||
- env: task=doctoc
|
|
||||||
install: npm install doctoc
|
|
||||||
script:
|
|
||||||
- cp README.md README.md.orig
|
|
||||||
- npm run doctoc
|
|
||||||
- diff -q README.md README.md.orig
|
|
||||||
language: generic
|
|
||||||
- env: task=json-lint
|
- env: task=json-lint
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
|
|
7
CHANGELOG.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
Please refer to the release notes published under
|
||||||
|
[`public/docs/release-notes.md`](public/docs/release-notes.md).
|
||||||
|
|
||||||
|
These are also available on each CodiMD instance under
|
||||||
|
https://[domain-name]/release-notes
|
37
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
Contributor Code of Conduct
|
||||||
|
===
|
||||||
|
|
||||||
|
As contributors and maintainers of this project, and in the interest of fostering an open and
|
||||||
|
welcoming community, we pledge to respect all people who contribute through reporting issues,
|
||||||
|
posting feature requests, updating documentation, submitting pull requests or patches, and other
|
||||||
|
activities.
|
||||||
|
|
||||||
|
We are committed to making participation in this project a harassment-free experience for everyone,
|
||||||
|
regardless of level of experience, gender, gender identity and expression, sexual orientation,
|
||||||
|
disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery
|
||||||
|
* Personal attacks
|
||||||
|
* Trolling or insulting/derogatory comments
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing other's private information, such as physical or electronic addresses, without explicit
|
||||||
|
permission
|
||||||
|
* Other unethical or unprofessional conduct.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits,
|
||||||
|
code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By
|
||||||
|
adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently
|
||||||
|
applying these principles to every aspect of managing this project. Project maintainers who do not
|
||||||
|
follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||||
|
|
||||||
|
This code of conduct applies both within project spaces and in public spaces when an individual is
|
||||||
|
representing the project or its community.
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an
|
||||||
|
issue or contacting one or more of the project maintainers.
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org),
|
||||||
|
version 1.2.0, available at
|
||||||
|
[http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
|
@ -3,7 +3,8 @@
|
||||||
When contributing to this repository, please first discuss the change you wish to make via issue,
|
When contributing to this repository, please first discuss the change you wish to make via issue,
|
||||||
email, or any other method with the owners of this repository before making a change.
|
email, or any other method with the owners of this repository before making a change.
|
||||||
|
|
||||||
Please note we have a code of conduct, please follow it in all your interactions with the project.
|
Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your
|
||||||
|
interactions with the project.
|
||||||
|
|
||||||
## Pull Request Process
|
## Pull Request Process
|
||||||
1. Ensure you signed all your commits with Developer Certificate of Origin (DCO).
|
1. Ensure you signed all your commits with Developer Certificate of Origin (DCO).
|
||||||
|
@ -16,44 +17,7 @@ Please note we have a code of conduct, please follow it in all your interactions
|
||||||
5. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
|
5. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
|
||||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||||
|
|
||||||
## Contributor Code of Conduct
|
## Sign your work
|
||||||
|
|
||||||
As contributors and maintainers of this project, and in the interest of fostering an open and
|
|
||||||
welcoming community, we pledge to respect all people who contribute through reporting issues,
|
|
||||||
posting feature requests, updating documentation, submitting pull requests or patches, and other
|
|
||||||
activities.
|
|
||||||
|
|
||||||
We are committed to making participation in this project a harassment-free experience for everyone,
|
|
||||||
regardless of level of experience, gender, gender identity and expression, sexual orientation,
|
|
||||||
disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery
|
|
||||||
* Personal attacks
|
|
||||||
* Trolling or insulting/derogatory comments
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing other's private information, such as physical or electronic addresses, without explicit
|
|
||||||
permission
|
|
||||||
* Other unethical or unprofessional conduct.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits,
|
|
||||||
code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By
|
|
||||||
adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently
|
|
||||||
applying these principles to every aspect of managing this project. Project maintainers who do not
|
|
||||||
follow or enforce the Code of Conduct may be permanently removed from the project team.
|
|
||||||
|
|
||||||
This code of conduct applies both within project spaces and in public spaces when an individual is
|
|
||||||
representing the project or its community.
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an
|
|
||||||
issue or contacting one or more of the project maintainers.
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org),
|
|
||||||
version 1.2.0, available at
|
|
||||||
[http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
|
||||||
|
|
||||||
### Sign your work
|
|
||||||
|
|
||||||
We use the Developer Certificate of Origin (DCO) as a additional safeguard
|
We use the Developer Certificate of Origin (DCO) as a additional safeguard
|
||||||
for the CodiMD project. This is a well established and widely used
|
for the CodiMD project. This is a well established and widely used
|
||||||
|
|
11
LICENSE
|
@ -629,8 +629,15 @@ to attach them to the start of each source file to most effectively
|
||||||
state the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
CodiMD - Realtime collaborative markdown notes on all platforms.
|
||||||
Copyright (C) <year> <name of author>
|
Copyright (C) 2019 Christoph (Sheogorath) Kern
|
||||||
|
Copyright (C) 2019 Claudius Coenen
|
||||||
|
Copyright (C) 2019 Max Wu
|
||||||
|
Copyright (C) 2017 Yukai Huang
|
||||||
|
And more can be found on https://github.com/codimd/server/graphs/contributors
|
||||||
|
Or in the local AUTHORS file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
|
399
README.md
|
@ -1,52 +1,70 @@
|
||||||
CodiMD
|
CodiMD
|
||||||
===
|
===
|
||||||
|
|
||||||
[![CodiMD on Gitter][gitter-image]][gitter-url]
|
[![#CodiMD on matrix.org][matrix.org-image]][matrix.org-url]
|
||||||
[![build status][travis-image]][travis-url]
|
[![build status][travis-image]][travis-url]
|
||||||
[![version][github-version-badge]][github-release-page]
|
[![version][github-version-badge]][github-release-page]
|
||||||
[![POEditor][poeditor-image]][poeditor-url]
|
[![POEditor][poeditor-image]][poeditor-url]
|
||||||
|
|
||||||
CodiMD lets you create real-time collaborative markdown notes on all platforms.
|
CodiMD lets you create real-time collaborative markdown notes. You can test-drive
|
||||||
Inspired by Hackpad, with more focus on speed and flexibility, and build from [HackMD](https://hackmd.io) source code.
|
it by visiting our [CodiMD demo server][codimd-demo].
|
||||||
Feel free to contribute.
|
|
||||||
|
|
||||||
Thanks for using! :smile:
|
It is inspired by Hackpad, Etherpad and similar collaborative editors. This
|
||||||
|
project originated with the team at [HackMD](https://hackmd.io) and now forked
|
||||||
|
into its own organisation. [A longer writeup can be read in the history doc](docs/history.md).
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
[![CodiMD 1.3.2 with its feature demonstration page open](docs/images/CodiMD-1.3.2-features.png)][codimd-demo-features]
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
||||||
# Table of Contents
|
|
||||||
|
|
||||||
- [HackMD CE became CodiMD](#hackmd-ce-became-codimd)
|
|
||||||
- [Browsers Requirement](#browsers-requirement)
|
|
||||||
- [Installation](#installation)
|
|
||||||
- [Getting started (Native install)](#getting-started-native-install)
|
|
||||||
- [Prerequisite](#prerequisite)
|
|
||||||
- [Instructions](#instructions)
|
|
||||||
- [Heroku Deployment](#heroku-deployment)
|
|
||||||
- [Kubernetes](#kubernetes)
|
|
||||||
- [Upgrade](#upgrade)
|
|
||||||
- [Native setup](#native-setup)
|
|
||||||
- [Configuration](#configuration)
|
|
||||||
- [Environment variables (will overwrite other server configs)](#environment-variables-will-overwrite-other-server-configs)
|
|
||||||
- [Application settings `config.json`](#application-settings-configjson)
|
|
||||||
- [Third-party integration API key settings](#third-party-integration-api-key-settings)
|
|
||||||
- [Third-party integration OAuth callback URLs](#third-party-integration-oauth-callback-urls)
|
|
||||||
- [Developer Notes](#developer-notes)
|
|
||||||
- [Structure](#structure)
|
|
||||||
- [Operational Transformation](#operational-transformation)
|
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
## Community and Contributions
|
||||||
|
|
||||||
# HackMD CE became CodiMD
|
We welcome contributions! There's a lot to do: If you would like to report bugs,
|
||||||
|
the [issue tracker][github-issue-tracker] is the right place. If you can help
|
||||||
|
translating, find us on [POEditor][poeditor-url]. To get started developing,
|
||||||
|
take a look at the [docs/dev](docs/dev) directory. In any case: come talk to us,
|
||||||
|
we'll be delighted to help you with the first steps.
|
||||||
|
|
||||||
CodiMD was recently renamed from its former name was HackMD. CodiMD is the free software version of HackMD. HackMD EE, which is a SaaS (Software as a Service) product available at [hackmd.io](https://hackmd.io).
|
To stay up to date with our work or get support it's recommended to join our
|
||||||
|
[Matrix channel][matrix.org-url], stop by our [community forums][codimd-community]
|
||||||
|
or subscribe to the [release feed][github-release-feed]. We also engage in
|
||||||
|
regular [community calls][codimd-community-calls] ([RSS](https://community.codimd.org/t/codimd-community-call/19.rss)) which you are very welcome to join.
|
||||||
|
|
||||||
We decided to change the name to break the confusion between HackMD and CodiMD, formally known as HackMD CE, as it never was an open core project.
|
|
||||||
|
|
||||||
*For the whole renaming story, see the [related issue](https://github.com/hackmdio/hackmd/issues/720)*
|
## Installation / Upgrading
|
||||||
|
|
||||||
# Browsers Requirement
|
You can run CodiMD in a number of ways, and we created setup instructions for
|
||||||
|
all of these:
|
||||||
|
|
||||||
|
* [Docker](docs/setup/docker.md)
|
||||||
|
* [Kubernetes](docs/setup/kubernetes.md)
|
||||||
|
* [Cloudron](docs/setup/cloudron.md)
|
||||||
|
* [Heroku](docs/setup/heroku.md)
|
||||||
|
* [manual setup](docs/setup/manual-setup.md)
|
||||||
|
|
||||||
|
If you do not wish to run your own setup, you can find a commercial offering at
|
||||||
|
https://hackmd.io. This is not the same codebase as this one, but it is a very
|
||||||
|
similar project.
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Theres two main ways to configure your CodiMD instance:
|
||||||
|
[Config file](docs/configuration-config-file.md) or
|
||||||
|
[environment variables](docs/configuration-env-vars.md). You can choose what
|
||||||
|
works best for you.
|
||||||
|
|
||||||
|
CodiMD can integrate with
|
||||||
|
|
||||||
|
* facebook, twitter, github, gitlab, mattermost, dropbox, google, ldap, saml and [oauth2](docs/guides/auth/oauth.md) **for login**
|
||||||
|
* imgur, s3, minio, azure **for image/attachment storage** (files can also be local!)
|
||||||
|
* dropbox **for export and import**
|
||||||
|
|
||||||
|
More info about that can be found in the configuration docs above.
|
||||||
|
|
||||||
|
|
||||||
|
## Browser support
|
||||||
|
|
||||||
|
To use CodiMD, your browser should match or exceed these versions:
|
||||||
|
|
||||||
- ![Chrome](http://browserbadge.com/chrome/47/18px) Chrome >= 47, Chrome for Android >= 47
|
- ![Chrome](http://browserbadge.com/chrome/47/18px) Chrome >= 47, Chrome for Android >= 47
|
||||||
- ![Safari](http://browserbadge.com/safari/9/18px) Safari >= 9, iOS Safari >= 8.4
|
- ![Safari](http://browserbadge.com/safari/9/18px) Safari >= 9, iOS Safari >= 8.4
|
||||||
|
@ -55,309 +73,28 @@ We decided to change the name to break the confusion between HackMD and CodiMD,
|
||||||
- ![Opera](http://browserbadge.com/opera/34/18px) Opera >= 34, Opera Mini not supported
|
- ![Opera](http://browserbadge.com/opera/34/18px) Opera >= 34, Opera Mini not supported
|
||||||
- Android Browser >= 4.4
|
- Android Browser >= 4.4
|
||||||
|
|
||||||
# Installation
|
|
||||||
|
|
||||||
## Getting started (Native install)
|
## Related Tools
|
||||||
|
|
||||||
### Prerequisite
|
|
||||||
|
|
||||||
- Node.js 6.x or up (test up to 7.5.0) and <10.x
|
|
||||||
- Database (PostgreSQL, MySQL, MariaDB, SQLite, MSSQL) use charset `utf8`
|
|
||||||
- npm (and its dependencies, especially [uWebSockets](https://github.com/uWebSockets/uWebSockets#nodejs-developers), [node-gyp](https://github.com/nodejs/node-gyp#installation))
|
|
||||||
- `libssl-dev` for building scrypt (see [here](https://github.com/ml1nk/node-scrypt/blob/master/README.md#installation-instructions) for further information)
|
|
||||||
- For **building** CodiMD we recommend to use a machine with at least **2GB** RAM
|
|
||||||
|
|
||||||
### Instructions
|
|
||||||
|
|
||||||
1. Download a release and unzip or clone into a directory
|
|
||||||
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
|
|
||||||
4. Setup environment variables which will overwrite the configs
|
|
||||||
5. Build front-end bundle by `npm run build` (use `npm run dev` if you are in development)
|
|
||||||
6. Modify the file named `.sequelizerc`, change the value of the variable `url` with your db connection string
|
|
||||||
For example: `postgres://username:password@localhost:5432/codimd`
|
|
||||||
7. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema
|
|
||||||
8. Run the server as you like (node, forever, pm2)
|
|
||||||
|
|
||||||
To stay up to date with your installation it's recommended to subscribe the [release feed][github-release-feed].
|
|
||||||
|
|
||||||
## Heroku Deployment
|
|
||||||
|
|
||||||
You can quickly setup a sample Heroku CodiMD application by clicking the button below.
|
|
||||||
|
|
||||||
[![Deploy on Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hackmdio/codimd/tree/master)
|
|
||||||
|
|
||||||
If you deploy it without the button, keep in mind to use the right buildpacks. For details check `app.json`.
|
|
||||||
|
|
||||||
## Kubernetes
|
|
||||||
|
|
||||||
To install use `helm install stable/hackmd`.
|
|
||||||
|
|
||||||
For all further details, please check out the offical CodiMD [K8s helm chart](https://github.com/kubernetes/charts/tree/master/stable/hackmd).
|
|
||||||
|
|
||||||
**Debian-based version:**
|
|
||||||
|
|
||||||
[![latest](https://images.microbadger.com/badges/version/hackmdio/hackmd:latest.svg)](https://microbadger.com/images/hackmdio/hackmd "Get your own version badge on microbadger.com") [![](https://images.microbadger.com/badges/image/hackmdio/hackmd:latest.svg)](https://microbadger.com/images/hackmdio/hackmd "Get your own image badge on microbadger.com")
|
|
||||||
|
|
||||||
The easiest way to setup CodiMD using docker are using the following three commands:
|
|
||||||
|
|
||||||
```console
|
|
||||||
git clone https://github.com/hackmdio/docker-hackmd.git
|
|
||||||
cd docker-hackmd
|
|
||||||
docker-compose up
|
|
||||||
```
|
|
||||||
Read more about it in the [container repository…](https://github.com/hackmdio/docker-hackmd)
|
|
||||||
|
|
||||||
# Upgrade
|
|
||||||
|
|
||||||
## Native setup
|
|
||||||
|
|
||||||
If you are upgrading CodiMD from an older version, follow these steps:
|
|
||||||
|
|
||||||
1. Fully stop your old server first (important)
|
|
||||||
2. `git pull` or do whatever that updates the files
|
|
||||||
3. `npm install` to update dependencies
|
|
||||||
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
|
|
||||||
For example: `postgres://username:password@localhost:5432/codimd`
|
|
||||||
6. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema
|
|
||||||
7. Start your whole new server!
|
|
||||||
|
|
||||||
To stay up to date with your installation it's recommended to subscribe the [release feed][github-release-feed].
|
|
||||||
|
|
||||||
* **migrate-to-1.1.0**
|
|
||||||
|
|
||||||
We deprecated the older lower case config style and moved on to camel case style. Please have a look at the current `config.json.example` and check the warnings on startup.
|
|
||||||
|
|
||||||
*Notice: This is not a breaking change right now but in the future*
|
|
||||||
|
|
||||||
* [**migration-to-0.5.0**](https://github.com/hackmdio/migration-to-0.5.0)
|
|
||||||
|
|
||||||
We don't use LZString to compress socket.io data and DB data after version 0.5.0.
|
|
||||||
Please run the migration tool if you're upgrading from the old version.
|
|
||||||
|
|
||||||
* [**migration-to-0.4.0**](https://github.com/hackmdio/migration-to-0.4.0)
|
|
||||||
|
|
||||||
We've dropped MongoDB after version 0.4.0.
|
|
||||||
So here is the migration tool for you to transfer the old DB data to the new DB.
|
|
||||||
This tool is also used for official service.
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
|
|
||||||
There are some config settings you need to change in the files below.
|
|
||||||
|
|
||||||
```
|
|
||||||
./config.json ----application settings
|
|
||||||
```
|
|
||||||
|
|
||||||
## 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`) |
|
|
||||||
| `DEBUG` | `true` or `false` | set debug mode; show more logs |
|
|
||||||
| `CMD_CONFIG_FILE` | `/path/to/config.json` | optional override for the path to CodiMD's config file |
|
|
||||||
| `CMD_DOMAIN` | `codimd.org` | domain name |
|
|
||||||
| `CMD_URL_PATH` | `codimd` | sub URL path, like `www.example.com/<URL_PATH>` |
|
|
||||||
| `CMD_HOST` | `localhost` | host to listen on |
|
|
||||||
| `CMD_PORT` | `80` | web app port |
|
|
||||||
| `CMD_PATH` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `CMD_HOST` and `CMD_PORT` are ignored) |
|
|
||||||
| `CMD_LOGLEVEL` | `info` | Defines what kind of logs are provided to stdout. |
|
|
||||||
| `CMD_ALLOW_ORIGIN` | `localhost, codimd.org` | domain name whitelist (use comma to separate) |
|
|
||||||
| `CMD_PROTOCOL_USESSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) |
|
|
||||||
| `CMD_URL_ADDPORT` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) |
|
|
||||||
| `CMD_USECDN` | `true` or `false` | set to use CDN resources or not (default is `true`) |
|
|
||||||
| `CMD_ALLOW_ANONYMOUS` | `true` or `false` | set to allow anonymous usage (default is `true`) |
|
|
||||||
| `CMD_ALLOW_ANONYMOUS_EDITS` | `true` or `false` | if `allowAnonymous` is `true`, allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`) |
|
|
||||||
| `CMD_ALLOW_FREEURL` | `true` or `false` | set to allow new note creation by accessing a nonexistent note URL |
|
|
||||||
| `CMD_FORBIDDEN_NODE_IDS` | `'robots.txt'` | disallow creation of notes, even if `CMD_ALLOW_FREEURL` is `true` |
|
|
||||||
| `CMD_DEFAULT_PERMISSION` | `freely`, `editable`, `limited`, `locked` or `private` | set notes default permission (only applied on signed users) |
|
|
||||||
| `CMD_DB_URL` | `mysql://localhost:3306/database` | set the database URL |
|
|
||||||
| `CMD_SESSION_SECRET` | no example | Secret used to sign the session cookie. If non is set, one will randomly generated on startup |
|
|
||||||
| `CMD_SESSION_LIFE` | `1209600000` | Session life time. (milliseconds) |
|
|
||||||
| `CMD_FACEBOOK_CLIENTID` | no example | Facebook API client id |
|
|
||||||
| `CMD_FACEBOOK_CLIENTSECRET` | no example | Facebook API client secret |
|
|
||||||
| `CMD_TWITTER_CONSUMERKEY` | no example | Twitter API consumer key |
|
|
||||||
| `CMD_TWITTER_CONSUMERSECRET` | no example | Twitter API consumer secret |
|
|
||||||
| `CMD_GITHUB_CLIENTID` | no example | GitHub API client id |
|
|
||||||
| `CMD_GITHUB_CLIENTSECRET` | no example | GitHub API client secret |
|
|
||||||
| `CMD_GITLAB_SCOPE` | `read_user` or `api` | GitLab API requested scope (default is `api`) (GitLab snippet import/export need `api` scope) |
|
|
||||||
| `CMD_GITLAB_BASEURL` | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) |
|
|
||||||
| `CMD_GITLAB_CLIENTID` | no example | GitLab API client id |
|
|
||||||
| `CMD_GITLAB_CLIENTSECRET` | no example | GitLab API client secret |
|
|
||||||
| `CMD_GITLAB_VERSION` | no example | GitLab API version (v3 or v4) |
|
|
||||||
| `CMD_MATTERMOST_BASEURL` | no example | Mattermost authentication endpoint for versions below 5.0. For Mattermost version 5.0 and above, see [guide](docs/guides/auth/mattermost-self-hosted.md). |
|
|
||||||
| `CMD_MATTERMOST_CLIENTID` | no example | Mattermost API client id |
|
|
||||||
| `CMD_MATTERMOST_CLIENTSECRET` | no example | Mattermost API client secret |
|
|
||||||
| `CMD_DROPBOX_CLIENTID` | no example | Dropbox API client id |
|
|
||||||
| `CMD_DROPBOX_CLIENTSECRET` | no example | Dropbox API client secret |
|
|
||||||
| `CMD_GOOGLE_CLIENTID` | no example | Google API client id |
|
|
||||||
| `CMD_GOOGLE_CLIENTSECRET` | no example | Google API client secret |
|
|
||||||
| `CMD_LDAP_URL` | `ldap://example.com` | URL of LDAP server |
|
|
||||||
| `CMD_LDAP_BINDDN` | no example | bindDn for LDAP access |
|
|
||||||
| `CMD_LDAP_BINDCREDENTIALS` | no example | bindCredentials for LDAP access |
|
|
||||||
| `CMD_LDAP_SEARCHBASE` | `o=users,dc=example,dc=com` | LDAP directory to begin search from |
|
|
||||||
| `CMD_LDAP_SEARCHFILTER` | `(uid={{username}})` | LDAP filter to search with |
|
|
||||||
| `CMD_LDAP_SEARCHATTRIBUTES` | `displayName, mail` | LDAP attributes to search with (use comma to separate) |
|
|
||||||
| `CMD_LDAP_USERIDFIELD` | `uidNumber` or `uid` or `sAMAccountName` | The LDAP field which is used uniquely identify a user on CodiMD |
|
|
||||||
| `CMD_LDAP_USERNAMEFIELD` | Fallback to userid | The LDAP field which is used as the username on CodiMD |
|
|
||||||
| `CMD_LDAP_TLS_CA` | `server-cert.pem, root.pem` | Root CA for LDAP TLS in PEM format (use comma to separate) |
|
|
||||||
| `CMD_LDAP_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the LDAP provider |
|
|
||||||
| `CMD_SAML_IDPSSOURL` | `https://idp.example.com/sso` | authentication endpoint of IdP. for details, see [guide](docs/guides/auth/saml-onelogin.md). |
|
|
||||||
| `CMD_SAML_IDPCERT` | `/path/to/cert.pem` | certificate file path of IdP in PEM format |
|
|
||||||
| `CMD_SAML_ISSUER` | no example | identity of the service provider (optional, default: serverurl)" |
|
|
||||||
| `CMD_SAML_IDENTIFIERFORMAT` | no example | name identifier format (optional, default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`) |
|
|
||||||
| `CMD_SAML_GROUPATTRIBUTE` | `memberOf` | attribute name for group list (optional) |
|
|
||||||
| `CMD_SAML_REQUIREDGROUPS` | `Hackmd-users` | group names that allowed (use vertical bar to separate) (optional) |
|
|
||||||
| `CMD_SAML_EXTERNALGROUPS` | `Temporary-staff` | group names that not allowed (use vertical bar to separate) (optional) |
|
|
||||||
| `CMD_SAML_ATTRIBUTE_ID` | `sAMAccountName` | attribute map for `id` (optional, default: NameID of SAML response) |
|
|
||||||
| `CMD_SAML_ATTRIBUTE_USERNAME` | `mailNickname` | attribute map for `username` (optional, default: NameID of SAML response) |
|
|
||||||
| `CMD_SAML_ATTRIBUTE_EMAIL` | `mail` | attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) |
|
|
||||||
| `CMD_OAUTH2_USER_PROFILE_URL` | `https://example.com` | where retrieve information about a user after succesful login. Needs to output JSON. (no default value) Refer to the [Mattermost](docs/guides/auth/mattermost-self-hosted.md) or [Nextcloud](docs/guides/auth/nextcloud.md) examples for more details on all of the `CMD_OAUTH2...` options. |
|
|
||||||
| `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | `name` | where to find the username in the JSON from the user profile URL. (no default value)|
|
|
||||||
| `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | `display-name` | where to find the display-name in the JSON from the user profile URL. (no default value) |
|
|
||||||
| `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | `email` | where to find the email address in the JSON from the user profile URL. (no default value) |
|
|
||||||
| `CMD_OAUTH2_TOKEN_URL` | `https://example.com` | sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) |
|
|
||||||
| `CMD_OAUTH2_AUTHORIZATION_URL` | `https://example.com` | authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) |
|
|
||||||
| `CMD_OAUTH2_CLIENT_ID` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) |
|
|
||||||
| `CMD_OAUTH2_CLIENT_SECRET` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) |
|
|
||||||
| `CMD_OAUTH2_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the oAuth2 provider |
|
|
||||||
| `CMD_IMGUR_CLIENTID` | no example | Imgur API client id |
|
|
||||||
| `CMD_EMAIL` | `true` or `false` | set to allow email signin |
|
|
||||||
| `CMD_ALLOW_PDF_EXPORT` | `true` or `false` | Enable or disable PDF exports |
|
|
||||||
| `CMD_ALLOW_EMAIL_REGISTER` | `true` or `false` | set to allow email register (only applied when email is set, default is `true`. Note `bin/manage_users` might help you if registration is `false`.) |
|
|
||||||
| `CMD_ALLOW_GRAVATAR` | `true` or `false` | set to `false` to disable gravatar as profile picture source on your instance |
|
|
||||||
| `CMD_IMAGE_UPLOAD_TYPE` | `imgur`, `s3`, `minio` or `filesystem` | Where to upload images. For S3, see our Image Upload Guides for [S3](docs/guides/s3-image-upload.md) or [Minio](docs/guides/minio-image-upload.md) |
|
|
||||||
| `CMD_S3_ACCESS_KEY_ID` | no example | AWS access key id |
|
|
||||||
| `CMD_S3_SECRET_ACCESS_KEY` | no example | AWS secret key |
|
|
||||||
| `CMD_S3_REGION` | `ap-northeast-1` | AWS S3 region |
|
|
||||||
| `CMD_S3_BUCKET` | no example | AWS S3 bucket name |
|
|
||||||
| `CMD_MINIO_ACCESS_KEY` | no example | Minio access key |
|
|
||||||
| `CMD_MINIO_SECRET_KEY` | no example | Minio secret key |
|
|
||||||
| `CMD_MINIO_ENDPOINT` | `minio.example.org` | Address of your Minio endpoint/instance |
|
|
||||||
| `CMD_MINIO_PORT` | `9000` | Port that is used for your Minio instance |
|
|
||||||
| `CMD_MINIO_SECURE` | `true` | If set to `true` HTTPS is used for Minio |
|
|
||||||
| `CMD_AZURE_CONNECTION_STRING` | no example | Azure Blob Storage connection string |
|
|
||||||
| `CMD_AZURE_CONTAINER` | no example | Azure Blob Storage container name (automatically created if non existent) |
|
|
||||||
| `CMD_HSTS_ENABLE` | ` true` | set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default is ` true`) |
|
|
||||||
| `CMD_HSTS_INCLUDE_SUBDOMAINS` | `true` | set to include subdomains in HSTS (default is `true`) |
|
|
||||||
| `CMD_HSTS_MAX_AGE` | `31536000` | max duration in seconds to tell clients to keep HSTS status (default is a year) |
|
|
||||||
| `CMD_HSTS_PRELOAD` | `true` | whether to allow preloading of the site's HSTS status (e.g. into browsers) |
|
|
||||||
| `CMD_CSP_ENABLE` | `true` | whether to enable Content Security Policy (directives cannot be configured with environment variables) |
|
|
||||||
| `CMD_CSP_REPORTURI` | `https://<someid>.report-uri.com/r/d/csp/enforce` | Allows to add a URL for CSP reports in case of violations |
|
|
||||||
| `CMD_SOURCE_URL` | `https://github.com/hackmdio/codimd/tree/<current commit>` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) |
|
|
||||||
|
|
||||||
***Note:** Due to the rename process we renamed all `HMD_`-prefix variables to be `CMD_`-prefixed. The old ones continue to work.*
|
|
||||||
|
|
||||||
## Application settings `config.json`
|
|
||||||
|
|
||||||
| variables | example values | description |
|
|
||||||
| --------- | ------ | ----------- |
|
|
||||||
| `debug` | `true` or `false` | set debug mode, show more logs |
|
|
||||||
| `domain` | `localhost` | domain name |
|
|
||||||
| `urlPath` | `codimd` | sub URL path, like `www.example.com/<urlpath>` |
|
|
||||||
| `host` | `localhost` | host to listen on |
|
|
||||||
| `port` | `80` | web app port |
|
|
||||||
| `path` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `host` and `port` are ignored) |
|
|
||||||
| `loglevel` | `info` | Defines what kind of logs are provided to stdout. |
|
|
||||||
| `allowOrigin` | `['localhost']` | domain name whitelist |
|
|
||||||
| `useSSL` | `true` or `false` | set to use SSL server (if `true`, will auto turn on `protocolUseSSL`) |
|
|
||||||
| `hsts` | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) |
|
|
||||||
| `csp` | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some CDN locations are allowed too. By default (`auto`), insecure (HTTP) requests are upgraded to HTTPS via CSP if `useSSL` is on. To change this behaviour, set `upgradeInsecureRequests` to either `true` or `false`. |
|
|
||||||
| `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 (ports `80` or `443` won't be applied) (only applied when domain is set) |
|
|
||||||
| `useCDN` | `true` or `false` | set to use CDN resources or not (default is `true`) |
|
|
||||||
| `allowAnonymous` | `true` or `false` | set to allow anonymous usage (default is `true`) |
|
|
||||||
| `allowAnonymousEdits` | `true` or `false` | if `allowAnonymous` is `true`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`) |
|
|
||||||
| `allowFreeURL` | `true` or `false` | set to allow new note creation by accessing a nonexistent note URL |
|
|
||||||
| `forbiddenNoteIDs` | `['robots.txt']` | disallow creation of notes, even if `allowFreeUrl` is `true` |
|
|
||||||
| `defaultPermission` | `freely`, `editable`, `limited`, `locked`, `protected` or `private` | set notes default permission (only applied on signed users) |
|
|
||||||
| `dbURL` | `mysql://localhost:3306/database` | set the db URL; if set, then db config (below) won't be applied |
|
|
||||||
| `db` | `{ "dialect": "sqlite", "storage": "./db.codimd.sqlite" }` | set the db configs, [see more here](http://sequelize.readthedocs.org/en/latest/api/sequelize/) |
|
|
||||||
| `sslKeyPath` | `./cert/client.key` | SSL key path<sup>1</sup> (only need when you set `useSSL`) |
|
|
||||||
| `sslCertPath` | `./cert/codimd_io.crt` | SSL cert path<sup>1</sup> (only need when you set `useSSL`) |
|
|
||||||
| `sslCAPath` | `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain<sup>1</sup> (only need when you set `useSSL`) |
|
|
||||||
| `dhParamPath` | `./cert/dhparam.pem` | SSL dhparam path<sup>1</sup> (only need when you set `useSSL`) |
|
|
||||||
| `tmpPath` | `./tmp/` | temp directory path<sup>1</sup> |
|
|
||||||
| `defaultNotePath` | `./public/default.md` | default note file path<sup>1</sup> |
|
|
||||||
| `docsPath` | `./public/docs` | docs directory path<sup>1</sup> |
|
|
||||||
| `viewPath` | `./public/views` | template directory path<sup>1</sup> |
|
|
||||||
| `uploadsPath` | `./public/uploads` | uploads directory<sup>1</sup> - needs to be persistent when you use imageUploadType `filesystem` |
|
|
||||||
| `sessionName` | `connect.sid` | cookie session name |
|
|
||||||
| `sessionSecret` | `secret` | cookie session secret |
|
|
||||||
| `sessionLife` | `14 * 24 * 60 * 60 * 1000` | cookie session life |
|
|
||||||
| `staticCacheTime` | `1 * 24 * 60 * 60 * 1000` | static file cache time |
|
|
||||||
| `heartbeatInterval` | `5000` | socket.io heartbeat interval |
|
|
||||||
| `heartbeatTimeout` | `10000` | socket.io heartbeat timeout |
|
|
||||||
| `documentMaxLength` | `100000` | note max length |
|
|
||||||
| `email` | `true` or `false` | set to allow email signin |
|
|
||||||
| `oauth2` | `{baseURL: ..., userProfileURL: ..., userProfileUsernameAttr: ..., userProfileDisplayNameAttr: ..., userProfileEmailAttr: ..., tokenURL: ..., authorizationURL: ..., clientID: ..., clientSecret: ...}` | An object detailing your OAuth2 provider. Refer to the [Mattermost](docs/guides/auth/mattermost-self-hosted.md) or [Nextcloud](docs/guides/auth/nextcloud.md) examples for more details!|
|
|
||||||
| `allowEmailRegister` | `true` or `false` | set to allow email register (only applied when email is set, default is `true`. Note `bin/manage_users` might help you if registration is `false`.) |
|
|
||||||
| `allowGravatar` | `true` or `false` | set to `false` to disable gravatar as profile picture source on your instance |
|
|
||||||
| `imageUploadType` | `imgur`, `s3`, `minio`, `azure` or `filesystem`(default) | Where to upload images. For S3, see our Image Upload Guides for [S3](docs/guides/s3-image-upload.md) or [Minio](docs/guides/minio-image-upload.md)|
|
|
||||||
| `minio` | `{ "accessKey": "YOUR_MINIO_ACCESS_KEY", "secretKey": "YOUR_MINIO_SECRET_KEY", "endpoint": "YOUR_MINIO_HOST", port: 9000, secure: true }` | When `imageUploadType` is set to `minio`, you need to set this key. Also checkout our [Minio Image Upload Guide](docs/guides/minio-image-upload.md) |
|
|
||||||
| `s3` | `{ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID", "secretAccessKey": "YOUR_S3_ACCESS_KEY", "region": "YOUR_S3_REGION" }` | When `imageuploadtype` be set to `s3`, you would also need to setup this key, check our [S3 Image Upload Guide](docs/guides/s3-image-upload.md) |
|
|
||||||
| `s3bucket` | `YOUR_S3_BUCKET_NAME` | bucket name when `imageUploadType` is set to `s3` or `minio` |
|
|
||||||
| `sourceURL` | `https://github.com/hackmdio/codimd/tree/<current commit>` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) |
|
|
||||||
|
|
||||||
<sup>1</sup>: relative paths are based on CodiMD's base directory
|
|
||||||
|
|
||||||
## Third-party integration API key settings
|
|
||||||
|
|
||||||
| service | settings location | description |
|
|
||||||
| ------- | --------- | ----------- |
|
|
||||||
| facebook, twitter, github, gitlab, mattermost, dropbox, google, ldap, saml | environment variables or `config.json` | for signin |
|
|
||||||
| imgur, s3, minio, azure | environment variables or `config.json` | for image upload |
|
|
||||||
| dropbox(`dropbox/appKey`) | `config.json` | for export and import |
|
|
||||||
|
|
||||||
## Third-party integration OAuth callback URLs
|
|
||||||
|
|
||||||
| service | callback URL (after the server URL) |
|
|
||||||
| ------- | --------- |
|
|
||||||
| facebook | `/auth/facebook/callback` |
|
|
||||||
| twitter | `/auth/twitter/callback` |
|
|
||||||
| github | `/auth/github/callback` |
|
|
||||||
| gitlab | `/auth/gitlab/callback` |
|
|
||||||
| mattermost | `/auth/mattermost/callback` |
|
|
||||||
| dropbox | `/auth/dropbox/callback` |
|
|
||||||
| google | `/auth/google/callback` |
|
|
||||||
| saml | `/auth/saml/callback` |
|
|
||||||
|
|
||||||
# Developer Notes
|
|
||||||
|
|
||||||
## Structure
|
|
||||||
|
|
||||||
```text
|
|
||||||
codimd/
|
|
||||||
├── tmp/ --- temporary files
|
|
||||||
├── docs/ --- document files
|
|
||||||
├── lib/ --- server libraries
|
|
||||||
└── public/ --- client files
|
|
||||||
├── css/ --- css styles
|
|
||||||
├── js/ --- js scripts
|
|
||||||
├── vendor/ --- vendor includes
|
|
||||||
└── views/ --- view templates
|
|
||||||
```
|
|
||||||
|
|
||||||
## Operational Transformation
|
|
||||||
|
|
||||||
From 0.3.2, we started supporting operational transformation.
|
|
||||||
It makes concurrent editing safe and will not break up other users' operations.
|
|
||||||
Additionally, now can show other clients' selections.
|
|
||||||
See more at [http://operational-transformation.github.io/](http://operational-transformation.github.io/)
|
|
||||||
|
|
||||||
|
Our community has created related tools, we'd like to highlight [codimd-cli](https://github.com/codimd/cli)
|
||||||
|
which lets you use CodiMD from the comfort of your command line.
|
||||||
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
**License under AGPL.**
|
Licensed under AGPLv3. For our list of contributors, see [AUTHORS](AUTHORS).
|
||||||
|
|
||||||
[gitter-image]: https://img.shields.io/badge/gitter-hackmdio/codimd-blue.svg
|
[matrix.org-image]: https://img.shields.io/badge/Matrix.org-%23CodiMD@matrix.org-green.svg
|
||||||
[gitter-url]: https://gitter.im/hackmdio/hackmd
|
[matrix.org-url]: https://riot.im/app/#/room/#codimd:matrix.org
|
||||||
[travis-image]: https://travis-ci.org/hackmdio/codimd.svg?branch=master
|
[travis-image]: https://travis-ci.org/codimd/server.svg?branch=master
|
||||||
[travis-url]: https://travis-ci.org/hackmdio/codimd
|
[travis-url]: https://travis-ci.org/codimd/server
|
||||||
[github-version-badge]: https://img.shields.io/github/release/hackmdio/codimd.svg
|
[github-version-badge]: https://img.shields.io/github/release/codimd/server.svg
|
||||||
[github-release-page]: https://github.com/hackmdio/codimd/releases
|
[github-release-page]: https://github.com/codimd/server/releases
|
||||||
[github-release-feed]: https://github.com/hackmdio/codimd/releases.atom
|
[github-release-feed]: https://github.com/codimd/server/releases.atom
|
||||||
|
[github-issue-tracker]: https://github.com/codimd/server/issues/
|
||||||
[poeditor-image]: https://img.shields.io/badge/POEditor-translate-blue.svg
|
[poeditor-image]: https://img.shields.io/badge/POEditor-translate-blue.svg
|
||||||
[poeditor-url]: https://poeditor.com/join/project/q0nuPWyztp
|
[poeditor-url]: https://poeditor.com/join/project/1OpGjF2Jir
|
||||||
|
[codimd-demo]: https://demo.codimd.org
|
||||||
|
[codimd-demo-features]: https://demo.codimd.org/features
|
||||||
|
[codimd-community]: https://community.codimd.org
|
||||||
|
[codimd-community-calls]: https://community.codimd.org/t/codimd-community-call/19
|
||||||
|
|
1
app.js
|
@ -115,6 +115,7 @@ if (config.csp.enable) {
|
||||||
i18n.configure({
|
i18n.configure({
|
||||||
locales: ['en', 'zh-CN', 'zh-TW', 'fr', 'de', 'ja', 'es', 'ca', 'el', 'pt', 'it', 'tr', 'ru', 'nl', 'hr', 'pl', 'uk', 'hi', 'sv', 'eo', 'da', 'ko', 'id', 'sr'],
|
locales: ['en', 'zh-CN', 'zh-TW', 'fr', 'de', 'ja', 'es', 'ca', 'el', 'pt', 'it', 'tr', 'ru', 'nl', 'hr', 'pl', 'uk', 'hi', 'sv', 'eo', 'da', 'ko', 'id', 'sr'],
|
||||||
cookie: 'locale',
|
cookie: 'locale',
|
||||||
|
indent: ' ', // this is the style poeditor.com exports it, this creates less churn
|
||||||
directory: path.join(__dirname, '/locales'),
|
directory: path.join(__dirname, '/locales'),
|
||||||
updateFiles: config.updateI18nFiles
|
updateFiles: config.updateI18nFiles
|
||||||
})
|
})
|
||||||
|
|
76
app.json
|
@ -7,14 +7,10 @@
|
||||||
"Notes"
|
"Notes"
|
||||||
],
|
],
|
||||||
"website": "https://codimd.org",
|
"website": "https://codimd.org",
|
||||||
"repository": "https://github.com/hackmdio/codimd",
|
"repository": "https://github.com/codimd/server",
|
||||||
"logo": "https://github.com/hackmdio/codimd/raw/master/public/codimd-icon-1024.png",
|
"logo": "https://github.com/codimd/server/raw/master/public/codimd-icon-1024.png",
|
||||||
"success_url": "/",
|
"success_url": "/",
|
||||||
"env": {
|
"env": {
|
||||||
"BUILD_ASSETS": {
|
|
||||||
"description": "Our build script variable",
|
|
||||||
"value": "true"
|
|
||||||
},
|
|
||||||
"NPM_CONFIG_PRODUCTION": {
|
"NPM_CONFIG_PRODUCTION": {
|
||||||
"description": "Let npm also install development build tool",
|
"description": "Let npm also install development build tool",
|
||||||
"value": "false"
|
"value": "false"
|
||||||
|
@ -23,137 +19,129 @@
|
||||||
"description": "Specify database type. See sequelize available databases. Default using postgres",
|
"description": "Specify database type. See sequelize available databases. Default using postgres",
|
||||||
"value": "postgres"
|
"value": "postgres"
|
||||||
},
|
},
|
||||||
"HMD_SESSION_SECRET": {
|
"CMD_SESSION_SECRET": {
|
||||||
"description": "Secret used to secure session cookies.",
|
"description": "Secret used to secure session cookies.",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_HSTS_ENABLE": {
|
"CMD_HSTS_ENABLE": {
|
||||||
"description": "whether to also use HSTS if HTTPS is enabled",
|
"description": "whether to also use HSTS if HTTPS is enabled",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_HSTS_MAX_AGE": {
|
"CMD_HSTS_MAX_AGE": {
|
||||||
"description": "max duration, in seconds, to tell clients to keep HSTS status",
|
"description": "max duration, in seconds, to tell clients to keep HSTS status",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_HSTS_INCLUDE_SUBDOMAINS": {
|
"CMD_HSTS_INCLUDE_SUBDOMAINS": {
|
||||||
"description": "whether to tell clients to also regard subdomains as HSTS hosts",
|
"description": "whether to tell clients to also regard subdomains as HSTS hosts",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_HSTS_PRELOAD": {
|
"CMD_HSTS_PRELOAD": {
|
||||||
"description": "whether to allow at all adding of the site to HSTS preloads (e.g. in browsers)",
|
"description": "whether to allow at all adding of the site to HSTS preloads (e.g. in browsers)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_DOMAIN": {
|
"CMD_DOMAIN": {
|
||||||
"description": "domain name",
|
"description": "domain name",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_URL_PATH": {
|
"CMD_URL_PATH": {
|
||||||
"description": "sub url path, like `www.example.com/<URL_PATH>`",
|
"description": "sub url path, like `www.example.com/<URL_PATH>`",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_ALLOW_ORIGIN": {
|
"CMD_ALLOW_ORIGIN": {
|
||||||
"description": "domain name whitelist (use comma to separate)",
|
"description": "domain name whitelist (use comma to separate)",
|
||||||
"required": false,
|
"required": false,
|
||||||
"value": "localhost"
|
"value": "localhost"
|
||||||
},
|
},
|
||||||
"HMD_PROTOCOL_USESSL": {
|
"CMD_PROTOCOL_USESSL": {
|
||||||
"description": "set to use ssl protocol for resources path (only applied when domain is set)",
|
"description": "set to use ssl protocol for resources path (only applied when domain is set)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_URL_ADDPORT": {
|
"CMD_URL_ADDPORT": {
|
||||||
"description": "set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)",
|
"description": "set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_FACEBOOK_CLIENTID": {
|
"CMD_FACEBOOK_CLIENTID": {
|
||||||
"description": "Facebook API client id",
|
"description": "Facebook API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_FACEBOOK_CLIENTSECRET": {
|
"CMD_FACEBOOK_CLIENTSECRET": {
|
||||||
"description": "Facebook API client secret",
|
"description": "Facebook API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_TWITTER_CONSUMERKEY": {
|
"CMD_TWITTER_CONSUMERKEY": {
|
||||||
"description": "Twitter API consumer key",
|
"description": "Twitter API consumer key",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_TWITTER_CONSUMERSECRET": {
|
"CMD_TWITTER_CONSUMERSECRET": {
|
||||||
"description": "Twitter API consumer secret",
|
"description": "Twitter API consumer secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITHUB_CLIENTID": {
|
"CMD_GITHUB_CLIENTID": {
|
||||||
"description": "GitHub API client id",
|
"description": "GitHub API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITHUB_CLIENTSECRET": {
|
"CMD_GITHUB_CLIENTSECRET": {
|
||||||
"description": "GitHub API client secret",
|
"description": "GitHub API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITLAB_BASEURL": {
|
"CMD_GITLAB_BASEURL": {
|
||||||
"description": "GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional)",
|
"description": "GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITLAB_CLIENTID": {
|
"CMD_GITLAB_CLIENTID": {
|
||||||
"description": "GitLab API client id",
|
"description": "GitLab API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITLAB_CLIENTSECRET": {
|
"CMD_GITLAB_CLIENTSECRET": {
|
||||||
"description": "GitLab API client secret",
|
"description": "GitLab API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GITLAB_SCOPE": {
|
"CMD_GITLAB_SCOPE": {
|
||||||
"description": "GitLab API client scope (optional)",
|
"description": "GitLab API client scope (optional)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_MATTERMOST_BASEURL": {
|
"CMD_MATTERMOST_BASEURL": {
|
||||||
"description": "Mattermost authentication endpoint",
|
"description": "Mattermost authentication endpoint",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_MATTERMOST_CLIENTID": {
|
"CMD_MATTERMOST_CLIENTID": {
|
||||||
"description": "Mattermost API client id",
|
"description": "Mattermost API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_MATTERMOST_CLIENTSECRET": {
|
"CMD_MATTERMOST_CLIENTSECRET": {
|
||||||
"description": "Mattermost API client secret",
|
"description": "Mattermost API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_DROPBOX_CLIENTID": {
|
"CMD_DROPBOX_CLIENTID": {
|
||||||
"description": "Dropbox API client id",
|
"description": "Dropbox API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_DROPBOX_CLIENTSECRET": {
|
"CMD_DROPBOX_CLIENTSECRET": {
|
||||||
"description": "Dropbox API client secret",
|
"description": "Dropbox API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_DROPBOX_APP_KEY": {
|
"CMD_DROPBOX_APP_KEY": {
|
||||||
"description": "Dropbox app key (for import/export)",
|
"description": "Dropbox app key (for import/export)",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GOOGLE_CLIENTID": {
|
"CMD_GOOGLE_CLIENTID": {
|
||||||
"description": "Google API client id",
|
"description": "Google API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_GOOGLE_CLIENTSECRET": {
|
"CMD_GOOGLE_CLIENTSECRET": {
|
||||||
"description": "Google API client secret",
|
"description": "Google API client secret",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_IMGUR_CLIENTID": {
|
"CMD_IMGUR_CLIENTID": {
|
||||||
"description": "Imgur API client id",
|
"description": "Imgur API client id",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"HMD_ALLOW_PDF_EXPORT": {
|
"CMD_ALLOW_PDF_EXPORT": {
|
||||||
"description": "Enable or disable PDF exports",
|
"description": "Enable or disable PDF exports",
|
||||||
"required": false
|
"required": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"addons": [
|
"addons": [
|
||||||
"heroku-postgresql"
|
"heroku-postgresql"
|
||||||
],
|
|
||||||
"buildpacks": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/alex88/heroku-buildpack-vips"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/heroku/heroku-buildpack-nodejs"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
10
bin/heroku
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [ "$BUILD_ASSETS" = true ]; then
|
cat << EOF > .sequelizerc
|
||||||
# setup config files
|
|
||||||
cat << EOF > .sequelizerc
|
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -17,7 +15,7 @@ module.exports = {
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat << EOF > config.json
|
cat << EOF > config.json
|
||||||
|
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
|
@ -25,7 +23,3 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# build app
|
|
||||||
npm run build
|
|
||||||
fi
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ cat << EOF
|
||||||
|
|
||||||
|
|
||||||
Edit the following config file to setup CodiMD server and client.
|
Edit the following config file to setup CodiMD server and client.
|
||||||
Read more info at https://github.com/hackmdio/codimd#configuration-files
|
Read more info at https://github.com/codimd/server#configuration-files
|
||||||
|
|
||||||
* config.json -- CodiMD config
|
* config.json -- CodiMD config
|
||||||
* .sequelizerc -- db config
|
* .sequelizerc -- db config
|
||||||
|
|
|
@ -93,6 +93,7 @@
|
||||||
"idpCert": "change: certificate file path of IdP in PEM format",
|
"idpCert": "change: certificate file path of IdP in PEM format",
|
||||||
"issuer": "change or delete: identity of the service provider (default: serverurl)",
|
"issuer": "change or delete: identity of the service provider (default: serverurl)",
|
||||||
"identifierFormat": "change or delete: name identifier format (default: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')",
|
"identifierFormat": "change or delete: name identifier format (default: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')",
|
||||||
|
"disableRequestedAuthnContext": "change or delete: true to allow any authentication method, false restricts to password authentication method (default: false)",
|
||||||
"groupAttribute": "change or delete: attribute name for group list (ex: memberOf)",
|
"groupAttribute": "change or delete: attribute name for group list (ex: memberOf)",
|
||||||
"requiredGroups": [ "change or delete: group names that allowed" ],
|
"requiredGroups": [ "change or delete: group names that allowed" ],
|
||||||
"externalGroups": [ "change or delete: group names that not allowed" ],
|
"externalGroups": [ "change or delete: group names that not allowed" ],
|
||||||
|
|
153
docs/configuration-config-file.md
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
Configuration Using Config file
|
||||||
|
===
|
||||||
|
|
||||||
|
You can choose to configure CodiMD with either a config file or with
|
||||||
|
[environment variables](configuration-env-vars.md). The config file is processed
|
||||||
|
in [`lib/config/index.js`](../lib/config/index.js) - so this is the first
|
||||||
|
place to look if anything is missing not obvious from this document. The
|
||||||
|
default values are defined in [`lib/config/default.js`](../lib/config/default.js),
|
||||||
|
in case you wonder if you even need to override it.
|
||||||
|
|
||||||
|
Environment variables take precedence over configurations from the config files.
|
||||||
|
To get started, it is a good idea to take the `config.json.example` and copy it
|
||||||
|
to `config.json` before filling in your own details.
|
||||||
|
|
||||||
|
|
||||||
|
## Node.JS
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `debug` | `true` or `false` | set debug mode, show more logs |
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD basics
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `allowPDFExport` | `true` | Whether or not PDF export is offered. |
|
||||||
|
| `db` | `{ "dialect": "sqlite", "storage": "./db.codimd.sqlite" }` | set the db configs, [see more here](http://sequelize.readthedocs.org/en/latest/api/sequelize/) |
|
||||||
|
| `dbURL` | `mysql://localhost:3306/database` | set the db URL; if set, then db config (below) won't be applied |
|
||||||
|
| `forbiddenNoteIDs` | `['robots.txt']` | disallow creation of notes, even if `allowFreeUrl` is `true` |
|
||||||
|
| `loglevel` | `info` | Defines what kind of logs are provided to stdout. |
|
||||||
|
| `imageUploadType` | `imgur`, `s3`, `minio`, `azure`, `lutim` or `filesystem`(default) | Where to upload images. For S3, see our Image Upload Guides for [S3](guides/s3-image-upload.md) or [Minio](guides/minio-image-upload.md)|
|
||||||
|
| `sourceURL` | `https://github.com/codimd/server/tree/<current commit>` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) |
|
||||||
|
| `staticCacheTime` | `1 * 24 * 60 * 60 * 1000` | static file cache time |
|
||||||
|
| `heartbeatInterval` | `5000` | socket.io heartbeat interval |
|
||||||
|
| `heartbeatTimeout` | `10000` | socket.io heartbeat timeout |
|
||||||
|
| `documentMaxLength` | `100000` | note max length |
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD paths stuff
|
||||||
|
|
||||||
|
these are rarely used for various reasons.
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `defaultNotePath` | `./public/default.md` | default note file path<sup>1</sup>, empty notes will be created with this template. |
|
||||||
|
| `dhParamPath` | `./cert/dhparam.pem` | SSL dhparam path<sup>1</sup> (only need when you set `useSSL`) |
|
||||||
|
| `sslCAPath` | `['./cert/COMODORSAAddTrustCA.crt']` | SSL ca chain<sup>1</sup> (only need when you set `useSSL`) |
|
||||||
|
| `sslCertPath` | `./cert/codimd_io.crt` | SSL cert path<sup>1</sup> (only need when you set `useSSL`) |
|
||||||
|
| `sslKeyPath` | `./cert/client.key` | SSL key path<sup>1</sup> (only need when you set `useSSL`) |
|
||||||
|
| `tmpPath` | `./tmp/` | temp directory path<sup>1</sup> |
|
||||||
|
| `docsPath` | `./public/docs` | docs directory path<sup>1</sup> |
|
||||||
|
| `viewPath` | `./public/views` | template directory path<sup>1</sup> |
|
||||||
|
| `uploadsPath` | `./public/uploads` | uploads directory<sup>1</sup> - needs to be persistent when you use imageUploadType `filesystem` |
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD Location
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `domain` | `localhost` | domain name |
|
||||||
|
| `urlPath` | `codimd` | sub URL path, like `www.example.com/<urlpath>` |
|
||||||
|
| `host` | `localhost` | interface/ip to listen on |
|
||||||
|
| `port` | `80` | port to listen on |
|
||||||
|
| `path` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `host` and `port` are ignored) |
|
||||||
|
| `protocolUseSSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) |
|
||||||
|
| `useSSL` | `true` or `false` | set to use SSL server (if `true`, will auto turn on `protocolUseSSL`) |
|
||||||
|
| `urlAddPort` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) |
|
||||||
|
| `allowOrigin` | `['localhost']` | domain name whitelist |
|
||||||
|
|
||||||
|
|
||||||
|
## CSP and HSTS
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `hsts` | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) |
|
||||||
|
| `csp` | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some CDN locations are allowed too. By default (`auto`), insecure (HTTP) requests are upgraded to HTTPS via CSP if `useSSL` is on. To change this behaviour, set `upgradeInsecureRequests` to either `true` or `false`. |
|
||||||
|
|
||||||
|
## Privacy and External Requests
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `allowGravatar` | `true` or `false` | set to `false` to disable gravatar as profile picture source on your instance |
|
||||||
|
| `useCDN` | `true` or `false` | set to use CDN resources or not (default is `true`) |
|
||||||
|
|
||||||
|
## Users and Privileges
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `allowAnonymous` | `true` or `false` | set to allow anonymous usage (default is `true`) |
|
||||||
|
| `allowAnonymousEdits` | `true` or `false` | if `allowAnonymous` is `true`: allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`) |
|
||||||
|
| `allowFreeURL` | `true` or `false` | set to allow new note creation by accessing a nonexistent note URL |
|
||||||
|
| `defaultPermission` | `freely`, `editable`, `limited`, `locked`, `protected` or `private` | set notes default permission (only applied on signed users) |
|
||||||
|
| `sessionName` | `connect.sid` | cookie session name |
|
||||||
|
| `sessionLife` | `14 * 24 * 60 * 60 * 1000` | cookie session life |
|
||||||
|
| `sessionSecret` | `secret` | cookie session secret | If none is set, one will randomly generated on each startup, meaning all your users will be logged out. |
|
||||||
|
|
||||||
|
|
||||||
|
## Login methods
|
||||||
|
|
||||||
|
Most of these have never been documented for the config.json, feel free to expand these
|
||||||
|
|
||||||
|
### Email (local account)
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `email` | `true` or `false` | set to allow email signin |
|
||||||
|
| `allowEmailRegister` | `true` or `false` | set to allow email register (only applied when email is set, default is `true`. Note `bin/manage_users` might help you if registration is `false`.) |
|
||||||
|
|
||||||
|
### Dropbox Login
|
||||||
|
### Facebook Login
|
||||||
|
### GitHub Login
|
||||||
|
### GitLab Login
|
||||||
|
### Google Login
|
||||||
|
### LDAP Login
|
||||||
|
### Mattermost Login
|
||||||
|
### OAuth2 Login
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `oauth2` | `{baseURL: ..., userProfileURL: ..., userProfileUsernameAttr: ..., userProfileDisplayNameAttr: ..., userProfileEmailAttr: ..., tokenURL: ..., authorizationURL: ..., clientID: ..., clientSecret: ...}` | An object detailing your OAuth2 provider. Refer to the [Mattermost](guides/auth/mattermost-self-hosted.md) or [Nextcloud](guides/auth/nextcloud.md) examples for more details!|
|
||||||
|
|
||||||
|
### SAML Login
|
||||||
|
### Twitter Login
|
||||||
|
|
||||||
|
|
||||||
|
## Upload Storage
|
||||||
|
|
||||||
|
Most of these have never been documented for the config.json, feel free to expand these
|
||||||
|
|
||||||
|
|
||||||
|
### Amazon S3
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `s3` | `{ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID", "secretAccessKey": "YOUR_S3_ACCESS_KEY", "region": "YOUR_S3_REGION" }` | When `imageuploadtype` be set to `s3`, you would also need to setup this key, check our [S3 Image Upload Guide](guides/s3-image-upload.md) |
|
||||||
|
| `s3bucket` | `YOUR_S3_BUCKET_NAME` | bucket name when `imageUploadType` is set to `s3` or `minio` |
|
||||||
|
|
||||||
|
### Azure Blob Storage
|
||||||
|
### imgur
|
||||||
|
### Minio
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
| `minio` | `{ "accessKey": "YOUR_MINIO_ACCESS_KEY", "secretKey": "YOUR_MINIO_SECRET_KEY", "endpoint": "YOUR_MINIO_HOST", port: 9000, secure: true }` | When `imageUploadType` is set to `minio`, you need to set this key. Also check out our [Minio Image Upload Guide](guides/minio-image-upload.md) |
|
||||||
|
|
||||||
|
### Lutim
|
||||||
|
|
||||||
|
| variables | example values | description |
|
||||||
|
| --------- | ------ | ----------- |
|
||||||
|
|`lutim`| `{"url": "YOUR_LUTIM_URL"}`| When `imageUploadType` is set to `lutim`, you can setup the lutim url|
|
||||||
|
|
||||||
|
<sup>1</sup>: relative paths are based on CodiMD's base directory
|
255
docs/configuration-env-vars.md
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
Configuration Using Environment variables
|
||||||
|
===
|
||||||
|
|
||||||
|
You can choose to configure CodiMD with either a
|
||||||
|
[config file](configuration-config-file.md) or with environment variables.
|
||||||
|
Environment variables are processed in
|
||||||
|
[`lib/config/environment.js`](../lib/config/environment.js) - so this is the first
|
||||||
|
place to look if anything is missing not obvious from this document. The
|
||||||
|
default values are defined in [`lib/config/default.js`](../lib/config/default.js),
|
||||||
|
in case you wonder if you even need to override it.
|
||||||
|
|
||||||
|
Environment variables take precedence over configurations from the config files.
|
||||||
|
They generally start with `CMD_` for our own options, but we also list
|
||||||
|
node-specific options you can configure this way.
|
||||||
|
|
||||||
|
|
||||||
|
## Node.JS
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `NODE_ENV` | `production` or `development` | set current environment (will apply corresponding settings in the `config.json`) |
|
||||||
|
| `DEBUG` | `true` or `false` | set debug mode; show more logs |
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD basics
|
||||||
|
|
||||||
|
defaultNotePath can't be set from env-vars
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_ALLOW_PDF_EXPORT` | `true` or `false` | Enable or disable PDF exports |
|
||||||
|
| `CMD_CONFIG_FILE` | `/path/to/config.json` | optional override for the path to CodiMD's config file |
|
||||||
|
| `CMD_DB_URL` | `mysql://localhost:3306/database` | set the database URL |
|
||||||
|
| `CMD_LOGLEVEL` | `info`, `debug` ... | Defines what kind of logs are provided to stdout. |
|
||||||
|
| `CMD_FORBIDDEN_NOTE_IDS` | `'robots.txt'` | disallow creation of notes, even if `CMD_ALLOW_FREEURL` is `true` |
|
||||||
|
| `CMD_IMAGE_UPLOAD_TYPE` | `imgur`, `s3`, `minio`, `lutim` or `filesystem` | Where to upload images. For S3, see our Image Upload Guides for [S3](guides/s3-image-upload.md) or [Minio](guides/minio-image-upload.md), also there's a whole section on their respective env vars below. |
|
||||||
|
| `CMD_SOURCE_URL` | `https://github.com/codimd/server/tree/<current commit>` | Provides the link to the source code of CodiMD on the entry page (Please, make sure you change this when you run a modified version) |
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD Location
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_DOMAIN` | `codimd.org` | domain name |
|
||||||
|
| `CMD_URL_PATH` | `codimd` | If CodiMD is run from a subdirectory like `www.example.com/<urlpath>` |
|
||||||
|
| `CMD_HOST` | `localhost` | interface/ip to listen on |
|
||||||
|
| `CMD_PORT` | `80` | port to listen on |
|
||||||
|
| `CMD_PATH` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `CMD_HOST` and `CMD_PORT` are ignored) |
|
||||||
|
| `CMD_PROTOCOL_USESSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) |
|
||||||
|
| `CMD_URL_ADDPORT` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) |
|
||||||
|
| `CMD_ALLOW_ORIGIN` | `localhost, codimd.org` | domain name whitelist (use comma to separate) |
|
||||||
|
|
||||||
|
|
||||||
|
## CSP and HSTS
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_CSP_ENABLE` | `true` | whether to enable Content Security Policy (directives cannot be configured with environment variables) |
|
||||||
|
| `CMD_CSP_REPORTURI` | `https://<someid>.report-uri.com/r/d/csp/enforce` | Allows to add a URL for CSP reports in case of violations |
|
||||||
|
| `CMD_HSTS_ENABLE` | ` true` | set to enable [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) if HTTPS is also enabled (default is ` true`) |
|
||||||
|
| `CMD_HSTS_INCLUDE_SUBDOMAINS` | `true` | set to include subdomains in HSTS (default is `true`) |
|
||||||
|
| `CMD_HSTS_MAX_AGE` | `31536000` | max duration in seconds to tell clients to keep HSTS status (default is a year) |
|
||||||
|
| `CMD_HSTS_PRELOAD` | `true` | whether to allow preloading of the site's HSTS status (e.g. into browsers) |
|
||||||
|
|
||||||
|
|
||||||
|
## Privacy and External Requests
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_ALLOW_GRAVATAR` | `true` or `false` | set to `false` to disable gravatar as profile picture source on your instance |
|
||||||
|
| `CMD_USECDN` | `true` or `false` | set to use CDN resources or not|
|
||||||
|
|
||||||
|
|
||||||
|
## Users and Privileges
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_ALLOW_ANONYMOUS` | `true` or `false` | set to allow anonymous usage (default is `true`) |
|
||||||
|
| `CMD_ALLOW_ANONYMOUS_EDITS` | `true` or `false` | if `allowAnonymous` is `true`, allow users to select `freely` permission, allowing guests to edit existing notes (default is `false`) |
|
||||||
|
| `CMD_ALLOW_FREEURL` | `true` or `false` | set to allow new note creation by accessing a nonexistent note URL |
|
||||||
|
| `CMD_DEFAULT_PERMISSION` | `freely`, `editable`, `limited`, `locked` or `private` | set notes default permission (only applied on signed users) |
|
||||||
|
| `CMD_SESSION_LIFE` | `1209600000` | Session life time. (milliseconds) |
|
||||||
|
| `CMD_SESSION_SECRET` | no example | Secret used to sign the session cookie. If none is set, one will randomly generated on each startup, meaning all your users will be logged out. |
|
||||||
|
|
||||||
|
|
||||||
|
## Login methods
|
||||||
|
|
||||||
|
### Email (local account)
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_EMAIL` | `true` or `false` | set to allow email signin |
|
||||||
|
| `CMD_ALLOW_EMAIL_REGISTER` | `true` or `false` | set to allow email register (only applied when email is set, default is `true`. Note `bin/manage_users` might help you if registration is `false`.) |
|
||||||
|
|
||||||
|
|
||||||
|
### Dropbox Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_DROPBOX_CLIENTID` | no example | Dropbox API client id |
|
||||||
|
| `CMD_DROPBOX_CLIENTSECRET` | no example | Dropbox API client secret |
|
||||||
|
|
||||||
|
|
||||||
|
### Facebook Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_FACEBOOK_CLIENTID` | no example | Facebook API client id |
|
||||||
|
| `CMD_FACEBOOK_CLIENTSECRET` | no example | Facebook API client secret |
|
||||||
|
|
||||||
|
|
||||||
|
### GitHub Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_GITHUB_CLIENTID` | no example | GitHub API client id |
|
||||||
|
| `CMD_GITHUB_CLIENTSECRET` | no example | GitHub API client secret |
|
||||||
|
|
||||||
|
|
||||||
|
### GitLab Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_GITLAB_SCOPE` | `read_user` or `api` | GitLab API requested scope (default is `api`) (GitLab snippet import/export need `api` scope) |
|
||||||
|
| `CMD_GITLAB_BASEURL` | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) |
|
||||||
|
| `CMD_GITLAB_CLIENTID` | no example | GitLab API client id |
|
||||||
|
| `CMD_GITLAB_CLIENTSECRET` | no example | GitLab API client secret |
|
||||||
|
| `CMD_GITLAB_VERSION` | no example | GitLab API version (v3 or v4) |
|
||||||
|
|
||||||
|
|
||||||
|
### Google Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_GOOGLE_CLIENTID` | no example | Google API client id |
|
||||||
|
| `CMD_GOOGLE_CLIENTSECRET` | no example | Google API client secret |
|
||||||
|
|
||||||
|
|
||||||
|
### LDAP Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_LDAP_URL` | `ldap://example.com` | URL of LDAP server |
|
||||||
|
| `CMD_LDAP_BINDDN` | no example | bindDn for LDAP access |
|
||||||
|
| `CMD_LDAP_BINDCREDENTIALS` | no example | bindCredentials for LDAP access |
|
||||||
|
| `CMD_LDAP_SEARCHBASE` | `o=users,dc=example,dc=com` | LDAP directory to begin search from |
|
||||||
|
| `CMD_LDAP_SEARCHFILTER` | `(uid={{username}})` | LDAP filter to search with |
|
||||||
|
| `CMD_LDAP_SEARCHATTRIBUTES` | `displayName, mail` | LDAP attributes to search with (use comma to separate) |
|
||||||
|
| `CMD_LDAP_USERIDFIELD` | `uidNumber` or `uid` or `sAMAccountName` | The LDAP field which is used uniquely identify a user on CodiMD |
|
||||||
|
| `CMD_LDAP_USERNAMEFIELD` | Fallback to userid | The LDAP field which is used as the username on CodiMD |
|
||||||
|
| `CMD_LDAP_TLS_CA` | `server-cert.pem, root.pem` | Root CA for LDAP TLS in PEM format (use comma to separate) |
|
||||||
|
| `CMD_LDAP_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the LDAP provider |
|
||||||
|
|
||||||
|
|
||||||
|
### Mattermost Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_MATTERMOST_BASEURL` | no example | Mattermost authentication endpoint for versions below 5.0. For Mattermost version 5.0 and above, see [guide](guides/auth/mattermost-self-hosted.md). |
|
||||||
|
| `CMD_MATTERMOST_CLIENTID` | no example | Mattermost API client id |
|
||||||
|
| `CMD_MATTERMOST_CLIENTSECRET` | no example | Mattermost API client secret |
|
||||||
|
|
||||||
|
|
||||||
|
### OAuth2 Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_OAUTH2_USER_PROFILE_URL` | `https://example.com` | where retrieve information about a user after succesful login. Needs to output JSON. (no default value) Refer to the [Mattermost](guides/auth/mattermost-self-hosted.md) or [Nextcloud](guides/auth/nextcloud.md) examples for more details on all of the `CMD_OAUTH2...` options. |
|
||||||
|
| `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | `name` | where to find the username in the JSON from the user profile URL. (no default value)|
|
||||||
|
| `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | `display-name` | where to find the display-name in the JSON from the user profile URL. (no default value) |
|
||||||
|
| `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | `email` | where to find the email address in the JSON from the user profile URL. (no default value) |
|
||||||
|
| `CMD_OAUTH2_TOKEN_URL` | `https://example.com` | sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) |
|
||||||
|
| `CMD_OAUTH2_AUTHORIZATION_URL` | `https://example.com` | authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) |
|
||||||
|
| `CMD_OAUTH2_CLIENT_ID` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) |
|
||||||
|
| `CMD_OAUTH2_CLIENT_SECRET` | `afae02fckafd...` | you will get this from your OAuth2 provider when you register CodiMD as OAuth2-client, (no default value) |
|
||||||
|
| `CMD_OAUTH2_PROVIDERNAME` | `My institution` | Optional name to be displayed at login form indicating the oAuth2 provider |
|
||||||
|
|
||||||
|
|
||||||
|
### SAML Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_SAML_IDPSSOURL` | `https://idp.example.com/sso` | authentication endpoint of IdP. for details, see [guide](guides/auth/saml-onelogin.md). |
|
||||||
|
| `CMD_SAML_IDPCERT` | `/path/to/cert.pem` | certificate file path of IdP in PEM format |
|
||||||
|
| `CMD_SAML_ISSUER` | no example | identity of the service provider (optional, default: serverurl)" |
|
||||||
|
| `CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT` | `true` or `false` | true to allow any authentication method, false restricts to password authentication (PasswordProtectedTransport) method (default: false) |
|
||||||
|
| `CMD_SAML_IDENTIFIERFORMAT` | no example | name identifier format (optional, default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`) |
|
||||||
|
| `CMD_SAML_GROUPATTRIBUTE` | `memberOf` | attribute name for group list (optional) |
|
||||||
|
| `CMD_SAML_REQUIREDGROUPS` | `codimd-users` | group names that allowed (use vertical bar to separate) (optional) |
|
||||||
|
| `CMD_SAML_EXTERNALGROUPS` | `Temporary-staff` | group names that not allowed (use vertical bar to separate) (optional) |
|
||||||
|
| `CMD_SAML_ATTRIBUTE_ID` | `sAMAccountName` | attribute map for `id` (optional, default: NameID of SAML response) |
|
||||||
|
| `CMD_SAML_ATTRIBUTE_USERNAME` | `mailNickname` | attribute map for `username` (optional, default: NameID of SAML response) |
|
||||||
|
| `CMD_SAML_ATTRIBUTE_EMAIL` | `mail` | attribute map for `email` (optional, default: NameID of SAML response if `CMD_SAML_IDENTIFIERFORMAT` is default) |
|
||||||
|
|
||||||
|
|
||||||
|
### Twitter Login
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_TWITTER_CONSUMERKEY` | no example | Twitter API consumer key |
|
||||||
|
| `CMD_TWITTER_CONSUMERSECRET` | no example | Twitter API consumer secret |
|
||||||
|
|
||||||
|
|
||||||
|
## Upload Storage
|
||||||
|
|
||||||
|
These are only relevant when they are also configured in sync with their
|
||||||
|
`CMD_IMAGE_UPLOAD_TYPE`. Also keep in mind, that `filesystem` is available, so
|
||||||
|
you don't have to use either of these.
|
||||||
|
|
||||||
|
|
||||||
|
### Amazon S3
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_S3_ACCESS_KEY_ID` | no example | AWS access key id |
|
||||||
|
| `CMD_S3_SECRET_ACCESS_KEY` | no example | AWS secret key |
|
||||||
|
| `CMD_S3_REGION` | `ap-northeast-1` | AWS S3 region |
|
||||||
|
| `CMD_S3_BUCKET` | no example | AWS S3 bucket name |
|
||||||
|
|
||||||
|
|
||||||
|
### Azure Blob Storage
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_AZURE_CONNECTION_STRING` | no example | Azure Blob Storage connection string |
|
||||||
|
| `CMD_AZURE_CONTAINER` | no example | Azure Blob Storage container name (automatically created if non existent) |
|
||||||
|
|
||||||
|
|
||||||
|
### imgur
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_IMGUR_CLIENTID` | no example | Imgur API client id |
|
||||||
|
|
||||||
|
|
||||||
|
### Minio
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_MINIO_ACCESS_KEY` | no example | Minio access key |
|
||||||
|
| `CMD_MINIO_SECRET_KEY` | no example | Minio secret key |
|
||||||
|
| `CMD_MINIO_ENDPOINT` | `minio.example.org` | Address of your Minio endpoint/instance |
|
||||||
|
| `CMD_MINIO_PORT` | `9000` | Port that is used for your Minio instance |
|
||||||
|
| `CMD_MINIO_SECURE` | `true` | If set to `true` HTTPS is used for Minio |
|
||||||
|
|
||||||
|
|
||||||
|
### Lutim
|
||||||
|
|
||||||
|
| variable | example value | description |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| `CMD_LUTIM_URL` | `https://framapic.org/` | When `CMD_IMAGE_UPLOAD_TYPE` is set to `lutim`, you can setup the lutim url |
|
||||||
|
|
||||||
|
**Note:** *Due to the rename process we renamed all `HMD_`-prefix variables to be `CMD_`-prefixed. The old ones continue to work.*
|
||||||
|
|
||||||
|
**Note:** *relative paths are based on CodiMD's base directory*
|
57
docs/dev/getting-started.md
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
Developer Notes
|
||||||
|
===
|
||||||
|
|
||||||
|
## Preparing for running the code
|
||||||
|
|
||||||
|
**Notice:** *There's [specialised instructions for docker](../setup/docker.md) or [heroku](../setup/heroku.md), if you prefer running code this way!*
|
||||||
|
|
||||||
|
1. Clone the repository with `git clone https://github.com/codimd/server.git codimd-server`
|
||||||
|
(cloning is the preferred way, but you can also download and unzip a release)
|
||||||
|
2. Enter the directory and run `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 [config file](../configuration-config-file.md) or set up
|
||||||
|
[environment variables](../configuration-env-vars.md).
|
||||||
|
|
||||||
|
|
||||||
|
## Running the Code
|
||||||
|
|
||||||
|
Now that everything is in place, we can start CodiMD:
|
||||||
|
|
||||||
|
4. `npm run build` will build the frontend bundle. It uses webpack to do that.
|
||||||
|
5. Run the server with `node app.js`
|
||||||
|
|
||||||
|
|
||||||
|
## Running the Code with Auto-Reload
|
||||||
|
|
||||||
|
The commands above are fine for production, but you're a developer and surely
|
||||||
|
you want to change things. You would need to restart both commands whenever you
|
||||||
|
change something. Luckily, you can run these commands that will automatically
|
||||||
|
rebuild the frontend or restart the server if necessary.
|
||||||
|
|
||||||
|
The commands will stay active in your terminal, so you will need multiple tabs
|
||||||
|
to run both at the same time.
|
||||||
|
|
||||||
|
4. Use `npm run dev` if you want webpack to continuously rebuild the frontend
|
||||||
|
code.
|
||||||
|
5. To auto-reload the server, the easiest method is to install [nodemon](https://www.npmjs.com/package/nodemon)
|
||||||
|
and run `nodemon --watch app.js --watch lib --watch locales app.js`.
|
||||||
|
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
The repository contains two parts: a server (backend) and a client (frontend).
|
||||||
|
most of the server code is in `/lib` and most of the client code is in `public`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
codimd-server/
|
||||||
|
├── docs/ --- documentation
|
||||||
|
├── lib/ --- server code
|
||||||
|
├── test/ --- test suite
|
||||||
|
└── public/ --- client code
|
||||||
|
├── css/ --- css styles
|
||||||
|
├── docs/ --- default documents
|
||||||
|
├── js/ --- js scripts
|
||||||
|
├── vendor/ --- vendor includes
|
||||||
|
└── views/ --- view templates
|
||||||
|
```
|
14
docs/dev/ot.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Operational Transformation
|
||||||
|
===
|
||||||
|
|
||||||
|
From 0.3.2, we started supporting operational transformation.
|
||||||
|
It makes concurrent editing safe and will not break up other users' operations.
|
||||||
|
Additionally, now can show other clients' selections.
|
||||||
|
|
||||||
|
See more at [https://operational-transformation.github.io/](https://operational-transformation.github.io/)
|
||||||
|
|
||||||
|
And even more in this 2010 article series:
|
||||||
|
|
||||||
|
* https://drive.googleblog.com/2010/09/whats-different-about-new-google-docs_21.html
|
||||||
|
* https://drive.googleblog.com/2010/09/whats-different-about-new-google-docs_22.html
|
||||||
|
* https://drive.googleblog.com/2010/09/whats-different-about-new-google-docs.html
|
|
@ -1,4 +1,11 @@
|
||||||
# Webpack Docs
|
Webpack
|
||||||
|
===
|
||||||
|
|
||||||
|
Webpack is a JavaScript build system for frontend code. You can find out all
|
||||||
|
about it on [the webpack website](https://webpack.js.org/).
|
||||||
|
|
||||||
|
Here's how we're using it:
|
||||||
|
|
||||||
## `webpack.common.js`
|
## `webpack.common.js`
|
||||||
This file contains all common definition for chunks and plugins, that are needed by the whole app.
|
This file contains all common definition for chunks and plugins, that are needed by the whole app.
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
Authentication guide - GitHub
|
Authentication guide - GitHub
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. Sign-in or sign-up for a GitHub account
|
1. Sign-in or sign-up for a GitHub account
|
||||||
2. Navigate to developer settings in your GitHub account [here](https://github.com/settings/developers) and select the "OAuth Apps" tab
|
2. Navigate to developer settings in your GitHub account [here](https://github.com/settings/developers) and select the "OAuth Apps" tab
|
||||||
3. Click on the **New OAuth App** button, to create a new OAuth App:
|
3. Click on the **New OAuth App** button, to create a new OAuth App:
|
||||||
|
![create-oauth-app](../../images/auth/create-oauth-app.png)
|
||||||
![create-oauth-app](../images/auth/create-oauth-app.png)
|
|
||||||
|
|
||||||
4. Fill out the new OAuth application registration form, and click **Register Application**
|
4. Fill out the new OAuth application registration form, and click **Register Application**
|
||||||
|
![register-oauth-application-form](../../images/auth/register-oauth-application-form.png)
|
||||||
|
|
||||||
![register-oauth-application-form](../images/auth/register-oauth-application-form.png)
|
**Note:** *The callback URL is <your-codimd-url>/auth/github/callback*
|
||||||
|
|
||||||
*Note: The callback URL is <your-hackmd-url>/auth/github/callback*
|
|
||||||
|
|
||||||
5. After successfully registering the application, you'll receive the Client ID and Client Secret for the application
|
5. After successfully registering the application, you'll receive the Client ID and Client Secret for the application
|
||||||
|
![application-page](../../images/auth/application-page.png)
|
||||||
![application-page](../images/auth/application-page.png)
|
|
||||||
|
|
||||||
6. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
|
6. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```js
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"github": {
|
"github": {
|
||||||
|
@ -30,9 +27,9 @@ Authentication guide - GitHub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables:
|
* environment variables:
|
||||||
````
|
```sh
|
||||||
HMD_GITHUB_CLIENTID=3747d30eaccXXXXXXXXX
|
CMD_GITHUB_CLIENTID=3747d30eaccXXXXXXXXX
|
||||||
HMD_GITHUB_CLIENTSECRET=2a8e682948eee0c580XXXXXXXXXXXXXXXXXXXXXX
|
CMD_GITHUB_CLIENTSECRET=2a8e682948eee0c580XXXXXXXXXXXXXXXXXXXXXX
|
||||||
````
|
````
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
# GitLab (self-hosted)
|
GitLab (self-hosted)
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. Sign in to your GitLab
|
1. Sign in to your GitLab
|
||||||
2. Navigate to the application management page at `https://your.gitlab.domain/admin/applications` (admin permissions required)
|
2. Navigate to the application management page at `https://your.gitlab.domain/admin/applications` (admin permissions required)
|
||||||
3. Click **New application** to create a new application and fill out the registration form:
|
3. Click **New application** to create a new application and fill out the registration form:
|
||||||
|
|
||||||
![New GitLab application](../images/auth/gitlab-new-application.png)
|
![New GitLab application](../../images/auth/gitlab-new-application.png)
|
||||||
|
|
||||||
4. Click **Submit**
|
4. Click **Submit**
|
||||||
5. In the list of applications select **HackMD**. Leave that site open to copy the application ID and secret in the next step.
|
5. In the list of applications select **HackMD**. Leave that site open to copy the application ID and secret in the next step.
|
||||||
|
|
||||||
![Application: HackMD](../images/auth/gitlab-application-details.png)
|
![Application: HackMD](../../images/auth/gitlab-application-details.png)
|
||||||
|
|
||||||
|
|
||||||
6. In the `docker-compose.yml` add the following environment variables to `app:` `environment:`
|
6. In the `docker-compose.yml` add the following environment variables to `app:` `environment:`
|
||||||
|
|
||||||
```
|
```
|
||||||
- HMD_DOMAIN=your.hackmd.domain
|
- HMD_DOMAIN=your.codimd.domain
|
||||||
- HMD_URL_ADDPORT=443
|
- HMD_URL_ADDPORT=443
|
||||||
- HMD_PROTOCOL_USESSL=true
|
- HMD_PROTOCOL_USESSL=true
|
||||||
- HMD_GITLAB_BASEURL=https://your.gitlab.domain
|
- HMD_GITLAB_BASEURL=https://your.gitlab.domain
|
||||||
|
@ -27,6 +27,6 @@
|
||||||
```
|
```
|
||||||
|
|
||||||
7. Run `docker-compose up -d` to apply your settings.
|
7. Run `docker-compose up -d` to apply your settings.
|
||||||
8. Sign in to your HackMD using your GitLab ID:
|
8. Sign in to your CodiMD using your GitLab ID:
|
||||||
|
|
||||||
![Sign in via GitLab](../images/auth/gitlab-sign-in.png)
|
![Sign in via GitLab](../../images/auth/gitlab-sign-in.png)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
AD LDAP auth
|
AD LDAP auth
|
||||||
===
|
===
|
||||||
|
|
||||||
|
|
||||||
To setup your CodiMD instance with Active Directory you need the following configs:
|
To setup your CodiMD instance with Active Directory you need the following configs:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
Authentication guide - Mattermost (self-hosted)
|
Authentication guide - Mattermost (self-hosted)
|
||||||
===
|
===
|
||||||
|
|
||||||
*Note: The Mattermost setup portion of this document is just a quick guide. See the [official documentation](https://docs.mattermost.com/developer/oauth-2-0-applications.html) for more details.*
|
**Note:** *The Mattermost setup portion of this document is just a quick guide. See the [official documentation](https://docs.mattermost.com/developer/oauth-2-0-applications.html) for more details.*
|
||||||
|
|
||||||
This guide uses the generic OAuth2 module for compatibility with Mattermost version 5.0 and above.
|
This guide uses the generic OAuth2 module for compatibility with Mattermost version 5.0 and above.
|
||||||
|
|
||||||
1. Sign-in with an administrator account to your Mattermost instance
|
1. Sign-in with an administrator account to your Mattermost instance
|
||||||
2. Make sure **OAuth 2.0 Service Provider** is enabled in the Main Menu (menu button next to your username in the top left corner) --> System Console --> Custom Integrations menu, which you can find at `https://your.mattermost.domain/admin_console/integrations/custom`
|
2. Make sure **OAuth 2.0 Service Provider** is enabled in the Main Menu (menu button next to your username in the top left corner) --> System Console --> Custom Integrations menu, which you can find at `https://your.mattermost.domain/admin_console/integrations/custom`
|
||||||
|
![mattermost-enable-oauth2](../../images/auth/mattermost-enable-oauth2.png)
|
||||||
![mattermost-enable-oauth2](../images/auth/mattermost-enable-oauth2.png)
|
|
||||||
|
|
||||||
3. Navigate to the OAuth integration settings through Main Menu --> Integrations --> OAuth 2.0 Applications, at `https://your.mattermost.domain/yourteam/integrations/oauth2-apps`
|
3. Navigate to the OAuth integration settings through Main Menu --> Integrations --> OAuth 2.0 Applications, at `https://your.mattermost.domain/yourteam/integrations/oauth2-apps`
|
||||||
4. Click on the **Add OAuth 2.0 Application** button to add a new OAuth application
|
4. Click on the **Add OAuth 2.0 Application** button to add a new OAuth application
|
||||||
|
![mattermost-oauth-app-add](../../images/auth/mattermost-oauth-app-add.png)
|
||||||
![mattermost-oauth-app-add](../images/auth/mattermost-oauth-app-add.png)
|
|
||||||
|
|
||||||
5. Fill out the form and click **Save**
|
5. Fill out the form and click **Save**
|
||||||
|
![mattermost-oauth-app-form](../../images/auth/mattermost-oauth-app-form.png)
|
||||||
![mattermost-oauth-app-form](../images/auth/mattermost-oauth-app-form.png)
|
|
||||||
|
|
||||||
*Note: The callback URL is \<your-codimd-url\>/auth/oauth2/callback*
|
*Note: The callback URL is \<your-codimd-url\>/auth/oauth2/callback*
|
||||||
|
|
||||||
6. After saving the application, you'll receive the Client ID and Client Secret
|
6. After saving the application, you'll receive the Client ID and Client Secret
|
||||||
|
![mattermost-oauth-app-done](../../images/auth/mattermost-oauth-app-done.png)
|
||||||
![mattermost-oauth-app-done](../images/auth/mattermost-oauth-app-done.png)
|
|
||||||
|
|
||||||
7. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
|
7. Add the Client ID and Client Secret to your config.json file or pass them as environment variables
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"oauth2": {
|
"oauth2": {
|
||||||
|
@ -43,9 +39,9 @@ This guide uses the generic OAuth2 module for compatibility with Mattermost vers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables:
|
* environment variables:
|
||||||
````
|
```sh
|
||||||
CMD_OAUTH2_BASEURL=https://your.mattermost.domain
|
CMD_OAUTH2_BASEURL=https://your.mattermost.domain
|
||||||
CMD_OAUTH2_USER_PROFILE_URL=https://your.mattermost.domain/api/v4/users/me
|
CMD_OAUTH2_USER_PROFILE_URL=https://your.mattermost.domain/api/v4/users/me
|
||||||
CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=id
|
CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR=id
|
||||||
|
@ -55,4 +51,4 @@ This guide uses the generic OAuth2 module for compatibility with Mattermost vers
|
||||||
CMD_OAUTH2_AUTHORIZATION_URL=https://your.mattermost.domain/oauth/authorize
|
CMD_OAUTH2_AUTHORIZATION_URL=https://your.mattermost.domain/oauth/authorize
|
||||||
CMD_OAUTH2_CLIENT_ID=ii4p1u3jz7dXXXXXXXXXXXXXXX
|
CMD_OAUTH2_CLIENT_ID=ii4p1u3jz7dXXXXXXXXXXXXXXX
|
||||||
CMD_OAUTH2_CLIENT_SECRET=mqzzx6fydbXXXXXXXXXXXXXXXX
|
CMD_OAUTH2_CLIENT_SECRET=mqzzx6fydbXXXXXXXXXXXXXXXX
|
||||||
````
|
```
|
||||||
|
|
|
@ -10,14 +10,14 @@ This guide uses the generic OAuth2 module for compatibility with Nextcloud 13 an
|
||||||
2. Navigate to the OAuth integration settings: Profile Icon (top right) --> Settings
|
2. Navigate to the OAuth integration settings: Profile Icon (top right) --> Settings
|
||||||
Then choose Security Settings from the *Administration* part of the list - Don't confuse this with Personal Security Settings, where you would change your personal password!
|
Then choose Security Settings from the *Administration* part of the list - Don't confuse this with Personal Security Settings, where you would change your personal password!
|
||||||
At the top there's OAuth 2.0-Clients.
|
At the top there's OAuth 2.0-Clients.
|
||||||
![Where to find OAuth2 in Nextcloud](../images/auth/nextcloud-oauth2-1-settings.png)
|
![Where to find OAuth2 in Nextcloud](../../images/auth/nextcloud-oauth2-1-settings.png)
|
||||||
|
|
||||||
3. Add your CodiMD instance by giving it a *name* (perhaps CodiMD, but could be anything) and a *Redirection-URI*. The Redirection-URI will be `\<your-codimd-url\>/auth/oauth2/callback`. Click <kbd>Add</kbd>.
|
3. Add your CodiMD instance by giving it a *name* (perhaps CodiMD, but could be anything) and a *Redirection-URI*. The Redirection-URI will be `\<your-codimd-url\>/auth/oauth2/callback`. Click <kbd>Add</kbd>.
|
||||||
![Adding a client to Nextcloud](../images/auth/nextcloud-oauth2-2-client-add.png)
|
![Adding a client to Nextcloud](../../images/auth/nextcloud-oauth2-2-client-add.png)
|
||||||
|
|
||||||
|
|
||||||
4. You'll now see a line containing a *client identifier* and a *Secret*.
|
4. You'll now see a line containing a *client identifier* and a *Secret*.
|
||||||
![Successfully added OAuth2-client](../images/auth/nextcloud-oauth2-3-clientid-secret.png)
|
![Successfully added OAuth2-client](../../images/auth/nextcloud-oauth2-3-clientid-secret.png)
|
||||||
|
|
||||||
5. That's it for Nextcloud, the rest is configured in your CodiMD `config.json` or via the `CMD_` environment variables!
|
5. That's it for Nextcloud, the rest is configured in your CodiMD `config.json` or via the `CMD_` environment variables!
|
||||||
|
|
||||||
|
|
12
docs/guides/auth/oauth.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# OAuth general information
|
||||||
|
|
||||||
|
| service | callback URL (after the server URL) |
|
||||||
|
| ------- | --------- |
|
||||||
|
| facebook | `/auth/facebook/callback` |
|
||||||
|
| twitter | `/auth/twitter/callback` |
|
||||||
|
| github | `/auth/github/callback` |
|
||||||
|
| gitlab | `/auth/gitlab/callback` |
|
||||||
|
| mattermost | `/auth/mattermost/callback` |
|
||||||
|
| dropbox | `/auth/dropbox/callback` |
|
||||||
|
| google | `/auth/google/callback` |
|
||||||
|
| saml | `/auth/saml/callback` |
|
|
@ -1,40 +1,35 @@
|
||||||
Authentication guide - SAML (OneLogin)
|
Authentication guide - SAML (OneLogin)
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. Sign-in or sign-up for an OneLogin account. (available free trial for 2 weeks)
|
1. Sign-in or sign-up for an OneLogin account. (available free trial for 2 weeks)
|
||||||
2. Go to the administration page.
|
2. Go to the administration page.
|
||||||
3. Select the **APPS** menu and click on the **Add Apps**.
|
3. Select the **APPS** menu and click on the **Add Apps**.
|
||||||
|
![onelogin-add-app](../../images/auth/onelogin-add-app.png)
|
||||||
![onelogin-add-app](../images/auth/onelogin-add-app.png)
|
|
||||||
|
|
||||||
4. Find "SAML Test Connector (SP)" for template of settings and select it.
|
4. Find "SAML Test Connector (SP)" for template of settings and select it.
|
||||||
|
![onelogin-select-template](../../images/auth/onelogin-select-template.png)
|
||||||
![onelogin-select-template](../images/auth/onelogin-select-template.png)
|
|
||||||
|
|
||||||
5. Edit display name and icons for OneLogin dashboard as you want, and click **SAVE**.
|
5. Edit display name and icons for OneLogin dashboard as you want, and click **SAVE**.
|
||||||
|
![onelogin-edit-app-name](../../images/auth/onelogin-edit-app-name.png)
|
||||||
![onelogin-edit-app-name](../images/auth/onelogin-edit-app-name.png)
|
|
||||||
|
|
||||||
6. After that other tabs will appear, click the **Configuration**, and fill out the below items, and click **SAVE**.
|
6. After that other tabs will appear, click the **Configuration**, and fill out the below items, and click **SAVE**.
|
||||||
* RelayState: The base URL of your hackmd, which is issuer. (last slash is not needed)
|
* RelayState: The base URL of your CodiMD, which is issuer. (last slash is not needed)
|
||||||
* ACS (Consumer) URL Validator: The callback URL of your hackmd. (serverurl + /auth/saml/callback)
|
* ACS (Consumer) URL Validator: The callback URL of your CodiMD. (serverurl + /auth/saml/callback)
|
||||||
* ACS (Consumer) URL: same as above.
|
* ACS (Consumer) URL: same as above.
|
||||||
* Login URL: login URL(SAML requester) of your hackmd. (serverurl + /auth/saml)
|
* Login URL: login URL(SAML requester) of your CopiMD. (serverurl + /auth/saml)
|
||||||
|
![onelogin-edit-sp-metadata](../../images/auth/onelogin-edit-sp-metadata.png)
|
||||||
![onelogin-edit-sp-metadata](../images/auth/onelogin-edit-sp-metadata.png)
|
|
||||||
|
|
||||||
7. The registration is completed. Next, click **SSO** and copy or download the items below.
|
7. The registration is completed. Next, click **SSO** and copy or download the items below.
|
||||||
* X.509 Certificate: Click **View Details** and **DOWNLOAD** or copy the content of certificate ....(A)
|
* X.509 Certificate: Click **View Details** and **DOWNLOAD** or copy the content of certificate ....(A)
|
||||||
* SAML 2.0 Endpoint (HTTP): Copy the URL ....(B)
|
* SAML 2.0 Endpoint (HTTP): Copy the URL ....(B)
|
||||||
|
![onelogin-copy-idp-metadata](../../images/auth/onelogin-copy-idp-metadata.png)
|
||||||
|
|
||||||
![onelogin-copy-idp-metadata](../images/auth/onelogin-copy-idp-metadata.png)
|
8. In your CodiMD server, create IdP certificate file from (A)
|
||||||
|
|
||||||
8. In your hackmd server, create IdP certificate file from (A)
|
|
||||||
9. Add the IdP URL (B) and the Idp certificate file path to your config.json file or pass them as environment variables.
|
9. Add the IdP URL (B) and the Idp certificate file path to your config.json file or pass them as environment variables.
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"saml": {
|
"saml": {
|
||||||
|
@ -43,12 +38,11 @@ Authentication guide - SAML (OneLogin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables
|
* environment variables
|
||||||
````
|
```sh
|
||||||
HMD_SAML_IDPSSOURL=https://*******.onelogin.com/trust/saml2/http-post/sso/******
|
CMD_SAML_IDPSSOURL=https://*******.onelogin.com/trust/saml2/http-post/sso/******
|
||||||
HMD_SAML_IDPCERT=/path/to/idp_cert.pem
|
CMD_SAML_IDPCERT=/path/to/idp_cert.pem
|
||||||
````
|
```
|
||||||
10. Try sign-in with SAML from your hackmd sign-in button or OneLogin dashboard (like the screenshot below).
|
10. Try sign-in with SAML from your CodiMD sign-in button or OneLogin dashboard (like the screenshot below).
|
||||||
|
![onelogin-use-dashboard](../../images/auth/onelogin-use-dashboard.png)
|
||||||
![onelogin-use-dashboard](../images/auth/onelogin-use-dashboard.png)
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Authentication guide - SAML
|
Authentication guide - SAML
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
The basic procedure is the same as the case of OneLogin which is mentioned in [OneLogin-Guide](./saml-onelogin.md). If you want to match your IdP, you can use more configurations as below.
|
The basic procedure is the same as the case of OneLogin which is mentioned in [OneLogin-Guide](./saml-onelogin.md). If you want to match your IdP, you can use more configurations as below.
|
||||||
|
|
||||||
|
@ -9,36 +9,36 @@ The basic procedure is the same as the case of OneLogin which is mentioned in [O
|
||||||
* {{your-serverurl}}/auth/saml/metadata
|
* {{your-serverurl}}/auth/saml/metadata
|
||||||
* _Note: If not accessible from IdP, download to local once and upload to IdP._
|
* _Note: If not accessible from IdP, download to local once and upload to IdP._
|
||||||
* Change the value of `issuer`, `identifierFormat` to match your IdP.
|
* Change the value of `issuer`, `identifierFormat` to match your IdP.
|
||||||
* `issuer`: A unique id to identify the application to the IdP, which is the base URL of your HackMD as default
|
* `issuer`: A unique id to identify the application to the IdP, which is the base URL of your CodiMD as default
|
||||||
* `identifierFormat`: A format of unique id to identify the user of IdP, which is the format based on email address as default. It is recommend that you use as below.
|
* `identifierFormat`: A format of unique id to identify the user of IdP, which is the format based on email address as default. It is recommend that you use as below.
|
||||||
* urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress (default)
|
* urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress (default)
|
||||||
* urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
|
* urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"saml": {
|
"saml": {
|
||||||
/* omitted */
|
/* omitted */
|
||||||
"issuer": "myhackmd"
|
"issuer": "mycodimd"
|
||||||
"identifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
"identifierFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables
|
* environment variables
|
||||||
````
|
```
|
||||||
HMD_SAML_ISSUER=myhackmd
|
CMD_SAML_ISSUER=mycodimd
|
||||||
HMD_SAML_IDENTIFIERFORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
|
CMD_SAML_IDENTIFIERFORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
|
||||||
````
|
```
|
||||||
|
|
||||||
* Change mapping of attribute names to customize the displaying user name and email address to match your IdP.
|
* Change mapping of attribute names to customize the displaying user name and email address to match your IdP.
|
||||||
* `attribute`: A dictionary to map attribute names
|
* `attribute`: A dictionary to map attribute names
|
||||||
* `attribute.id`: A primary key of user table for your HackMD
|
* `attribute.id`: A primary key of user table for your CodiMD
|
||||||
* `attribute.username`: Attribute name of displaying user name on HackMD
|
* `attribute.username`: Attribute name of displaying user name on CodiMD
|
||||||
* `attribute.email`: Attribute name of email address, which will be also used for Gravatar
|
* `attribute.email`: Attribute name of email address, which will be also used for Gravatar
|
||||||
* _Note: Default value of all attributes is NameID of SAML response, which is email address if `identifierFormat` is default._
|
* _Note: Default value of all attributes is NameID of SAML response, which is email address if `identifierFormat` is default._
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"saml": {
|
"saml": {
|
||||||
|
@ -51,35 +51,35 @@ The basic procedure is the same as the case of OneLogin which is mentioned in [O
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables
|
* environment variables
|
||||||
````
|
```sh
|
||||||
HMD_SAML_ATTRIBUTE_ID=sAMAccountName
|
CMD_SAML_ATTRIBUTE_ID=sAMAccountName
|
||||||
HMD_SAML_ATTRIBUTE_USERNAME=nickName
|
CMD_SAML_ATTRIBUTE_USERNAME=nickName
|
||||||
HMD_SAML_ATTRIBUTE_EMAIL=mail
|
CMD_SAML_ATTRIBUTE_EMAIL=mail
|
||||||
````
|
```
|
||||||
|
|
||||||
* If you want to control permission by group membership, add group attribute name and required group (allowed) or external group (not allowed).
|
* If you want to control permission by group membership, add group attribute name and required group (allowed) or external group (not allowed).
|
||||||
* `groupAttribute`: An attribute name of group membership
|
* `groupAttribute`: An attribute name of group membership
|
||||||
* `requiredGroups`: Group names array for allowed access to HackMD. Use vertical bar to separate for environment variables.
|
* `requiredGroups`: Group names array for allowed access to CodiMD. Use vertical bar to separate for environment variables.
|
||||||
* `externalGroups`: Group names array for not allowed access to HackMD. Use vertical bar to separate for environment variables.
|
* `externalGroups`: Group names array for not allowed access to CodiMD. Use vertical bar to separate for environment variables.
|
||||||
* _Note: Evaluates `externalGroups` first_
|
* _Note: Evaluates `externalGroups` first_
|
||||||
* config.json:
|
* `config.json`:
|
||||||
````javascript
|
```javascript
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"saml": {
|
"saml": {
|
||||||
/* omitted */
|
/* omitted */
|
||||||
"groupAttribute": "memberOf",
|
"groupAttribute": "memberOf",
|
||||||
"requiredGroups": [ "hackmd-users", "board-members" ],
|
"requiredGroups": [ "codimd-users", "board-members" ],
|
||||||
"externalGroups": [ "temporary-staff" ]
|
"externalGroups": [ "temporary-staff" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables
|
* environment variables
|
||||||
````
|
```sh
|
||||||
HMD_SAML_GROUPATTRIBUTE=memberOf
|
CMD_SAML_GROUPATTRIBUTE=memberOf
|
||||||
HMD_SAML_REQUIREDGROUPS=hackmd-users|board-members
|
CMD_SAML_REQUIREDGROUPS=codimd-users|board-members
|
||||||
HMD_SAML_EXTERNALGROUPS=temporary-staff
|
CMD_SAML_EXTERNALGROUPS=temporary-staff
|
||||||
````
|
```
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
Authentication guide - Twitter
|
Authentication guide - Twitter
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. Sign-in or sign-up for a Twitter account
|
1. Sign-in or sign-up for a Twitter account
|
||||||
2. Go to the Twitter Application management page [here](https://apps.twitter.com/)
|
2. Go to the Twitter Application management page [here](https://apps.twitter.com/)
|
||||||
3. Click on the **Create New App** button to create a new Twitter app:
|
3. Click on the **Create New App** button to create a new Twitter app:
|
||||||
|
![create-twitter-app](../../images/auth/create-twitter-app.png)
|
||||||
![create-twitter-app](../images/auth/create-twitter-app.png)
|
|
||||||
|
|
||||||
4. Fill out the create application form, check the developer agreement box, and click **Create Your Twitter Application**
|
4. Fill out the create application form, check the developer agreement box, and click **Create Your Twitter Application**
|
||||||
|
![register-twitter-application](../../images/auth/register-twitter-application.png)
|
||||||
|
|
||||||
![register-twitter-application](../images/auth/register-twitter-application.png)
|
*Note: you may have to register your phone number with Twitter to create a Twitter application*
|
||||||
|
|
||||||
*Note: you may have to register your phone number with Twitter to create a Twitter application*
|
To do this Click your profile icon --> Settings and privacy --> Mobile --> Select Country/region --> Enter phone number --> Click Continue
|
||||||
|
|
||||||
To do this Click your profile icon --> Settings and privacy --> Mobile --> Select Country/region --> Enter phone number --> Click Continue
|
|
||||||
|
|
||||||
5. After you receive confirmation that the Twitter application was created, click **Keys and Access Tokens**
|
5. After you receive confirmation that the Twitter application was created, click **Keys and Access Tokens**
|
||||||
|
![twitter-app-confirmation](../../images/auth/twitter-app-confirmation.png)
|
||||||
![twitter-app-confirmation](../images/auth/twitter-app-confirmation.png)
|
|
||||||
|
|
||||||
6. Obtain your Twitter Consumer Key and Consumer Secret
|
6. Obtain your Twitter Consumer Key and Consumer Secret
|
||||||
|
![twitter-app-keys](../../images/auth/twitter-app-keys.png)
|
||||||
|
|
||||||
![twitter-app-keys](../images/auth/twitter-app-keys.png)
|
7. Add your Consumer Key and Consumer Secret to your `config.json` file or pass them as environment variables:
|
||||||
|
* `config.json`:
|
||||||
7. Add your Consumer Key and Consumer Secret to your config.json file or pass them as environment variables:
|
```javascript
|
||||||
* config.json:
|
|
||||||
````javascript
|
|
||||||
{
|
{
|
||||||
"production": {
|
"production": {
|
||||||
"twitter": {
|
"twitter": {
|
||||||
|
@ -36,9 +32,9 @@ To do this Click your profile icon --> Settings and privacy --> Mobile --> Sele
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
````
|
```
|
||||||
* environment variables:
|
* environment variables:
|
||||||
````
|
```sh
|
||||||
HMD_TWITTER_CONSUMERKEY=esTCJFXXXXXXXXXXXXXXXXXXX
|
CMD_TWITTER_CONSUMERKEY=esTCJFXXXXXXXXXXXXXXXXXXX
|
||||||
HMD_TWITTER_CONSUMERSECRET=zpCs4tU86pRVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
CMD_TWITTER_CONSUMERSECRET=zpCs4tU86pRVXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
````
|
```
|
||||||
|
|
|
@ -12,7 +12,7 @@ require some creativity to work properly in your case. When I wrote this guide,
|
||||||
[Etherpad 1.7.0] and [CodiMD 1.2.1]. Good luck!
|
[Etherpad 1.7.0] and [CodiMD 1.2.1]. Good luck!
|
||||||
|
|
||||||
[Etherpad 1.7.0]: https://github.com/ether/etherpad-lite/tree/1.7.0
|
[Etherpad 1.7.0]: https://github.com/ether/etherpad-lite/tree/1.7.0
|
||||||
[CodiMD 1.2.1]: https://github.com/hackmdio/codimd/tree/1.2.1
|
[CodiMD 1.2.1]: https://github.com/codimd/server/tree/1.2.1
|
||||||
|
|
||||||
## 0. Requirements
|
## 0. Requirements
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ require some creativity to work properly in your case. When I wrote this guide,
|
||||||
- running CodiMD server
|
- running CodiMD server
|
||||||
- [codimd-cli]
|
- [codimd-cli]
|
||||||
|
|
||||||
[codimd-cli]: https://github.com/hackmdio/codimd-cli/blob/master/bin/codimd
|
[codimd-cli]: https://github.com/codimd/cli/blob/master/bin/codimd
|
||||||
|
|
||||||
## 1. Retrieve the list of pads
|
## 1. Retrieve the list of pads
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ configuration settings `ETHERPAD_SERVER` and `CODIMD_SERVER`.
|
||||||
# Author: Daan Sprenkels <hello@dsprenkels.com>
|
# Author: Daan Sprenkels <hello@dsprenkels.com>
|
||||||
|
|
||||||
# This script uses the codimd command line script[1] to import a list of pads from
|
# This script uses the codimd command line script[1] to import a list of pads from
|
||||||
# [1]: https://github.com/hackmdio/codimd-cli/blob/master/bin/codimd
|
# [1]: https://github.com/codimd/cli/blob/master/bin/codimd
|
||||||
|
|
||||||
# The base url to where etherpad is hosted
|
# The base url to where etherpad is hosted
|
||||||
ETHERPAD_SERVER="https://etherpad.example.com"
|
ETHERPAD_SERVER="https://etherpad.example.com"
|
||||||
|
|
52
docs/guides/migrations-and-breaking-changes.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
Migrations and Notable Changes
|
||||||
|
===
|
||||||
|
|
||||||
|
## Migrating to 1.3.2
|
||||||
|
|
||||||
|
This is not a breaking change, but to stay up to date with the community
|
||||||
|
repository, you may need to update a few urls. This is not a breaking change.
|
||||||
|
|
||||||
|
See more at [issue #10](https://github.com/codimd/server/issues/10)
|
||||||
|
|
||||||
|
**Native setup using git:**
|
||||||
|
|
||||||
|
Change the upstream remote using `git remote set-url origin https://github.com/codimd/server.git`.
|
||||||
|
|
||||||
|
**Docker:**
|
||||||
|
|
||||||
|
When you use our [container repository](https://github.com/codimd/container)
|
||||||
|
(which was previously `codimd-container`) all you can simply run `git pull` and
|
||||||
|
your `docker-compose.yml` will be updated.
|
||||||
|
|
||||||
|
When you setup things yourself, make sure you use the new image:
|
||||||
|
[`quay.io/codimd/server`](https://quay.io/repository/codimd/server?tab=tags).
|
||||||
|
|
||||||
|
**Heroku:**
|
||||||
|
|
||||||
|
All you need to do is [disconnect GitHub](https://devcenter.heroku.com/articles/github-integration#disconnecting-from-github)
|
||||||
|
and [reconnect it](https://devcenter.heroku.com/articles/github-integration#enabling-github-integration)
|
||||||
|
with this new repository.
|
||||||
|
|
||||||
|
Or you can use our Heroku button and redeploy your instance and link the old
|
||||||
|
database again.
|
||||||
|
|
||||||
|
## Migrating to 1.1.0
|
||||||
|
|
||||||
|
We deprecated the older lower case config style and moved on to camel case style. Please have a look at the current `config.json.example` and check the warnings on startup.
|
||||||
|
|
||||||
|
*Notice: This is not a breaking change right now but will be in the future*
|
||||||
|
|
||||||
|
## Migrating to 0.5.0
|
||||||
|
|
||||||
|
[migration-to-0.5.0 migration tool](https://github.com/hackmdio/migration-to-0.5.0)
|
||||||
|
|
||||||
|
We don't use LZString to compress socket.io data and DB data after version 0.5.0.
|
||||||
|
Please run the migration tool if you're upgrading from the old version.
|
||||||
|
|
||||||
|
## Migrating to 0.4.0
|
||||||
|
|
||||||
|
[migration-to-0.4.0 migration tool](https://github.com/hackmdio/migration-to-0.4.0)
|
||||||
|
|
||||||
|
We've dropped MongoDB after version 0.4.0.
|
||||||
|
So here is the migration tool for you to transfer the old DB data to the new DB.
|
||||||
|
This tool is also used for official service.
|
|
@ -1,7 +1,7 @@
|
||||||
Minio Guide for CodiMD
|
Minio Guide for CodiMD
|
||||||
===
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. First of all you need to setup Minio itself.
|
1. First of all you need to setup Minio itself.
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ Minio Guide for CodiMD
|
||||||
production setup.
|
production setup.
|
||||||
|
|
||||||
For checking it out and development purposes a non-persistent setup is enough:
|
For checking it out and development purposes a non-persistent setup is enough:
|
||||||
```console
|
```sh
|
||||||
docker run --name test-minio --rm -d -p 9000:9000 minio/minio server /data
|
docker run --name test-minio --rm -d -p 9000:9000 minio/minio server /data
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -18,29 +18,29 @@ Minio Guide for CodiMD
|
||||||
|
|
||||||
2. Next step is to get the credentials form the container:
|
2. Next step is to get the credentials form the container:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
docker logs test-minio
|
docker logs test-minio
|
||||||
```
|
```
|
||||||
|
|
||||||
![docker logs](images/minio-image-upload/docker-logs.png)
|
![docker logs](../images/minio-image-upload/docker-logs.png)
|
||||||
|
|
||||||
3. Open http://localhost:9000 and login with the shown credentials.
|
3. Open http://localhost:9000 and login with the shown credentials.
|
||||||
|
|
||||||
![minio default view](images/minio-image-upload/default-view.png)
|
![minio default view](../images/minio-image-upload/default-view.png)
|
||||||
|
|
||||||
4. Create a bucket for HackMD
|
4. Create a bucket for CodiMD
|
||||||
|
|
||||||
![minio create bucket](images/minio-image-upload/create-bucket.png)
|
![minio create bucket](../images/minio-image-upload/create-bucket.png)
|
||||||
|
|
||||||
5. Add a policy for the prefix `uploads` and make it read-only.
|
5. Add a policy for the prefix `uploads` and make it read-only.
|
||||||
|
|
||||||
![minio edit policy](images/minio-image-upload/open-edit-policy.png)
|
![minio edit policy](../images/minio-image-upload/open-edit-policy.png)
|
||||||
*Open policy editor*
|
*Open policy editor*
|
||||||
|
|
||||||
![minio policy adding](images/minio-image-upload/create-policy.png)
|
![minio policy adding](../images/minio-image-upload/create-policy.png)
|
||||||
*Add policy for uploads*
|
*Add policy for uploads*
|
||||||
|
|
||||||
6. Set credentials and configs for Minio in HackMD's `config.json`
|
6. Set credentials and configs for Minio in CodiMD's `config.json`
|
||||||
|
|
||||||
```JSON
|
```JSON
|
||||||
"minio": {
|
"minio": {
|
||||||
|
@ -58,7 +58,7 @@ Minio Guide for CodiMD
|
||||||
7. Set bucket name
|
7. Set bucket name
|
||||||
|
|
||||||
```JSON
|
```JSON
|
||||||
"s3bucket": "hackmd"
|
"s3bucket": "codimd"
|
||||||
```
|
```
|
||||||
|
|
||||||
8. Set upload type.
|
8. Set upload type.
|
||||||
|
@ -79,7 +79,7 @@ Minio Guide for CodiMD
|
||||||
"port": 9000,
|
"port": 9000,
|
||||||
"secure": false
|
"secure": false
|
||||||
},
|
},
|
||||||
"s3bucket": "hackmd",
|
"s3bucket": "codimd",
|
||||||
"imageuploadtype": "minio"
|
"imageuploadtype": "minio"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
# Guide - Setup CodiMD S3 image upload
|
Guide - Setup CodiMD S3 image upload
|
||||||
|
===
|
||||||
|
|
||||||
***Note:** This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
**Note:** *This guide was written before the renaming. Just replace `HackMD` with `CodiMD` in your mind :smile: thanks!*
|
||||||
|
|
||||||
1. Go to [AWS S3 console](https://console.aws.amazon.com/s3/home) and create a new bucket.
|
1. Go to [AWS S3 console](https://console.aws.amazon.com/s3/home) and create a new bucket.
|
||||||
|
|
||||||
![create-bucket](images/s3-image-upload/create-bucket.png)
|
![create-bucket](../images/s3-image-upload/create-bucket.png)
|
||||||
|
|
||||||
2. Click on bucket, select **Properties** on the side panel, and find **Permission** section. Click **Edit bucket policy**.
|
2. Click on bucket, select **Properties** on the side panel, and find **Permission** section. Click **Edit bucket policy**.
|
||||||
|
|
||||||
![bucket-property](images/s3-image-upload/bucket-property.png)
|
![bucket-property](../images/s3-image-upload/bucket-property.png)
|
||||||
|
|
||||||
3. Enter the following policy, replace `bucket_name` with your bucket name:
|
3. Enter the following policy, replace `bucket_name` with your bucket name:
|
||||||
|
|
||||||
![bucket-policy-editor](images/s3-image-upload/bucket-policy-editor.png)
|
![bucket-policy-editor](../images/s3-image-upload/bucket-policy-editor.png)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -32,15 +33,15 @@
|
||||||
|
|
||||||
5. Enter user page, select **Permission** tab, look at **Inline Policies** section, and click **Create User Policy**
|
5. Enter user page, select **Permission** tab, look at **Inline Policies** section, and click **Create User Policy**
|
||||||
|
|
||||||
![iam-user](images/s3-image-upload/iam-user.png)
|
![iam-user](../images/s3-image-upload/iam-user.png)
|
||||||
|
|
||||||
6. Select **Custom Policy**
|
6. Select **Custom Policy**
|
||||||
|
|
||||||
![custom-policy](images/s3-image-upload/custom-policy.png)
|
![custom-policy](../images/s3-image-upload/custom-policy.png)
|
||||||
|
|
||||||
7. Enter the following policy, replace `bucket_name` with your bucket name:
|
7. Enter the following policy, replace `bucket_name` with your bucket name:
|
||||||
|
|
||||||
![review-policy](images/s3-image-upload/review-policy.png)
|
![review-policy](../images/s3-image-upload/review-policy.png)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -76,7 +77,7 @@
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
9. In additional to edit `config.json` directly, you could also try [environment variable](https://github.com/hackmdio/hackmd#environment-variables-will-overwrite-other-server-configs).
|
9. In additional to edit `config.json` directly, you could also try [environment variables](../configuration-env-vars.md).
|
||||||
|
|
||||||
## Related Tools
|
## Related Tools
|
||||||
|
|
||||||
|
|
40
docs/history.md
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
History of CodiMD
|
||||||
|
===
|
||||||
|
|
||||||
|
## It started with HackMD
|
||||||
|
|
||||||
|
HackMD is the origin of this project, which was mostly developed by Max Wu and
|
||||||
|
Yukai Huang. Originally, this was open source under MIT license, but was
|
||||||
|
[relicensed in October 2017 to be AGPLv3](https://github.com/hackmdio/codimd/pull/578).
|
||||||
|
At the same time, [hackmd.io](https://hackmd.io) was founded to offer a
|
||||||
|
commercial version of HackMD.
|
||||||
|
|
||||||
|
The AGPLv3-version was developed and released by the community, this was for a
|
||||||
|
while referred to as "HackMD community edition".
|
||||||
|
|
||||||
|
*For more on the splitting of the projects, please refer to [A note to our community (2017-10-11)](https://hackmd.io/c/community-news/https%3A%2F%2Fhackmd.io%2Fs%2Fr1_4j9_hZ).*
|
||||||
|
|
||||||
|
|
||||||
|
## HackMD CE became CodiMD
|
||||||
|
|
||||||
|
In June 2018, CodiMD was renamed from its former name "HackMD" and continued to
|
||||||
|
be developed under AGPLv3 by the community. We decided to change the name to
|
||||||
|
break the confusion between HackMD (enterprise offering) and CodiMD (community
|
||||||
|
project), as people mistook it for an open core development model.
|
||||||
|
|
||||||
|
*For the whole renaming story, see the [issue where the renaming was discussed](https://github.com/hackmdio/hackmd/issues/720).*
|
||||||
|
|
||||||
|
|
||||||
|
## CodiMD went independent
|
||||||
|
|
||||||
|
In March 2019, a discussion over licensing, governance and the future of CodiMD
|
||||||
|
lead to the formation of a distinct GitHub organization. Up to that point, the
|
||||||
|
community project resided in the organization of hackmdio but was for the most
|
||||||
|
part self-organized.
|
||||||
|
|
||||||
|
During that debate, we did not reach an agreement that would have allowed us to
|
||||||
|
move the repository, so we simply forked it. We still welcome the HackMD team
|
||||||
|
as part of our community, especially since a large portion of this code base
|
||||||
|
originated with them.
|
||||||
|
|
||||||
|
*For the debate that lead to this step, please refer to the [governance debate](https://github.com/hackmdio/hackmd/issues/1170) and [the announcement of the new repository](https://github.com/codimd/server/issues/10).*
|
BIN
docs/images/CodiMD-1.3.2-features.png
Normal file
After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 187 KiB After Width: | Height: | Size: 187 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
6
docs/setup/cloudron.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Cloudron
|
||||||
|
===
|
||||||
|
|
||||||
|
Install CodiMD on [Cloudron](https://cloudron.io):
|
||||||
|
|
||||||
|
[![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=io.hackmd.cloudronapp)
|
23
docs/setup/docker.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
CodiMD by docker container
|
||||||
|
===
|
||||||
|
|
||||||
|
[![Try in PWD](https://cdn.rawgit.com/play-with-docker/stacks/cff22438/assets/images/button.png)](http://play-with-docker.com?stack=https://github.com/codimd/container/raw/master/docker-compose.yml&stack_name=codimd)
|
||||||
|
|
||||||
|
|
||||||
|
**Debian-based version:**
|
||||||
|
|
||||||
|
[![Docker Repository on Quay](https://quay.io/repository/codimd/server/status "Docker Repository on Quay")](https://quay.io/repository/codimd/server)
|
||||||
|
|
||||||
|
|
||||||
|
**Alpine-based version:**
|
||||||
|
|
||||||
|
[![Docker Repository on Quay](https://quay.io/repository/codimd/server/status "Docker Repository on Quay")](https://quay.io/repository/codimd/server)
|
||||||
|
|
||||||
|
The easiest way to setup CodiMD using docker are using the following three commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/codimd/container.git
|
||||||
|
cd codimd-container
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
Read more about it in the [container repository](https://github.com/codimd/container).
|
7
docs/setup/heroku.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Heroku Deployment
|
||||||
|
===
|
||||||
|
|
||||||
|
You can quickly setup a sample Heroku CodiMD application by clicking the button
|
||||||
|
below.
|
||||||
|
|
||||||
|
[![Deploy on Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/codimd/server/tree/master)
|
6
docs/setup/kubernetes.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Kubernetes
|
||||||
|
===
|
||||||
|
|
||||||
|
To install use `helm install stable/hackmd`.
|
||||||
|
|
||||||
|
For all further details, please check out the offical CodiMD [K8s helm chart](https://github.com/kubernetes/charts/tree/master/stable/hackmd).
|
39
docs/setup/manual-setup.md
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
Manual Installation
|
||||||
|
===
|
||||||
|
|
||||||
|
## Requirements on your server
|
||||||
|
|
||||||
|
- Node.js 6.x or up (test up to 7.5.0) and <10.x
|
||||||
|
- Database (PostgreSQL, MySQL, MariaDB, SQLite, MSSQL) use charset `utf8`
|
||||||
|
- npm (and its dependencies, [node-gyp](https://github.com/nodejs/node-gyp#installation))
|
||||||
|
- `libssl-dev` for building scrypt (see [here](https://github.com/ml1nk/node-scrypt/blob/master/README.md#installation-instructions) for further information)
|
||||||
|
- For **building** CodiMD we recommend to use a machine with at least **2GB** RAM
|
||||||
|
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
1. Download a release and unzip or clone into a directory
|
||||||
|
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
|
||||||
|
4. Setup environment variables which will overwrite the configs
|
||||||
|
5. Build front-end bundle by `npm run build` (use `npm run dev` if you are in development)
|
||||||
|
6. Modify the file named `.sequelizerc`, change the value of the variable `url` with your db connection string
|
||||||
|
For example: `postgres://username:password@localhost:5432/codimd`
|
||||||
|
7. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema
|
||||||
|
8. Run the server as you like (node, forever, pm2)
|
||||||
|
|
||||||
|
|
||||||
|
## How to upgrade your installation
|
||||||
|
|
||||||
|
:warning: When you are still running from the old repository, please run: `git remote set-url origin https://github.com/codimd/server.git` :warning:
|
||||||
|
|
||||||
|
If you are upgrading CodiMD from an older version, follow these steps:
|
||||||
|
|
||||||
|
1. Fully stop your old server first (important)
|
||||||
|
2. `git pull` or do whatever that updates the files
|
||||||
|
3. `npm install` to update dependencies
|
||||||
|
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
|
||||||
|
For example: `postgres://username:password@localhost:5432/codimd`
|
||||||
|
6. Run `node_modules/.bin/sequelize db:migrate`, this step will migrate your db to the latest schema
|
||||||
|
7. Start your whole new server!
|
161
docs/slide-options.md
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
Slide Separators
|
||||||
|
===
|
||||||
|
|
||||||
|
If you're getting started with reveal.js slides, there are a few things you need to know.
|
||||||
|
|
||||||
|
There are two types of slides, those that transition horizontally and those that transition vertically (subslides).
|
||||||
|
|
||||||
|
The following separators are used for each in the CodiMD syntax:
|
||||||
|
```
|
||||||
|
# First Slide
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Next slide
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Subslide
|
||||||
|
```
|
||||||
|
as you can see, horizontal transitions are separated by `---` and vertical transitions by `----`
|
||||||
|
|
||||||
|
## Basic YAML header
|
||||||
|
It's possible to customise the slide options using the YAML header in the slide markdown.
|
||||||
|
|
||||||
|
eg:
|
||||||
|
```
|
||||||
|
---
|
||||||
|
title: Example Slide
|
||||||
|
tags: presentation
|
||||||
|
slideOptions:
|
||||||
|
theme: solarized
|
||||||
|
transition: 'fade'
|
||||||
|
# parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'
|
||||||
|
---
|
||||||
|
```
|
||||||
|
make sure to have two spaces only at the start of the listed slide options.
|
||||||
|
|
||||||
|
you can comment out options with a `#`
|
||||||
|
|
||||||
|
### Some other options
|
||||||
|
```
|
||||||
|
# Display controls in the bottom right corner
|
||||||
|
controls: true
|
||||||
|
|
||||||
|
# Display a presentation progress bar
|
||||||
|
progress: true
|
||||||
|
|
||||||
|
# Set default timing of 2 minutes per slide
|
||||||
|
defaultTiming: 120
|
||||||
|
|
||||||
|
# Display the page number of the current slide
|
||||||
|
slideNumber: false
|
||||||
|
|
||||||
|
# Push each slide change to the browser history
|
||||||
|
history: false
|
||||||
|
|
||||||
|
# Enable keyboard shortcuts for navigation
|
||||||
|
keyboard: true
|
||||||
|
|
||||||
|
# Enable the slide overview mode
|
||||||
|
overview: true
|
||||||
|
|
||||||
|
# Vertical centering of slides
|
||||||
|
center: true
|
||||||
|
|
||||||
|
# Enables touch navigation on devices with touch input
|
||||||
|
touch: true
|
||||||
|
|
||||||
|
# Loop the presentation
|
||||||
|
loop: false
|
||||||
|
|
||||||
|
# Change the presentation direction to be RTL
|
||||||
|
rtl: false
|
||||||
|
|
||||||
|
# Randomizes the order of slides each time the presentation loads
|
||||||
|
shuffle: false
|
||||||
|
|
||||||
|
# Turns fragments on and off globally
|
||||||
|
fragments: true
|
||||||
|
|
||||||
|
# Flags if the presentation is running in an embedded mode,
|
||||||
|
# i.e. contained within a limited portion of the screen
|
||||||
|
embedded: false
|
||||||
|
|
||||||
|
# Flags if we should show a help overlay when the questionmark
|
||||||
|
# key is pressed
|
||||||
|
help: true
|
||||||
|
|
||||||
|
# Flags if speaker notes should be visible to all viewers
|
||||||
|
showNotes: false
|
||||||
|
|
||||||
|
# Global override for autolaying embedded media (video/audio/iframe)
|
||||||
|
# - null: Media will only autoplay if data-autoplay is present
|
||||||
|
# - true: All media will autoplay, regardless of individual setting
|
||||||
|
# - false: No media will autoplay, regardless of individual setting
|
||||||
|
autoPlayMedia: null
|
||||||
|
|
||||||
|
# Number of milliseconds between automatically proceeding to the
|
||||||
|
# next slide, disabled when set to 0, this value can be overwritten
|
||||||
|
# by using a data-autoslide attribute on your slides
|
||||||
|
autoSlide: 0
|
||||||
|
|
||||||
|
# Stop auto-sliding after user input
|
||||||
|
autoSlideStoppable: true
|
||||||
|
|
||||||
|
# Use this method for navigation when auto-sliding
|
||||||
|
autoSlideMethod: Reveal.navigateNext
|
||||||
|
|
||||||
|
# Enable slide navigation via mouse wheel
|
||||||
|
mouseWheel: false
|
||||||
|
|
||||||
|
# Hides the address bar on mobile devices
|
||||||
|
hideAddressBar: true
|
||||||
|
|
||||||
|
# Opens links in an iframe preview overlay
|
||||||
|
previewLinks: false
|
||||||
|
|
||||||
|
# Transition style
|
||||||
|
transition: 'slide'
|
||||||
|
# none/fade/slide/convex/concave/zoom
|
||||||
|
|
||||||
|
# Transition speed
|
||||||
|
transitionSpeed: 'default'
|
||||||
|
# default/fast/slow
|
||||||
|
|
||||||
|
# Transition style for full page slide backgrounds
|
||||||
|
backgroundTransition: 'fade'
|
||||||
|
# none/fade/slide/convex/concave/zoom
|
||||||
|
|
||||||
|
# Number of slides away from the current that are visible
|
||||||
|
viewDistance: 3
|
||||||
|
|
||||||
|
# Parallax background image
|
||||||
|
parallaxBackgroundImage: ''
|
||||||
|
# e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
|
||||||
|
|
||||||
|
# Parallax background size
|
||||||
|
parallaxBackgroundSize: ''
|
||||||
|
# CSS syntax, e.g. "2100px 900px"
|
||||||
|
|
||||||
|
# Number of pixels to move the parallax background per slide
|
||||||
|
# - Calculated automatically unless specified
|
||||||
|
# - Set to 0 to disable movement along an axis
|
||||||
|
parallaxBackgroundHorizontal: null
|
||||||
|
parallaxBackgroundVertical: null
|
||||||
|
|
||||||
|
# The display mode that will be used to show slides
|
||||||
|
display: 'block'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customising individual slides
|
||||||
|
|
||||||
|
custom background image:
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- .slide: data-background="https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg" -->
|
||||||
|
#### testslide
|
||||||
|
|
||||||
|
---
|
||||||
|
```
|
|
@ -58,8 +58,11 @@ module.exports = {
|
||||||
heartbeatTimeout: 10000,
|
heartbeatTimeout: 10000,
|
||||||
// document
|
// document
|
||||||
documentMaxLength: 100000,
|
documentMaxLength: 100000,
|
||||||
// image upload setting, available options are imgur/s3/filesystem/azure
|
// image upload setting, available options are imgur/s3/filesystem/azure/lutim
|
||||||
imageUploadType: 'filesystem',
|
imageUploadType: 'filesystem',
|
||||||
|
lutim: {
|
||||||
|
url: 'https://framapic.org/'
|
||||||
|
},
|
||||||
imgur: {
|
imgur: {
|
||||||
clientID: undefined
|
clientID: undefined
|
||||||
},
|
},
|
||||||
|
@ -138,6 +141,7 @@ module.exports = {
|
||||||
idpCert: undefined,
|
idpCert: undefined,
|
||||||
issuer: undefined,
|
issuer: undefined,
|
||||||
identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
||||||
|
disableRequestedAuthnContext: false,
|
||||||
groupAttribute: undefined,
|
groupAttribute: undefined,
|
||||||
externalGroups: [],
|
externalGroups: [],
|
||||||
requiredGroups: [],
|
requiredGroups: [],
|
||||||
|
|
|
@ -49,6 +49,9 @@ module.exports = {
|
||||||
secure: toBooleanConfig(process.env.CMD_MINIO_SECURE),
|
secure: toBooleanConfig(process.env.CMD_MINIO_SECURE),
|
||||||
port: toIntegerConfig(process.env.CMD_MINIO_PORT)
|
port: toIntegerConfig(process.env.CMD_MINIO_PORT)
|
||||||
},
|
},
|
||||||
|
lutim: {
|
||||||
|
url: process.env.CMD_LUTIM_URL
|
||||||
|
},
|
||||||
s3bucket: process.env.CMD_S3_BUCKET,
|
s3bucket: process.env.CMD_S3_BUCKET,
|
||||||
azure: {
|
azure: {
|
||||||
connectionString: process.env.CMD_AZURE_CONNECTION_STRING,
|
connectionString: process.env.CMD_AZURE_CONNECTION_STRING,
|
||||||
|
@ -115,6 +118,7 @@ module.exports = {
|
||||||
idpCert: process.env.CMD_SAML_IDPCERT,
|
idpCert: process.env.CMD_SAML_IDPCERT,
|
||||||
issuer: process.env.CMD_SAML_ISSUER,
|
issuer: process.env.CMD_SAML_ISSUER,
|
||||||
identifierFormat: process.env.CMD_SAML_IDENTIFIERFORMAT,
|
identifierFormat: process.env.CMD_SAML_IDENTIFIERFORMAT,
|
||||||
|
disableRequestedAuthnContext: toBooleanConfig(process.env.CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT),
|
||||||
groupAttribute: process.env.CMD_SAML_GROUPATTRIBUTE,
|
groupAttribute: process.env.CMD_SAML_GROUPATTRIBUTE,
|
||||||
externalGroups: toArrayConfig(process.env.CMD_SAML_EXTERNALGROUPS, '|', []),
|
externalGroups: toArrayConfig(process.env.CMD_SAML_EXTERNALGROUPS, '|', []),
|
||||||
requiredGroups: toArrayConfig(process.env.CMD_SAML_REQUIREDGROUPS, '|', []),
|
requiredGroups: toArrayConfig(process.env.CMD_SAML_REQUIREDGROUPS, '|', []),
|
||||||
|
|
|
@ -109,6 +109,7 @@ module.exports = {
|
||||||
idpCert: process.env.HMD_SAML_IDPCERT,
|
idpCert: process.env.HMD_SAML_IDPCERT,
|
||||||
issuer: process.env.HMD_SAML_ISSUER,
|
issuer: process.env.HMD_SAML_ISSUER,
|
||||||
identifierFormat: process.env.HMD_SAML_IDENTIFIERFORMAT,
|
identifierFormat: process.env.HMD_SAML_IDENTIFIERFORMAT,
|
||||||
|
disableRequestedAuthnContext: toBooleanConfig(process.env.HMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT),
|
||||||
groupAttribute: process.env.HMD_SAML_GROUPATTRIBUTE,
|
groupAttribute: process.env.HMD_SAML_GROUPATTRIBUTE,
|
||||||
externalGroups: toArrayConfig(process.env.HMD_SAML_EXTERNALGROUPS, '|', []),
|
externalGroups: toArrayConfig(process.env.HMD_SAML_EXTERNALGROUPS, '|', []),
|
||||||
requiredGroups: toArrayConfig(process.env.HMD_SAML_REQUIREDGROUPS, '|', []),
|
requiredGroups: toArrayConfig(process.env.HMD_SAML_REQUIREDGROUPS, '|', []),
|
||||||
|
|
|
@ -152,7 +152,7 @@ for (let i = keys.length; i--;) {
|
||||||
|
|
||||||
// Notify users about the prefix change and inform them they use legacy prefix for environment variables
|
// Notify users about the prefix change and inform them they use legacy prefix for environment variables
|
||||||
if (Object.keys(process.env).toString().indexOf('HMD_') !== -1) {
|
if (Object.keys(process.env).toString().indexOf('HMD_') !== -1) {
|
||||||
logger.warn('Using legacy HMD prefix for environment variables. Please change your variables in future. For details see: https://github.com/hackmdio/codimd#environment-variables-will-overwrite-other-server-configs')
|
logger.warn('Using legacy HMD prefix for environment variables. Please change your variables in future. For details see: https://github.com/codimd/server#environment-variables-will-overwrite-other-server-configs')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate session secret if it stays on default values
|
// Generate session secret if it stays on default values
|
||||||
|
@ -164,8 +164,8 @@ if (config.sessionSecret === 'secret') {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate upload upload providers
|
// Validate upload upload providers
|
||||||
if (['filesystem', 's3', 'minio', 'imgur', 'azure'].indexOf(config.imageUploadType) === -1) {
|
if (['filesystem', 's3', 'minio', 'imgur', 'azure', 'lutim'].indexOf(config.imageUploadType) === -1) {
|
||||||
logger.error('"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio", "azure" or "imgur". Defaulting to "filesystem"')
|
logger.error('"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio", "azure", "lutim" or "imgur". Defaulting to "filesystem"')
|
||||||
config.imageUploadType = 'filesystem'
|
config.imageUploadType = 'filesystem'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
|
||||||
let hexDigest = hash.digest('hex')
|
let hexDigest = hash.digest('hex')
|
||||||
|
|
||||||
if (email !== '' && config.allowGravatar) {
|
if (email !== '' && config.allowGravatar) {
|
||||||
photo = 'https://www.gravatar.com/avatar/' + hexDigest;
|
photo = 'https://cdn.libravatar.org/avatar/' + hexDigest;
|
||||||
if (big) {
|
if (big) {
|
||||||
photo += '?s=400'
|
photo += '?s=400'
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -427,7 +427,7 @@ function publishNoteActions (req, res, next) {
|
||||||
actionDownload(req, res, note)
|
actionDownload(req, res, note)
|
||||||
break
|
break
|
||||||
case 'edit':
|
case 'edit':
|
||||||
res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)))
|
res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)) + '?both')
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
res.redirect(config.serverURL + '/s/' + note.shortid)
|
res.redirect(config.serverURL + '/s/' + note.shortid)
|
||||||
|
@ -441,7 +441,7 @@ function publishSlideActions (req, res, next) {
|
||||||
var action = req.params.action
|
var action = req.params.action
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'edit':
|
case 'edit':
|
||||||
res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)))
|
res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)) + '?both')
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
res.redirect(config.serverURL + '/p/' + note.shortid)
|
res.redirect(config.serverURL + '/p/' + note.shortid)
|
||||||
|
|
|
@ -17,7 +17,8 @@ passport.use(new SamlStrategy({
|
||||||
entryPoint: config.saml.idpSsoUrl,
|
entryPoint: config.saml.idpSsoUrl,
|
||||||
issuer: config.saml.issuer || config.serverURL,
|
issuer: config.saml.issuer || config.serverURL,
|
||||||
cert: fs.readFileSync(config.saml.idpCert, 'utf-8'),
|
cert: fs.readFileSync(config.saml.idpCert, 'utf-8'),
|
||||||
identifierFormat: config.saml.identifierFormat
|
identifierFormat: config.saml.identifierFormat,
|
||||||
|
disableRequestedAuthnContext: config.saml.disableRequestedAuthnContext
|
||||||
}, function (user, done) {
|
}, function (user, done) {
|
||||||
// check authorization if needed
|
// check authorization if needed
|
||||||
if (config.saml.externalGroups && config.saml.groupAttribute) {
|
if (config.saml.externalGroups && config.saml.groupAttribute) {
|
||||||
|
|
31
lib/web/imageRouter/lutim.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
'use strict'
|
||||||
|
const config = require('../../config')
|
||||||
|
const logger = require('../../logger')
|
||||||
|
|
||||||
|
const lutim = require('lutim')
|
||||||
|
|
||||||
|
exports.uploadImage = function (imagePath, callback) {
|
||||||
|
if (!imagePath || typeof imagePath !== 'string') {
|
||||||
|
callback(new Error('Image path is missing or wrong'), null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!callback || typeof callback !== 'function') {
|
||||||
|
logger.error('Callback has to be a function')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.lutim && config.lutim.url) {
|
||||||
|
lutim.setAPIUrl(config.lutim.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
lutim.uploadImage(imagePath)
|
||||||
|
.then(function (json) {
|
||||||
|
if (config.debug) {
|
||||||
|
logger.info('SERVER uploadimage success: ' + JSON.stringify(json))
|
||||||
|
}
|
||||||
|
callback(null, lutim.getAPIUrl() + json.msg.short)
|
||||||
|
}).catch(function (err) {
|
||||||
|
callback(new Error(err), null)
|
||||||
|
})
|
||||||
|
}
|
|
@ -40,7 +40,9 @@ exports.uploadImage = function (imagePath, callback) {
|
||||||
callback(new Error(err), null)
|
callback(new Error(err), null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callback(null, `${protocol}://${config.minio.endPoint}:${config.minio.port}/${config.s3bucket}/${key}`)
|
let hidePort = [80, 443].includes(config.minio.port)
|
||||||
|
let urlPort = hidePort ? '' : `:${config.minio.port}`
|
||||||
|
callback(null, `${protocol}://${config.minio.endPoint}${urlPort}/${config.s3bucket}/${key}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
"Import from browser": "Importuj z przeglądarki",
|
"Import from browser": "Importuj z przeglądarki",
|
||||||
"Releases": "Wydania",
|
"Releases": "Wydania",
|
||||||
"Are you sure?": "Jesteś pewny?",
|
"Are you sure?": "Jesteś pewny?",
|
||||||
"Do you really want to delete this note?": "Do you really want to delete this note?",
|
"Do you really want to delete this note?": "Czy chcesz usunąć tą notatkę?",
|
||||||
"All users will lose their connection.": "All users will lose their connection.",
|
"All users will lose their connection.": "Wszyscy użytkownicy stracą swoje połączenie.",
|
||||||
"Cancel": "Anuluj",
|
"Cancel": "Anuluj",
|
||||||
"Yes, do it!": "Tak, zrób to!",
|
"Yes, do it!": "Tak, zrób to!",
|
||||||
"Choose method": "Wybierz metodę",
|
"Choose method": "Wybierz metodę",
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
"Refresh": "Odśwież",
|
"Refresh": "Odśwież",
|
||||||
"Contacts": "Kontakty",
|
"Contacts": "Kontakty",
|
||||||
"Report an issue": "Zgłoś błąd",
|
"Report an issue": "Zgłoś błąd",
|
||||||
"Meet us on %s": "Meet us on %s",
|
"Meet us on %s": "Spotkaj się z nami na %s",
|
||||||
"Send us email": "Wyślij nam email",
|
"Send us email": "Wyślij nam email",
|
||||||
"Documents": "Dokumenty",
|
"Documents": "Dokumenty",
|
||||||
"Features": "Funkcje",
|
"Features": "Funkcje",
|
||||||
|
@ -104,12 +104,16 @@
|
||||||
"OR": "LUB",
|
"OR": "LUB",
|
||||||
"Export to Snippet": "Eksportuj do Snippet",
|
"Export to Snippet": "Eksportuj do Snippet",
|
||||||
"Select Visibility Level": "Wybierz poziom widoczności",
|
"Select Visibility Level": "Wybierz poziom widoczności",
|
||||||
"Night Theme": "Night Theme",
|
"Night Theme": "Motyw Nocny",
|
||||||
"Follow us on %s and %s.": "Follow us on %s, and %s.",
|
"Follow us on %s and %s.": "Znajdź nas na %s oraz %s.",
|
||||||
"Privacy": "Privacy",
|
"Privacy": "Prywatność",
|
||||||
"Terms of Use": "Terms of Use",
|
"Terms of Use": "Warunki korzystania",
|
||||||
"Do you really want to delete your user account?": "Do you really want to delete your user account?",
|
"Do you really want to delete your user account?": "Czy chcesz usunąć swoje konto użytkownika?",
|
||||||
"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.": "This will delete your account, all notes that are owned by you and remove all references to your account from other notes.",
|
"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.": "Ta akcja usunie twoje konto, wszystkie notatki które posiadasz oraz wszystkie referencje do tego konta w twoich pozostałych notatkach.",
|
||||||
"Delete user": "Delete user",
|
"Delete user": "Usuń użytkownika",
|
||||||
"Export user data": "Export user data"
|
"Export user data": "Eksportuj dane użytkownika",
|
||||||
|
"Help us translating on %s": "Pomóż nam przetłumaczyć na język %s",
|
||||||
|
"Source Code": "Kod źródłowy",
|
||||||
|
"Register": "Zarejestruj",
|
||||||
|
"Powered by %s": "Wspierany przez %s"
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@
|
||||||
"Cancel": "Одустани",
|
"Cancel": "Одустани",
|
||||||
"Yes, do it!": "Да, уради!",
|
"Yes, do it!": "Да, уради!",
|
||||||
"Choose method": "Изаберите начин",
|
"Choose method": "Изаберите начин",
|
||||||
"Sign in via %s": "Пријавите се помоћу %s",
|
"Sign in via %s": "Пријави се уз %s",
|
||||||
"New": "Ново",
|
"New": "Ново",
|
||||||
"Publish": "Објави",
|
"Publish": "Објави",
|
||||||
"Extra": "Додатно",
|
"Extra": "Додатно",
|
||||||
|
@ -113,5 +113,7 @@
|
||||||
"Delete user": "Брисање корисника",
|
"Delete user": "Брисање корисника",
|
||||||
"Export user data": "Извоз свих корисничких података",
|
"Export user data": "Извоз свих корисничких података",
|
||||||
"Help us translating on %s": "Помозите нам да преведемо на %s",
|
"Help us translating on %s": "Помозите нам да преведемо на %s",
|
||||||
"Source Code": "Изворни код"
|
"Source Code": "Изворни код",
|
||||||
|
"Register": "Региструј се",
|
||||||
|
"Powered by %s": "Покреће %s"
|
||||||
}
|
}
|
23
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "CodiMD",
|
"name": "CodiMD",
|
||||||
"version": "1.3.1",
|
"version": "1.3.2",
|
||||||
"description": "Realtime collaborative markdown notes on all platforms.",
|
"description": "Realtime collaborative markdown notes on all platforms.",
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
|
@ -10,10 +10,9 @@
|
||||||
"jsonlint": "find . -not -path './node_modules/*' -type f -name '*.json' -o -type f -name '*.json.example' | while read json; do echo $json ; jq . $json; done",
|
"jsonlint": "find . -not -path './node_modules/*' -type f -name '*.json' -o -type f -name '*.json.example' | while read json; do echo $json ; jq . $json; done",
|
||||||
"standard": "echo 'standard is no longer being used, use `npm run eslint` instead!' && exit 1",
|
"standard": "echo 'standard is no longer being used, use `npm run eslint` instead!' && exit 1",
|
||||||
"dev": "webpack --config webpack.dev.js --progress --colors --watch",
|
"dev": "webpack --config webpack.dev.js --progress --colors --watch",
|
||||||
|
"heroku-prebuild": "bin/heroku",
|
||||||
"build": "webpack --config webpack.prod.js --progress --colors --bail",
|
"build": "webpack --config webpack.prod.js --progress --colors --bail",
|
||||||
"postinstall": "bin/heroku",
|
"start": "sequelize db:migrate && node app.js"
|
||||||
"start": "sequelize db:migrate && node app.js",
|
|
||||||
"doctoc": "doctoc --title='# Table of Contents' README.md"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hackmd/js-sequence-diagrams": "^0.0.1-alpha.2",
|
"@hackmd/js-sequence-diagrams": "^0.0.1-alpha.2",
|
||||||
|
@ -57,12 +56,14 @@
|
||||||
"jquery-mousewheel": "^3.1.13",
|
"jquery-mousewheel": "^3.1.13",
|
||||||
"jquery-ui": "^1.12.1",
|
"jquery-ui": "^1.12.1",
|
||||||
"js-cookie": "^2.1.3",
|
"js-cookie": "^2.1.3",
|
||||||
|
"js-sequence-diagrams": "git+https://github.com/codimd/js-sequence-diagrams.git",
|
||||||
"js-url": "^2.3.0",
|
"js-url": "^2.3.0",
|
||||||
"js-yaml": "^3.7.0",
|
"js-yaml": "^3.13.1",
|
||||||
"jsdom-nogyp": "^0.8.3",
|
"jsdom-nogyp": "^0.8.3",
|
||||||
"keymaster": "^1.6.2",
|
"keymaster": "^1.6.2",
|
||||||
"list.js": "^1.5.0",
|
"list.js": "^1.5.0",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
|
"lutim": "^1.0.2",
|
||||||
"lz-string": "git+https://github.com/hackmdio/lz-string.git",
|
"lz-string": "git+https://github.com/hackmdio/lz-string.git",
|
||||||
"markdown-it": "^8.2.2",
|
"markdown-it": "^8.2.2",
|
||||||
"markdown-it-abbr": "^1.0.4",
|
"markdown-it-abbr": "^1.0.4",
|
||||||
|
@ -140,7 +141,7 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.x"
|
"node": ">=6.x"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/hackmdio/codimd/issues",
|
"bugs": "https://github.com/codimd/server/issues",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Collaborative",
|
"Collaborative",
|
||||||
"Markdown",
|
"Markdown",
|
||||||
|
@ -149,17 +150,18 @@
|
||||||
"homepage": "https://codimd.org",
|
"homepage": "https://codimd.org",
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
{
|
{
|
||||||
"name": "Max Wu",
|
"name": "Claudius Coenen",
|
||||||
"email": "jackymaxj@gmail.com"
|
"url": "https://www.claudiuscoenen.de/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Christoph (Sheogorath) Kern",
|
"name": "Christoph (Sheogorath) Kern",
|
||||||
"email": "codimd@sheogorath.shivering-isles.com"
|
"email": "codimd@sheogorath.shivering-isles.com",
|
||||||
|
"url": "https://shivering-isles.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/hackmdio/codimd.git"
|
"url": "https://github.com/codimd/server.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-cli": "^6.26.0",
|
"babel-cli": "^6.26.0",
|
||||||
|
@ -171,7 +173,6 @@
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"copy-webpack-plugin": "^4.5.2",
|
"copy-webpack-plugin": "^4.5.2",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^1.0.0",
|
||||||
"doctoc": "^1.4.0",
|
|
||||||
"ejs-loader": "^0.3.1",
|
"ejs-loader": "^0.3.1",
|
||||||
"eslint": "^5.9.0",
|
"eslint": "^5.9.0",
|
||||||
"eslint-config-standard": "^12.0.0",
|
"eslint-config-standard": "^12.0.0",
|
||||||
|
|
|
@ -385,7 +385,7 @@ div[contenteditable]:empty:not(:focus):before{
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.night .btn.btn-default.ui-view.active{
|
.night .btn.btn-default.active{
|
||||||
background: #202020;
|
background: #202020;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,131 +1,138 @@
|
||||||
Features
|
# Features
|
||||||
===
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
Introduction
|
|
||||||
===
|
|
||||||
<i class="fa fa-file-text"></i> **CodiMD** is a real-time, multi-platform collaborative markdown note editor.
|
<i class="fa fa-file-text"></i> **CodiMD** is a real-time, multi-platform collaborative markdown note editor.
|
||||||
This means that you can write notes with other people on your **desktop**, **tablet** or even on the **phone**.
|
This means that you can write notes with other people on your **desktop**, **tablet** or even on the **phone**.
|
||||||
You can sign-in via multiple auth providers like **Facebook**, **Twitter**, **GitHub** and many more on the [_homepage_](/).
|
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).
|
If you experience any _issues_, feel free to report it on [**GitHub**](https://github.com/codimd/server/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 [**Matrix.org**](https://riot.im/app/#/room/#codimd:matrix.org) for dev-talk and interactive help.
|
||||||
**Thank you very much!**
|
**Thank you very much!**
|
||||||
|
|
||||||
Workspace
|
## Workspace
|
||||||
===
|
|
||||||
## Modes
|
### Modes
|
||||||
**Desktop & Tablet**
|
|
||||||
|
#### Desktop & Tablet
|
||||||
|
|
||||||
<i class="fa fa-edit fa-fw"></i> Edit: See only the editor.
|
|
||||||
<i class="fa fa-eye fa-fw"></i> View: See only the result.
|
<i class="fa fa-eye fa-fw"></i> View: See only the result.
|
||||||
<i class="fa fa-columns fa-fw"></i> Both: See both in split view.
|
<i class="fa fa-columns fa-fw"></i> Both: See editor and result at the same time.
|
||||||
|
<i class="fa fa-pencil fa-fw"></i> Edit: See only the editor.
|
||||||
|
|
||||||
**Mobile**
|
#### Mobile
|
||||||
|
|
||||||
<i class="fa fa-toggle-on fa-fw"></i> View: See only the result.
|
<i class="fa fa-eye fa-fw"></i> View: See only the result.
|
||||||
<i class="fa fa-toggle-off fa-fw"></i> Edit: See only the editor.
|
<i class="fa fa-pencil fa-fw"></i> Edit: See only the editor.
|
||||||
|
|
||||||
|
### Night Mode
|
||||||
|
|
||||||
## Night Mode:
|
|
||||||
When you are tired of a white screen and like a night mode, click on the little moon <i class="fa fa-moon-o"></i> and turn on the night view of CodiMD.
|
When you are tired of a white screen and like a night mode, click on the little moon <i class="fa fa-moon-o"></i> and turn on the night view of CodiMD.
|
||||||
|
|
||||||
The editor view, which is in night mode by default, can also be toggled between night and day view using the the little sun<i class="fa fa-sun-o fa-fw"></i>.
|
The editor view, which is in night mode by default, can also be toggled between night and day view using the the little sun<i class="fa fa-sun-o fa-fw"></i>.
|
||||||
|
|
||||||
## Image Upload:
|
### Image Upload
|
||||||
You can upload an image simply by clicking on the camera button <i class="fa fa-camera"></i>.
|
|
||||||
|
You can upload an image simply by clicking on the upload button <i class="fa fa-upload"></i>.
|
||||||
Alternatively, you can **drag-n-drop** an image into the editor. Even **pasting** images is possible!
|
Alternatively, you can **drag-n-drop** an image into the editor. Even **pasting** images is possible!
|
||||||
This will automatically upload the image to **[imgur](http://imgur.com)**, **[Amazon S3](https://aws.amazon.com/s3/)**, **[Minio](https://minio.io)** or **local filesystem**, nothing to worry about. :tada:
|
This will automatically upload the image to **[imgur](http://imgur.com)**, **[Amazon S3](https://aws.amazon.com/s3/)**, **[Minio](https://minio.io)** or the **local filesystem** (depending on the instance's configuration), nothing to worry about. :tada:
|
||||||
|
|
||||||
![imgur](https://i.imgur.com/9cgQVqD.png)
|
![imgur](https://i.imgur.com/9cgQVqD.png)
|
||||||
|
|
||||||
## Share Notes:
|
### Share Notes
|
||||||
|
|
||||||
If you want to share an **editable** note, just copy the URL.
|
If you want to share an **editable** note, just copy the URL.
|
||||||
If you want to share a **read-only** note, simply press publish button <i class="fa fa-share-square-o"></i> and copy the URL.
|
If you want to share a **read-only** note, simply press the publish button <i class="fa fa-share-square-o"></i> and copy the URL.
|
||||||
|
|
||||||
## Save a Note:
|
### Save a Note
|
||||||
Currently, you can save to **Dropbox** <i class="fa fa-dropbox"></i> or save an `.md` file <i class="fa fa-file-text"></i> locally.
|
|
||||||
|
|
||||||
## Import Notes:
|
Currently, you can save to **Dropbox** <i class="fa fa-dropbox"></i> (depending on the instance's configuration) or save a Markdown <i class="fa fa-file-text"></i>, HTML or raw HTML <i class="fa fa-file-code-o"></i> file locally.
|
||||||
Similarly to the _save_ feature, you can also import an `.md` file from **Dropbox** <i class="fa fa-dropbox"></i>,
|
|
||||||
or import content from your **clipboard** <i class="fa fa-clipboard"></i>, and that can parse some **html** which might be useful :smiley:
|
|
||||||
|
|
||||||
## Permissions:
|
### Import Notes
|
||||||
It is possible to change the access permission to a note through the little button on the top right of the view.
|
|
||||||
|
Similarly to the _save_ feature, you can also import a Markdown file from **Dropbox** <i class="fa fa-dropbox"></i> (depending on the instance's configuration), or import content from your **clipboard** <i class="fa fa-clipboard"></i>, which can parse some HTML. :smiley:
|
||||||
|
|
||||||
|
### Permissions
|
||||||
|
|
||||||
|
It is possible to change the access permission of a note through the little button on the top right of the view.
|
||||||
There are four possible options:
|
There are four possible options:
|
||||||
|
|
||||||
| |Owner read/write|Signed-in read|Signed-in write|Guest read|Guest write|
|
| |Owner read/write|Signed-in read|Signed-in write|Guest read|Guest write|
|
||||||
|:-----------------------------|:--------------:|:------------:|:-------------:|:--------:|:---------:|
|
|:-----------------------------|:--------------:|:------------:|:-------------:|:--------:|:---------:|
|
||||||
|<span class="text-nowrap"><i class="fa fa-leaf fa-fw"></i> **Freely**</span> |✔|✔|✔|✔|✔|
|
|<span class="text-nowrap"><i class="fa fa-leaf fa-fw"></i> **Freely**</span>|✔|✔|✔|✔|✔|
|
||||||
|<span class="text-nowrap"><i class="fa fa-pencil fa-fw"></i> **Editable**</span> |✔|✔|✔|✔|✖|
|
|<span class="text-nowrap"><i class="fa fa-pencil fa-fw"></i> **Editable**</span>|✔|✔|✔|✔|✖|
|
||||||
|<span class="text-nowrap"><i class="fa fa-id-card fa-fw"></i> **Limited**</span> |✔|✔|✔|✖|✖|
|
|<span class="text-nowrap"><i class="fa fa-id-card fa-fw"></i> **Limited**</span>|✔|✔|✔|✖|✖|
|
||||||
|<span class="text-nowrap"><i class="fa fa-lock fa-fw"></i> **Locked**</span> |✔|✔|✖|✔|✖|
|
|<span class="text-nowrap"><i class="fa fa-lock fa-fw"></i> **Locked**</span>|✔|✔|✖|✔|✖|
|
||||||
|<span class="text-nowrap"><i class="fa fa-umbrella fa-fw"></i> **Protected**</span> |✔|✔|✖|✖|✖|
|
|<span class="text-nowrap"><i class="fa fa-umbrella fa-fw"></i> **Protected**</span>|✔|✔|✖|✖|✖|
|
||||||
|<span class="text-nowrap"><i class="fa fa-hand-stop-o fa-fw"></i> **Private**</span> |✔|✖|✖|✖|✖|
|
|<span class="text-nowrap"><i class="fa fa-hand-stop-o fa-fw"></i> **Private**</span>|✔|✖|✖|✖|✖|
|
||||||
|
|
||||||
|
|
||||||
**Only the owner of the note can change the note's permissions.**
|
**Only the owner of the note can change the note's permissions.**
|
||||||
|
|
||||||
## Embed a Note:
|
### Embed a Note
|
||||||
|
|
||||||
Notes can be embedded as follows:
|
Notes can be embedded as follows:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<iframe width="100%" height="500" src="https://hackmd.io/features" frameborder="0"></iframe>
|
<iframe width="100%" height="500" src="https://demo.codimd.io/features" frameborder="0"></iframe>
|
||||||
```
|
```
|
||||||
|
|
||||||
## [Slide Mode](./slide-example):
|
### [Slide Mode](./slide-example)
|
||||||
|
|
||||||
You can use a special syntax to organize your note into slides.
|
You can use a special syntax to organize your note into slides.
|
||||||
After that, you can use the **[Slide Mode](./slide-example)** <i class="fa fa-tv"></i> to make a presentation.
|
After that, you can use the **[Slide Mode](./slide-example)** <i class="fa fa-tv"></i> to make a presentation.
|
||||||
Visit the above link for details.
|
Visit the above link for details.
|
||||||
|
|
||||||
To switch the editor into slide mode, set the [document type](./yaml-metadata#type) to `slide`.
|
To switch the editor into slide mode, set the [document type](./yaml-metadata#type) to `slide`.
|
||||||
|
|
||||||
View
|
## View
|
||||||
===
|
|
||||||
## Table of Contents:
|
### Autogenerated Table of Contents
|
||||||
|
|
||||||
You can look at the bottom right section of the view area, there is a _ToC_ button <i class="fa fa-bars"></i>.
|
You can look at the bottom right section of the view area, there is a _ToC_ button <i class="fa fa-bars"></i>.
|
||||||
Pressing that button will show you a current _Table of Contents_, and will highlight which section you're at.
|
Pressing that button will show you a current _Table of Contents_, and will highlight which section you're at.
|
||||||
ToCs support up to **three header levels**.
|
ToCs support up to **three header levels**.
|
||||||
|
|
||||||
## Permalink
|
### Permalink
|
||||||
|
|
||||||
Every header will automatically add a permalink on the right side.
|
Every header will automatically add a permalink on the right side.
|
||||||
You can hover and click <i class="fa fa-chain"></i> to anchor on it.
|
You can hover and click <i class="fa fa-chain"></i> to anchor on it.
|
||||||
|
|
||||||
Edit:
|
## Edit
|
||||||
===
|
|
||||||
## Editor Modes:
|
|
||||||
You can look in the bottom right section of the editor area, there you'll find a button with `sublime` on it.
|
|
||||||
When you click it, you can select 3 editor modes:
|
|
||||||
|
|
||||||
- sublime (default)
|
### Editor Modes
|
||||||
- emacs
|
|
||||||
- vim
|
|
||||||
|
|
||||||
## Shortcut Keys:
|
You can look in the bottom right section of the editor area, there you'll find a button with `SUBLIME` on it.
|
||||||
The shortcut keys depend on your selected editor mode. By default they are just like Sublime text, which is pretty quick and convenient.
|
When you click it, you can select 3 editor modes, which will also define your shortcut keys:
|
||||||
> For more information, see [here](https://codemirror.net/demo/sublime.html).
|
|
||||||
|
|
||||||
For emacs:
|
- [Sublime](https://codemirror.net/demo/sublime.html) (default)
|
||||||
> For more information, see [here](https://codemirror.net/demo/emacs.html).
|
- [Emacs](https://codemirror.net/demo/emacs.html)
|
||||||
|
- [Vim](https://codemirror.net/demo/vim.html)
|
||||||
|
|
||||||
For vim:
|
### Auto-Complete
|
||||||
> For more information, see [here](https://codemirror.net/demo/vim.html).
|
|
||||||
|
|
||||||
## Auto-Complete:
|
|
||||||
This editor provides full auto-complete hints in markdown.
|
This editor provides full auto-complete hints in markdown.
|
||||||
|
|
||||||
- Emojis: type `:` to show hints.
|
- Emojis: type `:` to show hints.
|
||||||
- Code blocks: type ` ``` ` and plus a character to show hint. <i hidden>```</i>
|
- Code blocks: type ` ``` `, followed by another character to show syntax highlighting suggestions.
|
||||||
- Headers: type `#` to show hint.
|
- Headers: type `#` to show hint.
|
||||||
- Referrals: type `[]` to show hint.
|
- Referrals: type `[]` to show hint.
|
||||||
- Externals: type `{}` to show hint.
|
- Externals: type `{}` to show hint.
|
||||||
- Images: type `!` to show hint.
|
- Images: type `!` to show hint.
|
||||||
|
|
||||||
## Title:
|
### Title
|
||||||
This will take the first **level 1 header** as the note title.
|
|
||||||
|
The first **level 1 heading** (e.g. `# Title`) will be used as the note title.
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
|
||||||
## Tags:
|
|
||||||
Using tags as follows, the specified tags will show in your **history**.
|
Using tags as follows, the specified tags will show in your **history**.
|
||||||
|
|
||||||
###### tags: `features` `cool` `updated`
|
###### tags: `features` `cool` `updated`
|
||||||
|
|
||||||
## [YAML Metadata](./yaml-metadata)
|
### [YAML Metadata](./yaml-metadata)
|
||||||
|
|
||||||
You can provide advanced note information to set the browser behavior (visit above link for details):
|
You can provide advanced note information to set the browser behavior (visit above link for details):
|
||||||
|
|
||||||
- robots: set web robots meta
|
- robots: set web robots meta
|
||||||
- lang: set browser language
|
- lang: set browser language
|
||||||
- dir: set text direction
|
- dir: set text direction
|
||||||
|
@ -134,23 +141,30 @@ You can provide advanced note information to set the browser behavior (visit abo
|
||||||
- disqus: set to use Disqus
|
- disqus: set to use Disqus
|
||||||
- slideOptions: setup slide mode options
|
- slideOptions: setup slide mode options
|
||||||
|
|
||||||
## ToC:
|
### Table of Contents
|
||||||
Use the syntax `[TOC]` to embed table of content into your note.
|
|
||||||
|
Use the syntax `[TOC]` to embed a table of contents into your note.
|
||||||
|
|
||||||
[TOC]
|
[TOC]
|
||||||
|
|
||||||
## Emoji
|
### Emoji
|
||||||
|
|
||||||
You can type any emoji like this :smile: :smiley: :cry: :wink:
|
You can type any emoji like this :smile: :smiley: :cry: :wink:
|
||||||
|
|
||||||
> See full emoji list [here](http://www.emoji-cheat-sheet.com/).
|
> See full emoji list [here](http://www.emoji-cheat-sheet.com/).
|
||||||
|
|
||||||
## ToDo List:
|
### ToDo List
|
||||||
|
|
||||||
- [ ] ToDos
|
- [ ] ToDos
|
||||||
- [x] Buy some salad
|
- [x] Buy some salad
|
||||||
- [ ] Brush teeth
|
- [ ] Brush teeth
|
||||||
- [x] Drink some water
|
- [x] Drink some water
|
||||||
|
- [ ] **Click my box** and see the source code, if you're allowed to edit!
|
||||||
|
|
||||||
|
### Code Block
|
||||||
|
|
||||||
## Code Block:
|
|
||||||
We support many programming languages, use the auto complete function to see the entire list.
|
We support many programming languages, use the auto complete function to see the entire list.
|
||||||
|
|
||||||
```javascript=
|
```javascript=
|
||||||
var s = "JavaScript syntax highlighting";
|
var s = "JavaScript syntax highlighting";
|
||||||
alert(s);
|
alert(s);
|
||||||
|
@ -168,9 +182,11 @@ function $initHighlight(block, cls) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
> If you want **line numbers**, type `=` after specifying the code block languagues.
|
|
||||||
> Also, you can specify the start line number.
|
If you want **line numbers**, type `=` after specifying the code block languagues.
|
||||||
> Like below, the line number starts from 101:
|
Also, you can specify the start line number.
|
||||||
|
Like below, the line number starts from 101:
|
||||||
|
|
||||||
```javascript=101
|
```javascript=101
|
||||||
var s = "JavaScript syntax highlighting";
|
var s = "JavaScript syntax highlighting";
|
||||||
alert(s);
|
alert(s);
|
||||||
|
@ -189,44 +205,50 @@ function $initHighlight(block, cls) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> Or you might want to continue the previous code block's line number, use `=+`
|
Or you might want to continue the previous code block's line number, use `=+`:
|
||||||
|
|
||||||
```javascript=+
|
```javascript=+
|
||||||
var s = "JavaScript syntax highlighting";
|
var s = "JavaScript syntax highlighting";
|
||||||
alert(s);
|
alert(s);
|
||||||
```
|
```
|
||||||
|
|
||||||
> Somtimes you have a super long text without breaks. It's time to use `!` to wrap your code.
|
Somtimes you have a super long text without breaks. It's time to use `!` to wrap your code:
|
||||||
|
|
||||||
```!
|
```!
|
||||||
When you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back.
|
When you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Blockquote Tags:
|
### Blockquote Tags
|
||||||
|
|
||||||
> Using the syntax below to specifiy your **name, time and color** to vary the blockquotes.
|
> Using the syntax below to specifiy your **name, time and color** to vary the blockquotes.
|
||||||
> [name=ChengHan Wu] [time=Sun, Jun 28, 2015 9:59 PM] [color=#907bf7]
|
> [name=ChengHan Wu] [time=Sun, Jun 28, 2015 9:59 PM] [color=#907bf7]
|
||||||
> > Even support the nest blockquotes!
|
> > Even support nested blockquotes!
|
||||||
> > [name=ChengHan Wu] [time=Sun, Jun 28, 2015 10:00 PM] [color=red]
|
> > [name=Max Mustermann] [time=Sun, Jun 28, 2015 9:47 PM] [color=red]
|
||||||
|
|
||||||
## Externals
|
### Externals
|
||||||
|
|
||||||
|
#### YouTube
|
||||||
|
|
||||||
### YouTube
|
|
||||||
{%youtube aqz-KE-bpKQ %}
|
{%youtube aqz-KE-bpKQ %}
|
||||||
|
|
||||||
### Vimeo
|
#### Vimeo
|
||||||
|
|
||||||
{%vimeo 124148255 %}
|
{%vimeo 124148255 %}
|
||||||
|
|
||||||
### Gist
|
#### Gist
|
||||||
|
|
||||||
{%gist schacon/4277%}
|
{%gist schacon/4277%}
|
||||||
|
|
||||||
### SlideShare
|
#### SlideShare
|
||||||
|
|
||||||
{%slideshare briansolis/26-disruptive-technology-trends-2016-2018-56796196 %}
|
{%slideshare briansolis/26-disruptive-technology-trends-2016-2018-56796196 %}
|
||||||
|
|
||||||
### PDF
|
#### PDF
|
||||||
|
|
||||||
**Caution: this might be blocked by your browser if not using an `https` URL.**
|
**Caution: this might be blocked by your browser if not using an `https` URL.**
|
||||||
{%pdf https://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf %}
|
{%pdf https://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf %}
|
||||||
|
|
||||||
## MathJax
|
### MathJax
|
||||||
|
|
||||||
You can render *LaTeX* mathematical expressions using **MathJax**, as on [math.stackexchange.com](http://math.stackexchange.com/):
|
You can render *LaTeX* mathematical expressions using **MathJax**, as on [math.stackexchange.com](http://math.stackexchange.com/):
|
||||||
|
|
||||||
|
@ -242,9 +264,9 @@ $$
|
||||||
|
|
||||||
> More information about **LaTeX** mathematical expressions [here](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).
|
> More information about **LaTeX** mathematical expressions [here](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).
|
||||||
|
|
||||||
## UML Diagrams
|
### Diagrams
|
||||||
|
|
||||||
### Sequence Diagrams
|
#### UML Sequence Diagrams
|
||||||
|
|
||||||
You can render sequence diagrams like this:
|
You can render sequence diagrams like this:
|
||||||
|
|
||||||
|
@ -256,9 +278,12 @@ Note left of Alice: Alice responds
|
||||||
Alice->Bob: Where have you been?
|
Alice->Bob: Where have you been?
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flow Charts
|
More information about **sequence diagrams** syntax [here](http://bramp.github.io/js-sequence-diagrams/).
|
||||||
|
|
||||||
|
#### Flow Charts
|
||||||
|
|
||||||
Flow charts can be specified like this:
|
Flow charts can be specified like this:
|
||||||
|
|
||||||
```flow
|
```flow
|
||||||
st=>start: Start
|
st=>start: Start
|
||||||
e=>end: End
|
e=>end: End
|
||||||
|
@ -271,36 +296,45 @@ cond(yes)->e
|
||||||
cond(no)->op2
|
cond(no)->op2
|
||||||
```
|
```
|
||||||
|
|
||||||
### Graphviz
|
More information about **flow charts** syntax [here](http://adrai.github.io/flowchart.js/).
|
||||||
|
|
||||||
|
#### Graphviz
|
||||||
|
|
||||||
```graphviz
|
```graphviz
|
||||||
digraph hierarchy {
|
digraph hierarchy {
|
||||||
|
nodesep=1.0 // Increases the separation between nodes
|
||||||
|
|
||||||
nodesep=1.0 // increases the separation between nodes
|
node [color=Red,fontname=Courier,shape=box] // All nodes will this shape and colour
|
||||||
|
edge [color=Blue, style=dashed] // All the lines look like this
|
||||||
|
|
||||||
node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour
|
Headteacher->{Deputy1 Deputy2 BusinessManager}
|
||||||
edge [color=Blue, style=dashed] //All the lines look like this
|
Deputy1->{Teacher1 Teacher2}
|
||||||
|
BusinessManager->ITManager
|
||||||
Headteacher->{Deputy1 Deputy2 BusinessManager}
|
{rank=same;ITManager Teacher1 Teacher2} // Put them on the same level
|
||||||
Deputy1->{Teacher1 Teacher2}
|
|
||||||
BusinessManager->ITManager
|
|
||||||
{rank=same;ITManager Teacher1 Teacher2} // Put them on the same level
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mermaid
|
More information about **graphviz** syntax [here](http://www.tonyballantyne.com/graphs.html)
|
||||||
|
|
||||||
|
#### Mermaid
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
gantt
|
gantt
|
||||||
title A Gantt Diagram
|
title A Gantt Diagram
|
||||||
|
|
||||||
section Section
|
section Section
|
||||||
A task :a1, 2014-01-01, 30d
|
A task: a1, 2014-01-01, 30d
|
||||||
Another task :after a1 , 20d
|
Another task: after a1, 20d
|
||||||
section Another
|
|
||||||
Task in sec :2014-01-12 , 12d
|
section Another
|
||||||
anther task : 24d
|
Task in sec: 2014-01-12, 12d
|
||||||
|
Another task: 24d
|
||||||
```
|
```
|
||||||
|
|
||||||
### Abc
|
More information about **mermaid** syntax [here](http://knsv.github.io/mermaid)
|
||||||
|
|
||||||
|
#### Abc Music Notation
|
||||||
|
|
||||||
```abc
|
```abc
|
||||||
X:1
|
X:1
|
||||||
T:Speed the Plough
|
T:Speed the Plough
|
||||||
|
@ -313,14 +347,10 @@ GABc dedB|dedB dedB|c2ec B2dB|A2F2 G4:|
|
||||||
g2gf g2Bd|g2f2 e2d2|c2ec B2dB|A2F2 G4:|
|
g2gf g2Bd|g2f2 e2d2|c2ec B2dB|A2F2 G4:|
|
||||||
```
|
```
|
||||||
|
|
||||||
> More information about **sequence diagrams** syntax [here](http://bramp.github.io/js-sequence-diagrams/).
|
More information about **abc** syntax [here](http://abcnotation.com/learn)
|
||||||
> More information about **flow charts** syntax [here](http://adrai.github.io/flowchart.js/).
|
|
||||||
> More information about **graphviz** syntax [here](http://www.tonyballantyne.com/graphs.html)
|
### Alert Area
|
||||||
> More information about **mermaid** syntax [here](http://knsv.github.io/mermaid)
|
|
||||||
> More information about **abc** syntax [here](http://abcnotation.com/learn)
|
|
||||||
|
|
||||||
Alert Area
|
|
||||||
---
|
|
||||||
:::success
|
:::success
|
||||||
Yes :tada:
|
Yes :tada:
|
||||||
:::
|
:::
|
||||||
|
@ -337,11 +367,11 @@ Watch out :zap:
|
||||||
Oh No! :fire:
|
Oh No! :fire:
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## Typography
|
### Typography
|
||||||
|
|
||||||
### Headers
|
#### Headers
|
||||||
|
|
||||||
```
|
``` markdown
|
||||||
# h1 Heading
|
# h1 Heading
|
||||||
## h2 Heading
|
## h2 Heading
|
||||||
### h3 Heading
|
### h3 Heading
|
||||||
|
@ -350,7 +380,7 @@ Oh No! :fire:
|
||||||
###### h6 Heading
|
###### h6 Heading
|
||||||
```
|
```
|
||||||
|
|
||||||
### Horizontal Rules
|
#### Horizontal Rules
|
||||||
|
|
||||||
___
|
___
|
||||||
|
|
||||||
|
@ -358,8 +388,7 @@ ___
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
#### Typographic Replacements
|
||||||
### Typographic Replacements
|
|
||||||
|
|
||||||
Enable typographer option to see result.
|
Enable typographer option to see result.
|
||||||
|
|
||||||
|
@ -375,7 +404,7 @@ Remarkable -- awesome
|
||||||
|
|
||||||
'Smartypants, single quotes'
|
'Smartypants, single quotes'
|
||||||
|
|
||||||
### Emphasis
|
#### Emphasis
|
||||||
|
|
||||||
**This is bold text**
|
**This is bold text**
|
||||||
|
|
||||||
|
@ -397,18 +426,15 @@ Subscript: H~2~O
|
||||||
|
|
||||||
==Marked text==
|
==Marked text==
|
||||||
|
|
||||||
|
#### Blockquotes
|
||||||
### Blockquotes
|
|
||||||
|
|
||||||
|
|
||||||
> Blockquotes can also be nested...
|
> Blockquotes can also be nested...
|
||||||
>> ...by using additional greater-than signs right next to each other...
|
>> ...by using additional greater-than signs right next to each other...
|
||||||
> > > ...or with spaces between arrows.
|
> > > ...or with spaces between arrows.
|
||||||
|
|
||||||
|
#### Lists
|
||||||
|
|
||||||
### Lists
|
##### Unordered
|
||||||
|
|
||||||
#### Unordered
|
|
||||||
|
|
||||||
+ Create a list by starting a line with `+`, `-`, or `*`
|
+ Create a list by starting a line with `+`, `-`, or `*`
|
||||||
+ Sub-lists are made by indenting 2 spaces:
|
+ Sub-lists are made by indenting 2 spaces:
|
||||||
|
@ -418,27 +444,26 @@ Subscript: H~2~O
|
||||||
- Nulla volutpat aliquam velit
|
- Nulla volutpat aliquam velit
|
||||||
+ Very easy!
|
+ Very easy!
|
||||||
|
|
||||||
#### Ordered
|
##### Ordered
|
||||||
|
|
||||||
1. Lorem ipsum dolor sit amet
|
1. Lorem ipsum dolor sit amet
|
||||||
2. Consectetur adipiscing elit
|
2. Consectetur adipiscing elit
|
||||||
3. Integer molestie lorem at massa
|
3. Aenean commodo ligula eget dolor
|
||||||
|
|
||||||
|
1. **You can use sequential numbers...**
|
||||||
1. You can use sequential numbers...
|
1. **...or keep all the numbers as `1.`**
|
||||||
1. ...or keep all the numbers as `1.`
|
1. Aenean massa
|
||||||
1. feafw
|
2. Cum sociis natoque penatibus
|
||||||
2. 332
|
3. Magnis dis parturient montes
|
||||||
3. 242
|
4. Nascetur ridiculus mus
|
||||||
4. 2552
|
1. Donec quam felis
|
||||||
1. e2
|
|
||||||
|
|
||||||
Start numbering with offset:
|
Start numbering with offset:
|
||||||
|
|
||||||
57. foo
|
57. foo
|
||||||
1. bar
|
1. bar
|
||||||
|
|
||||||
### Code
|
#### Code
|
||||||
|
|
||||||
Inline `code`
|
Inline `code`
|
||||||
|
|
||||||
|
@ -449,7 +474,6 @@ Indented code
|
||||||
line 2 of code
|
line 2 of code
|
||||||
line 3 of code
|
line 3 of code
|
||||||
|
|
||||||
|
|
||||||
Block code "fences"
|
Block code "fences"
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -466,7 +490,7 @@ var foo = function (bar) {
|
||||||
console.log(foo(5));
|
console.log(foo(5));
|
||||||
```
|
```
|
||||||
|
|
||||||
### Tables
|
#### Tables
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------ | ----------- |
|
| ------ | ----------- |
|
||||||
|
@ -498,26 +522,28 @@ Center aligned columns
|
||||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
| engine | engine to be used for processing templates. Handlebars is the default. |
|
||||||
| ext | extension to be used for dest files. |
|
| ext | extension to be used for dest files. |
|
||||||
|
|
||||||
|
#### Links
|
||||||
|
|
||||||
### Links
|
[link text](https://demo.codimd.org)
|
||||||
[link text](http://dev.nodeca.com)
|
[link with title](https://nodeca.github.io/pica/demo/ "title text!")
|
||||||
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
|
|
||||||
Autoconverted link https://github.com/nodeca/pica
|
Autoconverted link https://github.com/nodeca/pica
|
||||||
|
|
||||||
|
#### Images
|
||||||
|
|
||||||
### Images
|
|
||||||
![Minion](https://octodex.github.com/images/minion.png)
|
![Minion](https://octodex.github.com/images/minion.png)
|
||||||
|
|
||||||
|
With a title:
|
||||||
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
|
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
|
||||||
Like links, Images also have a footnote style syntax
|
|
||||||
![Alt text][id]
|
|
||||||
With a reference later in the document defining the URL location:
|
|
||||||
|
|
||||||
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
|
Like links, images also have a footnote style syntax with a reference later in the document defining the URL location:
|
||||||
|
![Dojocat][dojoref]
|
||||||
|
|
||||||
|
[dojoref]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
|
||||||
|
|
||||||
|
Show the image with given size:
|
||||||
![Minion](https://octodex.github.com/images/minion.png =200x200)
|
![Minion](https://octodex.github.com/images/minion.png =200x200)
|
||||||
Show the image with given size
|
|
||||||
|
|
||||||
### Footnotes
|
#### Footnotes
|
||||||
|
|
||||||
Footnote 1 link[^first].
|
Footnote 1 link[^first].
|
||||||
Footnote 2 link[^second].
|
Footnote 2 link[^second].
|
||||||
|
@ -528,7 +554,7 @@ Duplicated footnote reference[^second].
|
||||||
and multiple paragraphs.
|
and multiple paragraphs.
|
||||||
[^second]: Footnote text.
|
[^second]: Footnote text.
|
||||||
|
|
||||||
### Definition Lists
|
#### Definition Lists
|
||||||
|
|
||||||
Term 1
|
Term 1
|
||||||
|
|
||||||
|
@ -552,7 +578,7 @@ Term 2
|
||||||
~ Definition 2a
|
~ Definition 2a
|
||||||
~ Definition 2b
|
~ Definition 2b
|
||||||
|
|
||||||
### Abbreviations
|
#### Abbreviations
|
||||||
|
|
||||||
This is an HTML abbreviation example.
|
This is an HTML abbreviation example.
|
||||||
It converts "HTML", but keeps intact partial entries like "xxxHTMLyyy" and so on.
|
It converts "HTML", but keeps intact partial entries like "xxxHTMLyyy" and so on.
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
Release Notes
|
Release Notes
|
||||||
===
|
===
|
||||||
|
|
||||||
|
<i class="fa fa-tag"></i> 1.3.2 <i class="fa fa-clock-o"></i> 2019-03-28 00:00
|
||||||
|
---
|
||||||
|
|
||||||
|
### Announcement
|
||||||
|
* CodiMD is now running in an own organization. [Check out our vision for the future](https://github.com/codimd/server/issues/10)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Update various links to the new repositories
|
||||||
|
* Fix background color for mode switching button in night mode
|
||||||
|
|
||||||
<i class="fa fa-tag"></i> 1.3.1 <i class="fa fa-clock-o"></i> 2019-03-23 00:00
|
<i class="fa fa-tag"></i> 1.3.1 <i class="fa fa-clock-o"></i> 2019-03-23 00:00
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -158,7 +168,7 @@ Release Notes
|
||||||
|
|
||||||
### Deprecations
|
### Deprecations
|
||||||
* NodeJS version 6
|
* NodeJS version 6
|
||||||
* Mattermost login integration (is replaced by [generic oAuth2 module](https://github.com/hackmdio/codimd/blob/6ce7b20a7f92ccff2f7f870ff5d116d685310cfd/docs/guides/auth/mattermost-self-hosted.md))
|
* Mattermost login integration (is replaced by [generic oAuth2 module](https://github.com/codimd/server/blob/6ce7b20a7f92ccff2f7f870ff5d116d685310cfd/docs/guides/auth/mattermost-self-hosted.md))
|
||||||
|
|
||||||
### Honorable mentions
|
### Honorable mentions
|
||||||
* [Alex Hesse (Pingu501)](https://github.com/Pingu501)
|
* [Alex Hesse (Pingu501)](https://github.com/Pingu501)
|
||||||
|
@ -174,7 +184,7 @@ Release Notes
|
||||||
---
|
---
|
||||||
|
|
||||||
### Announcement
|
### Announcement
|
||||||
* HackMD CE is renamed to CodiMD to prevent confusion. [For details see here](https://github.com/hackmdio/codimd#hackmd-ce-became-codimd)
|
* HackMD CE is renamed to CodiMD to prevent confusion. [For details see here](https://github.com/codimd/server/tree/master/docs/history.md)
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
* Show full title by hovering over to table of contents entries
|
* Show full title by hovering over to table of contents entries
|
||||||
|
|
|
@ -304,7 +304,6 @@ var editor = editorInstance.init(textit)
|
||||||
// FIXME: global referncing in jquery-textcomplete patch
|
// FIXME: global referncing in jquery-textcomplete patch
|
||||||
window.editor = editor
|
window.editor = editor
|
||||||
|
|
||||||
var inlineAttach = inlineAttachment.editors.codemirror4.attach(editor)
|
|
||||||
defaultTextHeight = parseInt($('.CodeMirror').css('line-height'))
|
defaultTextHeight = parseInt($('.CodeMirror').css('line-height'))
|
||||||
|
|
||||||
// initalize ui reference
|
// initalize ui reference
|
||||||
|
@ -801,7 +800,6 @@ function changeMode (type) {
|
||||||
editor.getInputField().blur()
|
editor.getInputField().blur()
|
||||||
}
|
}
|
||||||
if (appState.currentMode === modeType.edit || appState.currentMode === modeType.both) {
|
if (appState.currentMode === modeType.edit || appState.currentMode === modeType.both) {
|
||||||
ui.toolbar.uploadImage.fadeIn()
|
|
||||||
// add and update status bar
|
// add and update status bar
|
||||||
if (!editorInstance.statusBar) {
|
if (!editorInstance.statusBar) {
|
||||||
editorInstance.addStatusBar()
|
editorInstance.addStatusBar()
|
||||||
|
@ -814,8 +812,6 @@ function changeMode (type) {
|
||||||
// work around foldGutter might not init properly
|
// work around foldGutter might not init properly
|
||||||
editor.setOption('foldGutter', false)
|
editor.setOption('foldGutter', false)
|
||||||
editor.setOption('foldGutter', true)
|
editor.setOption('foldGutter', true)
|
||||||
} else {
|
|
||||||
ui.toolbar.uploadImage.fadeOut()
|
|
||||||
}
|
}
|
||||||
if (appState.currentMode !== modeType.edit) {
|
if (appState.currentMode !== modeType.edit) {
|
||||||
$(document.body).css('background-color', 'white')
|
$(document.body).css('background-color', 'white')
|
||||||
|
@ -1051,17 +1047,6 @@ ui.toolbar.import.snippet.click(function () {
|
||||||
ui.spinner.hide()
|
ui.spinner.hide()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// import from clipboard
|
|
||||||
ui.toolbar.import.clipboard.click(function () {
|
|
||||||
// na
|
|
||||||
})
|
|
||||||
// upload image
|
|
||||||
ui.toolbar.uploadImage.bind('change', function (e) {
|
|
||||||
var files = e.target.files || e.dataTransfer.files
|
|
||||||
e.dataTransfer = {}
|
|
||||||
e.dataTransfer.files = files
|
|
||||||
inlineAttach.onDrop(e)
|
|
||||||
})
|
|
||||||
// toc
|
// toc
|
||||||
ui.toc.dropdown.click(function (e) {
|
ui.toc.dropdown.click(function (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
|
@ -138,6 +138,7 @@ export default class Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
addToolBar () {
|
addToolBar () {
|
||||||
|
var inlineAttach = inlineAttachment.editors.codemirror4.attach(this.editor)
|
||||||
this.toolBar = $(toolBarTemplate)
|
this.toolBar = $(toolBarTemplate)
|
||||||
this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {
|
this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {
|
||||||
position: 'top'
|
position: 'top'
|
||||||
|
@ -157,6 +158,7 @@ export default class Editor {
|
||||||
var makeTable = $('#makeTable')
|
var makeTable = $('#makeTable')
|
||||||
var makeLine = $('#makeLine')
|
var makeLine = $('#makeLine')
|
||||||
var makeComment = $('#makeComment')
|
var makeComment = $('#makeComment')
|
||||||
|
var uploadImage = $('#uploadImage')
|
||||||
|
|
||||||
makeBold.click(() => {
|
makeBold.click(() => {
|
||||||
utils.wrapTextWith(this.editor, this.editor, '**')
|
utils.wrapTextWith(this.editor, this.editor, '**')
|
||||||
|
@ -217,6 +219,13 @@ export default class Editor {
|
||||||
makeComment.click(() => {
|
makeComment.click(() => {
|
||||||
utils.insertText(this.editor, '> []')
|
utils.insertText(this.editor, '> []')
|
||||||
})
|
})
|
||||||
|
uploadImage.bind('change', function (e) {
|
||||||
|
console.log("tiggered")
|
||||||
|
var files = e.target.files || e.dataTransfer.files
|
||||||
|
e.dataTransfer = {}
|
||||||
|
e.dataTransfer.files = files
|
||||||
|
inlineAttach.onDrop(e)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addStatusBar () {
|
addStatusBar () {
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
<a id="makeImage" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Image">
|
<a id="makeImage" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Image">
|
||||||
<i class="fa fa-image fa-fw"></i>
|
<i class="fa fa-image fa-fw"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<span id="uploadImage" class="btn btn-sm btn-dark btn-file ui-upload-image" title="Upload Image">
|
||||||
|
<i class="fa fa-upload fa-fw"></i><input type="file" accept="image/*" name="upload" multiple>
|
||||||
|
</span>
|
||||||
<a id="makeTable" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Table">
|
<a id="makeTable" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Table">
|
||||||
<i class="fa fa-table fa-fw"></i>
|
<i class="fa fa-table fa-fw"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -35,8 +35,7 @@ export const getUIElements = () => ({
|
||||||
edit: $('.ui-edit'),
|
edit: $('.ui-edit'),
|
||||||
view: $('.ui-view'),
|
view: $('.ui-view'),
|
||||||
both: $('.ui-both'),
|
both: $('.ui-both'),
|
||||||
night: $('.ui-night'),
|
night: $('.ui-night')
|
||||||
uploadImage: $('.ui-upload-image')
|
|
||||||
},
|
},
|
||||||
infobar: {
|
infobar: {
|
||||||
lastchange: $('.ui-lastchange'),
|
lastchange: $('.ui-lastchange'),
|
||||||
|
|
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 222 KiB |
|
@ -15,9 +15,6 @@
|
||||||
</div>
|
</div>
|
||||||
<a class="navbar-brand pull-left" href="<%- serverURL %>/"><i class="fa fa-file-text"></i> DepauMD</a>
|
<a class="navbar-brand pull-left" href="<%- serverURL %>/"><i class="fa fa-file-text"></i> DepauMD</a>
|
||||||
<div class="nav-mobile pull-right visible-xs">
|
<div class="nav-mobile pull-right visible-xs">
|
||||||
<span class="btn btn-link btn-file ui-upload-image" title="Upload Image" style="display:none;">
|
|
||||||
<i class="fa fa-camera"></i><input type="file" accept="image/*" name="upload" multiple>
|
|
||||||
</span>
|
|
||||||
<a data-toggle="dropdown" class="btn btn-link">
|
<a data-toggle="dropdown" class="btn btn-link">
|
||||||
<i class="fa fa-caret-down"></i>
|
<i class="fa fa-caret-down"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -100,9 +97,6 @@
|
||||||
<span class="btn btn-link btn-file ui-help" title="<%= __('Help') %>" data-toggle="modal" data-target=".help-modal">
|
<span class="btn btn-link btn-file ui-help" title="<%= __('Help') %>" data-toggle="modal" data-target=".help-modal">
|
||||||
<i class="fa fa-question-circle"></i>
|
<i class="fa fa-question-circle"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="btn btn-link btn-file ui-upload-image" title="<%= __('Upload Image') %>" style="display:none;">
|
|
||||||
<i class="fa fa-camera"></i><input type="file" accept="image/*" name="upload" multiple>
|
|
||||||
</span>
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
<li id="online-user-list">
|
<li id="online-user-list">
|
||||||
|
|
|
@ -135,26 +135,26 @@
|
||||||
<option value="ca">Català</option>
|
<option value="ca">Català</option>
|
||||||
<option value="el">Ελληνικά</option>
|
<option value="el">Ελληνικά</option>
|
||||||
<option value="pt">Português</option>
|
<option value="pt">Português</option>
|
||||||
<option value="it">italiano</option>
|
<option value="it">Italiano</option>
|
||||||
<option value="tr">Türkçe</option>
|
<option value="tr">Türkçe</option>
|
||||||
<option value="ru">Русский</option>
|
<option value="ru">Русский</option>
|
||||||
<option value="nl">Nederlands</option>
|
<option value="nl">Nederlands</option>
|
||||||
<option value="hr">hrvatski jezik</option>
|
<option value="hr">Hrvatski</option>
|
||||||
<option value="pl">język polski</option>
|
<option value="pl">Polski</option>
|
||||||
<option value="uk">Українська</option>
|
<option value="uk">Українська</option>
|
||||||
<option value="hi">हिन्दी</option>
|
<option value="hi">हिन्दी</option>
|
||||||
<option value="sv">svenska</option>
|
<option value="sv">Svenska</option>
|
||||||
<option value="eo">Esperanto</option>
|
<option value="eo">Esperanto</option>
|
||||||
<option value="da">dansk</option>
|
<option value="da">Dansk</option>
|
||||||
<option value="ko">한국어</option>
|
<option value="ko">한국어</option>
|
||||||
<option value="id">Bahasa Indonesia</option>
|
<option value="id">Bahasa Indonesia</option>
|
||||||
<option value="sr">српски</option>
|
<option value="sr">Cрпски</option>
|
||||||
</select>
|
</select>
|
||||||
<p>
|
<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://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><% } %>
|
||||||
</p>
|
</p>
|
||||||
<h6 class="social-foot">
|
<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/codimd/server" 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>') %>
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<h3 class="panel-title"><%= __('Contacts') %></h3>
|
<h3 class="panel-title"><%= __('Contacts') %></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<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>
|
<a href="https://github.com/codimd/server/issues" target="_blank"><i class="fa fa-tag fa-fw"></i> <%= __('Report an issue') %></a>
|
||||||
<br>
|
<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://riot.im/app/#/room/#codimd:matrix.org" target="_blank"><i class="fa fa-hashtag fa-fw"></i> <%= __('Meet us on %s', 'Matrix') %></a>
|
||||||
<br>
|
<br>
|
||||||
|
|
|
@ -19,8 +19,8 @@ describe('generateAvatarURL() gravatar enabled', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return correct urls', function () {
|
it('should return correct urls', function () {
|
||||||
assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', true), 'https://www.gravatar.com/avatar/d41b5f3508cc3f31865566a47dd0336b?s=400')
|
assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', true), 'https://cdn.libravatar.org/avatar/d41b5f3508cc3f31865566a47dd0336b?s=400')
|
||||||
assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', false), 'https://www.gravatar.com/avatar/d41b5f3508cc3f31865566a47dd0336b?s=96')
|
assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', false), 'https://cdn.libravatar.org/avatar/d41b5f3508cc3f31865566a47dd0336b?s=96')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return correct urls for names with spaces', function () {
|
it('should return correct urls for names with spaces', function () {
|
||||||
|
|