Move docs into subdirectory to make mkdocs work in a subdirectory

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

(cherry picked from commit eaeb88401d)
Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
Tilman Vatteroth 2021-01-04 13:07:44 +01:00 committed by David Mehren
parent a5ad35f94d
commit 4b7318ca33
No known key found for this signature in database
GPG key ID: 185982BA4C42B7C3
97 changed files with 1485 additions and 524 deletions

7
docs/content/dev/2.0.md Normal file
View file

@ -0,0 +1,7 @@
# 2.0 Development Hints
## Dev Setup
- Clone backend and frontend in two folders.
- Run `yarn install` in both projects
- Start the backend server in watch mode using `yarn start:dev`. The backend is then accessible on port 3000.
- Start the frontend dev server using `yarn start`. The frontend is now accessible on port 3001.

64
docs/content/dev/api.md Normal file
View file

@ -0,0 +1,64 @@
# API documentation
Several tasks of HedgeDoc can be automated through HTTP requests. The available endpoints for this api are described in
this document. For code-autogeneration there is an OpenAPIv3-compatible description available [here](openapi.yml).
## Notes
These endpoints create notes, return information about them or export them.
You have to replace *\<NOTE\>* with either the alias or id of a note you want to work on.
| Endpoint | HTTP-Method | Description |
| ---------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `/new` | `GET` | **Creates a new
note.**<br>A random id will be assigned and the content will equal to the template (blank by default). After note creation a redirect is issued to the created note. |
| `/new` | `POST` | **Imports some markdown data into a new
note.**<br>A random id will be assigned and the content will equal to the body of the received HTTP-request. The `Content-Type: text/markdown` header should be set on this request. |
| `/new/<ALIAS>` | `POST` | **Imports some markdown data into a new note with a
given alias.**<br>This endpoint equals to the above one except that the alias from the url will be assigned to the note
if [FreeURL-mode](../configuration.md#users-and-privileges) is enabled. | | `/<NOTE>/download`
or `/s/<SHORT-ID>/download` | `GET` | **Returns the raw markdown content of a note.**
| | `/<NOTE>/publish` | `GET` | **Redirects to the published version of the note.**
| | `/<NOTE>/slide` | `GET` | **Redirects to the slide-presentation of the
note.**<br>This is only useful on notes which are designed to be slides. | | `/<NOTE>/info`
| `GET` | **Returns metadata about the note.**<br>This includes the title and description of the note as well as
the creation date and viewcount. The data is returned as a JSON object. | | `/<NOTE>/revision`
| `GET` | **Returns a list of the available note revisions.**<br>The list is returned as a JSON object with an
array of revision-id and length associations. The revision-id equals to the timestamp when the revision was saved. |
| `/<NOTE>/revision/<REVISION-ID>` | `GET` | **Returns the revision of the note with some
metadata.**<br>The revision is returned as a JSON object with the content of the note and the authorship. |
| `/<NOTE>/gist` | `GET` | **Creates a new GitHub Gist with the note's
content.**<br>If [GitHub integration](../configuration.md#github-login) is configured, the user will be redirected to
GitHub and a new Gist with the content of the note will be created. |
## User / History
These endpoints return information about the current logged-in user and it's note history. If no user is logged-in, the
most of this requests will fail with either a HTTP 403 or a JSON object containing `{"status":"forbidden"}`.
| Endpoint | HTTP-Method | Description |
| ----------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/me` | `GET` | **Returns the profile data of the current logged-in
user.**<br>The data is returned as a JSON object containing the user-id, the user's name and a url to the profile picture. |
| `/me/export` | `GET` | **Exports a zip-archive with all notes of the current
user.** |
| `/history` | `GET` | **Returns a list of the last viewed
notes.**<br>The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status. |
| `/history` | `POST` | **Replace user's history with a new
one.**<br>The body must be form-encoded and contain a field `history` with a JSON-encoded array like its returned from the server when exporting the history. |
| `/history` | `DELETE` | **Deletes the user's
history.** |
| `/history/<NOTE>` | `POST` | **Toggles the pinned status in the history for a
note.**<br>The body must be form-encoded and contain a field `pinned` that is either `true` or `false`. |
| `/history/<NOTE>` | `DELETE` | **Deletes a note from the user's
history.** |
## HedgeDoc-server
These endpoints return information about the running HedgeDoc instance.
| Endpoint | HTTP-Method | Description |
| --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/status` | `GET` | **Returns the current status of the HedgeDoc
instance.**<br>The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more. |

View file

@ -0,0 +1,154 @@
@startuml
hide circle
skinparam nodesep 60
entity "Note" {
*id : uuid <<generated>>
--
*shortid : text
alias : text
*viewcount : number
*ownerId : uuid <<FK User>>
description: text
title: text
}
entity "User" {
*id : uuid <<generated>>
--
*userName : text
*displayName : text
*createdAt : date
*updatedAt : date
photo : text
email : text
}
entity "AuthToken" as authToken{
*id : number <<generated>>
--
*userId : uuid
*accessToken : text
}
entity "Identity" {
*id : number
--
*userId : uuid <<FK User>>
' Identifies the external login provider and is set in the config
*providerName : text
*syncSource : boolean
*createdAt : date
*updatedAt : date
' The unique identifier of a user from the login provider
providerUserId : text
' Token used to access the OAuth provider in the users name. Can be NULL
oauthAccessToken : text
' Password hash. Can be NULL
passwordHash : text
}
entity "Session" {
*id : text
--
*expiredAt : number
*json : text
}
entity "Revision" {
*id : number <<generated>>
--
*noteId : uuid <<FK Note>>
*content : text
*patch : text
*createdAt : date
*length : number
}
entity "Authorship" {
*id : uuid <<generated>>
--
*userId : uuid <FK User>>
*startPos : number
*endPos : number
*createdAt : date
*updatedAt : date
}
entity "RevisionAuthorship" {
*revisionId : number <<FK Revision>>
*authorshipId : uuid <<FK Authorship>>
}
entity "AuthorColors" {
*noteId : uuid <<FK Note>>
*userId : uuid <<FK User>>
--
*color : text
}
entity "NoteUserPermission" {
*userId : uuid <<FK User>>
*noteId : uuid <<FK Note>>
--
*canEdit : boolean
}
entity "Group" {
*id : number <<generated>>
--
*name : text <<unique>>
*displayName : text
' Is set to denote a special group
' Special groups are used to map the old share settings like "everyone can edit"
' or "logged in users can view" to the group permission system
*special : boolean
}
entity "NoteGroupPermission" {
*groupId : number <<FK Group>>
*noteId : uuid <<FK Note>>
--
*canEdit : boolean
}
entity "Tag" {
*id: number <<generated>>
*name: text
}
entity "MediaUpload" {
*id : text <<unique>>
--
*noteId : uuid <<FK Note>>
*userId : uuid <<FK User>>
*backendType: text
backendData: text
*createdAt : date
}
User "1" -- "0..*" Note: owner
User "1" -u- "1..*" Identity
User "1" - "1..*" authToken
User "1" -l- "1..*" Session
User "1" - "0..*" MediaUpload
User "0..*" -- "0..*" Note
User "1" - "0..*" Authorship
(User, Note) . AuthorColors
Revision "0..*" - "0..*" Authorship
(Revision, Authorship) .. RevisionAuthorship
MediaUpload "0..*" -- "1" Note
Note "1" - "1..*" Revision
Note "0..*" -l- "0..*" Tag
Note "0..*" -- "0..*" Group
User "0..*" -- "0..*" Note
(User, Note) . NoteUserPermission
(Note, Group) . NoteGroupPermission
@enduml

View file

@ -0,0 +1,37 @@
# Documentation
Our documentation is build with [mkdocs](https://www.mkdocs.org).
## Writing
All documentation files are found in the `docs/content` directory of
the [hedgedoc/hedgedoc repo](https://github.com/hedgedoc/hedgedoc). These files are just normal markdown files with
nothing special about them.
The configuration for mkdocs lies in the `docs` folder in a file called `mkdocs.yml`. With that file the theme and menu
- amoung others - can be configured.
**Please note:** Any new files need to be linked to by other files or put in the navigation or the files will be very
hard to find on the documentation website.
## Building
To build the documentation locally you need to perform the following steps:
0. Make sure you have python3 installed.
1. Go into the `docs` folder.
2. Install all the dependencies (E.g. with a [venv](https://docs.python.org/3/library/venv.html))
with `pip install -r requirements.txt`
3. Start the mkdocs dev server (`mkdocs serve`) or build the documentation (`mkdocs build`).
## Deployment
The documentation is deployed with [Messor Structor](https://github.com/traefik/structor).
The necessary Dockerfile and version menu template and also the github action to build the whole documentation can be
found in the [docs.hedgedoc.org repo](https://github.com/hedgedoc/docs.hedgedoc.org). This repo is also used to deploy
the actuall website to github.io.
Messor Structor builds and deploys the documentation by finding all branches that follow the pattern `v*`. For each
branch the docs are generated separately by first installing the dependencies from `requirements.txt` and then running
mkdocs. Afterwards the menu go template is used to include a version switcher in the theme.

View file

@ -0,0 +1,54 @@
# Getting started
## 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/hedgedoc/hedgedoc.git hedgedoc-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.md) or set up
[environment variables](../configuration.md).
## Running the Code
Now that everything is in place, we can start HedgeDoc:
1. `yarn run build` will build the frontend bundle. It uses webpack to do that.
2. 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.
1. Use `yarn run dev` if you want webpack to continuously rebuild the frontend code.
2. 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
hedgedoc-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
```

View file

@ -0,0 +1,456 @@
openapi: 3.0.1
info:
title: HedgeDoc
description: HedgeDoc is an open source collaborative note editor. Several tasks of HedgeDoc can be automated through this API.
version: 1.7.1
contact:
name: HedgeDoc on GitHub
url: https://github.com/hedgedoc/hedgedoc
license:
name: AGPLv3
url: https://github.com/hedgedoc/hedgedoc/blob/master/LICENSE
externalDocs:
url: https://github.com/hedgedoc/hedgedoc/blob/master/docs/dev/api.md
paths:
/new:
get:
tags:
- note
summary: Creates a new note.
description: A random id will be assigned and the content will equal to the template (blank by default). After note creation a redirect is issued to the created note.
responses:
default:
description: Redirect to the new note
post:
tags:
- note
summary: Imports some markdown data into a new note.
description: A random id will be assigned and the content will equal to the body of the received HTTP-request.
requestBody:
required: true
description: The content of the note to be imported as markdown
content:
'text/markdown':
example: '# Some header'
responses:
default:
description: Redirect to the imported note
/new/{alias}:
post:
tags:
- note
summary: Imports some markdown data into a new note with a given alias.
description: 'This endpoint equals to the above one except that the alias from the url will be assigned to the note if [FreeURL-mode](../configuration-env-vars.md#users-and-privileges) is enabled.'
requestBody:
required: true
description: The content of the note to be imported as markdown
content:
'text/markdown':
example: '# Some heading'
responses:
default:
description: Redirect to the imported note
parameters:
- name: alias
in: path
required: true
description: The alias for the note-id under which the note will be saved
content:
'text/plain':
example: my-note
/{note}/download:
get:
tags:
- note
summary: Returns the raw markdown content of a note.
responses:
200:
description: The raw markdown content of the note
content:
'text/markdown':
example: '# Some heading'
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note which should be downloaded
content:
'text/plain':
example: my-note
/{note}/publish:
get:
tags:
- note
summary: Redirects to the published version of the note.
responses:
default:
description: Redirect to the published version of the note
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note which should be published
content:
'text/plain':
example: my-note
/{note}/slide:
get:
tags:
- note
summary: Redirects to the slide-presentation of the note.
description: This is only useful on notes which are designed to be slides.
responses:
default:
description: Redirect to the slide version of the note
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note which should be shown as slide
content:
'text/plain':
example: my-note
/{note}/info:
get:
tags:
- note
summary: Returns metadata about the note.
description: This includes the title and description of the note as well as the creation date and viewcount.
responses:
200:
description: Metadata about the note
content:
'text/json':
schema:
type: object
properties:
title:
type: string
description: The title of the note
default: Untitled
description:
type: string
description: The description of the note or the first words from the note
viewcount:
type: integer
minimum: 0
description: How often the published version of the note was viewed
createtime:
type: string
description: The timestamp when the note was created in ISO 8601 format.
updatetime:
type: string
description: The timestamp when the note was last updated in ISO 8601 format.
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note for which the info should be shown
content:
'text/plain':
example: my-note
/{note}/revision:
get:
tags:
- note
summary: Returns a list of the available note revisions.
description: The list is returned as a JSON object with an array of revision-id and length associations. The revision-id equals to the timestamp when the revision was saved.
responses:
200:
description: Revisions of the note
content:
'text/json':
schema:
type: object
properties:
revision:
type: array
description: Array that holds all revision-info objects
items:
type: object
properties:
time:
type: integer
description: UNIX-timestamp of when the revision was saved. Is also the revision-id.
length:
type: integer
description: Length of the document to the timepoint the revision was saved
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note for which revisions should be shown
content:
'text/plain':
example: my-note
/{note}/revision/{revision-id}:
get:
tags:
- note
summary: Returns the revision of the note with some metadata.
description: The revision is returned as a JSON object with the content of the note and the authorship.
responses:
200:
description: Revision of the note for the given timestamp
content:
'text/json':
schema:
type: object
properties:
content:
type: string
description: The raw markdown content of the note revision
authorship:
type: array
description: Data which gives insights about who worked on the note
items:
type: integer
description: Unique user ids and additional data
patch:
type: array
description: Data which gives insight about what changed in comparison to former revisions
items:
type: string
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note for which the revision should be shown
content:
'text/plain':
example: my-note
- name: revision-id
in: path
required: true
description: The id (timestamp) of the revision to fetch
content:
'text/plain':
example: 1570921051959
/{note}/gist:
get:
tags:
- note
summary: Creates a new GitHub Gist with the note's content.
description: 'If [GitHub integration](https://github.com/hedgedoc/hedgedoc/blob/master/docs/configuration-env-vars.md#github-login) is configured, the user will be redirected to GitHub and a new Gist with the content of the note will be created.'
responses:
default:
description: Redirect to the created gist (or the GitHub authentication before)
404:
description: Note does not exist
parameters:
- name: note
in: path
required: true
description: The note which should be pasted to GitHub gist
content:
'text/plain':
example: my-note
/me:
get:
tags:
- user
summary: Returns the profile data of the current logged-in user.
description: The data is returned as a JSON object containing the user-id, the user's name and a url to the profile picture. Requires an active session of the user.
responses:
200:
description: If the user is logged-in, the user data otherwise `{"status":"forbidden"}`
content:
'text/json':
schema:
type: object
properties:
status:
type: string
description: ok if everything works as expected, forbidden is the user is not logged-in
id:
type: string
description: Unique id of the user
name:
type: string
description: The user's display name
photo:
type: string
description: An url to the online stored user profile photo
/me/export:
get:
tags:
- user
summary: Exports a zip-archive with all notes of the current user.
responses:
default:
description: The zip-archive with all notes
/history:
get:
tags:
- user
summary: Returns a list of the last viewed notes.
description: The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status.
responses:
200:
description: The list of recently viewed notes and pinned notes
content:
'text/json':
schema:
type: object
properties:
history:
type: array
description: The array that contains history objects
items:
type: object
properties:
id:
type: string
description: The id or alias of the note
text:
type: string
description: The title of the note
time:
type: integer
description: The UNIX-timestamp when the note was last accessed by the user
tags:
type: array
description: The tags that were added by the user to the note
items:
type: string
pinned:
type: boolean
description: Whether the user has pinned this note
post:
tags:
- user
summary: Replace user's history with a new one.
description: The body must be form-encoded and contain a field `history` with a JSON-encoded array like its returned from the server when exporting the history.
requestBody:
required: true
content:
'application/x-www-form-urlencoded':
example: 'history=[{"id":"example","text":"Untitled","time":1556275442010,"tags":[],"pinned":false}]'
responses:
200:
description: History replaced
delete:
tags:
- user
summary: Deletes the user's history.
responses:
200:
description: User's history deleted
/history/{note}:
post:
tags:
- user
summary: Toggles the pinned status in the history for a note.
description: The body must be form-encoded and contain a field `pinned` that is either `true` or `false`.
requestBody:
required: true
content:
'application/x-www-form-urlencoded':
example: 'pinned=false'
responses:
200:
description: Pinned state toggled
parameters:
- name: note
in: path
required: true
description: The note for which the pinned state should be toggled
content:
'text/plain':
example: my-note
delete:
tags:
- user
summary: Deletes a note from the user's history.
responses:
200:
description: Pinned state toggled
parameters:
- name: note
in: path
required: true
description: The note for which the pinned state should be toggled
content:
'text/plain':
example: my-note
/status:
get:
tags:
- server
summary: Returns the current status of the HedgeDoc instance.
description: The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more.
responses:
200:
description: The server info
content:
'text/json':
schema:
type: object
properties:
onlineNotes:
type: integer
description: How many notes are edited at the moment
onlineUsers:
type: integer
description: How many users are online at the moment
distinctOnlineUsers:
type: integer
description: How many distinct users (different machines) are online at the moment
notesCount:
type: integer
description: How many notes are stored on the server
registeredUsers:
type: integer
description: How many users are registered on the server
onlineRegisteredUsers:
type: integer
description: How many of the online users are registered on the server
distinctOnlineRegisteredUsers:
type: integer
description: How many of the distinct online users are registered on the server
isConnectionBusy:
type: boolean
connectionSocketQueueLength:
type: integer
isDisconnectBusy:
type: boolean
disconnectSocketQueueLength:
type: integer
tags:
- name: note
description: These endpoints create notes, return information about them or export them.
- name: user
description: These endpoints return information about the current logged-in user and it's note history. If no user is logged-in, the most of this requests will fail with either a HTTP 403 or a JSON object containing `{"status":"forbidden"}`.
- name: server
description: These endpoints return information about the running HedgeDoc instance.

14
docs/content/dev/ot.md Normal file
View 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

View file

@ -0,0 +1,932 @@
openapi: 3.0.3
info:
title: HedgeDoc
description: HedgeDoc is an open source collaborative note editor. Several tasks of HedgeDoc can be automated through this API.
version: 2.0.0
contact:
name: HedgeDoc on GitHub
url: https://github.com/codimd/server
license:
name: AGPLv3
url: https://github.com/codimd/server/blob/master/LICENSE
externalDocs:
description: The CodiMD Documentation.
url: https://github.com/codimd/server/tree/master/docs
servers:
- url: "/api/v2"
description: The base API Path.
security:
- bearerAuth: []
paths:
/me:
get:
tags:
- user
summary: Get the user information of the currently logged-in user
operationId: getMe
responses:
'200':
description: The user information.
content:
application/json:
schema:
"$ref": "#/components/schemas/UserInfo"
'401':
"$ref": "#/components/responses/UnauthorizedError"
/me/history:
get:
tags:
- history
- user
summary: Returns a list of the last viewed notes
operationId: getHistory
description: The list is returned as a JSON object with an array containing for each entry it's id, title, tags, last visit time and pinned status.
responses:
'200':
description: The list of recently viewed notes and pinned notes.
content:
application/json:
schema:
type: array
items:
"$ref": "#/components/schemas/History"
'401':
"$ref": "#/components/responses/UnauthorizedError"
/me/history/{note}:
get:
tags:
- history
- user
summary: Returns History data for a note
operationId: getHistoryObject
description: JSON Object which contains id, title, tags, last visit time and pinned status
responses:
'200':
description: Information about the history entry
content:
application/json:
schema:
"$ref": "#/components/schemas/History"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The name of the note which is used to address it.
content:
text/plain:
example: my-note
put:
tags:
- history
- user
summary: Update the history object of the note (e.g change it's pin status)
operationId: updateHistoryObject
requestBody:
description: The updated history object.
content:
application/json:
schema:
"$ref": "#/components/schemas/HistoryUpdate"
responses:
'200':
description: The new history object.
content:
application/json:
schema:
"$ref": "#/components/schemas/History"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the revision should be shown.
content:
text/plain:
example: my-note
delete:
tags:
- history
- user
summary: Remove the note from the currently logged-in user's history
operationId: deleteHistoryObject
responses:
'204':
"$ref": "#/components/responses/SuccessfullyDeleted"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the revision should be shown.
content:
text/plain:
example: my-note
/me/notes:
get:
tags:
- user
summary: Returns a list of the notes metadata the user owns
operationId: getOwnNotes
description: The list is returned as a JSON object with an array containing each notes metadata.
responses:
'200':
description: The list of notes owned by the currently logged in user.
content:
application/json:
schema:
type: array
description: The array that contains notes metadata.
items:
"$ref": "#/components/schemas/NoteMetadata"
'401':
"$ref": "#/components/responses/UnauthorizedError"
/me/media:
get:
tags: [ user, media ]
summary: Get list of uploaded files owned by the current user
operationId: getOwnMedia
responses:
'200':
description:
content:
application/json:
schema:
type: array
items:
"$ref": "#/components/schemas/MediaUpload"
/notes:
post:
tags:
- note
summary: Imports some markdown data into a new note
operationId: createNoteFromMarkdown
description: A random id will be assigned and the content will equal to the body of the received HTTP-request.
security:
- bearerAuth: [ ]
- { }
requestBody:
required: false
description: The content of the note to be imported as markdown.
content:
'text/markdown':
schema:
type: string
examples:
markdownExample:
"$ref": '#/components/examples/markdownExample'
responses:
'201':
description: Get information about the newly created note.
content:
application/json:
schema:
"$ref": "#/components/schemas/Note"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
/notes/{note}:
get:
tags:
- note
summary: Returns the note
operationId: getNote
description: This includes all metadata and the content of the note.
responses:
'200':
description: All data of the note.
content:
application/json:
schema:
"$ref": "#/components/schemas/Note"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The name of the note which is used to address it.
content:
text/plain:
example: my-note
post:
tags:
- note
summary: Imports some markdown data into a new note with a given alias
operationId: createNoteWithAlias
description: This endpoint creates a new note with the content of the HTTP request body and the alias from the URL parameter.
requestBody:
required: true
description: The content of the note to be imported as markdown.
content:
'text/markdown':
schema:
type: string
examples:
markdownExample:
"$ref": '#/components/examples/markdownExample'
responses:
'201':
description: Get information about the newly created note.
content:
application/json:
schema:
"$ref": "#/components/schemas/Note"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'409':
description: This alias is already in use.
parameters:
- name: note
in: path
required: true
description: The name of the note which is used to address it.
content:
text/plain:
example: my-note
delete:
tags:
- note
summary: Remove the note
operationId: deleteNote
responses:
'204':
"$ref": "#/components/responses/SuccessfullyDeleted"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the revision should be shown.
content:
text/plain:
example: my-note
put:
tags:
- note
summary: Imports some markdown data into an existing note, creating a new revision
operationId: createNewRevisionForNote
description: This endpoint updates the note content of an existing note. The old content is completely replaced and a new revision is created.
requestBody:
required: true
description: The content of the note to be imported as markdown.
content:
'text/markdown':
schema:
type: string
examples:
markdownExample:
"$ref": '#/components/examples/markdownExample'
responses:
'200':
description: The new, changed note
content:
application/json:
schema:
"$ref": "#/components/schemas/Note"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the info should be shown.
content:
text/plain:
example: my-note
/notes/{note}/metadata:
get:
tags:
- note
summary: Get the metadata of a note
operationId: getNoteMetadata
responses:
'200':
description: The metadata of the note.
content:
application/json:
schema:
"$ref": "#/components/schemas/NoteMetadata"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the info should be shown.
content:
text/plain:
example: my-note
/notes/{note}/permissions:
put:
tags: [ note ]
summary: Set permissions of a note
operationId: updateNotePermissions
requestBody:
required: true
content:
application/json:
schema:
"$ref": "#/components/schemas/NotePermissionsUpdate"
responses:
'200':
description: The updated permissions of the note.
content:
application/json:
schema:
"$ref": "#/components/schemas/NotePermissions"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the info should be shown.
content:
text/plain:
example: my-note
/notes/{note}/revisions:
get:
tags:
- note
summary: Returns a list of the available note revisions
operationId: getAllRevisionsOfNote
description: The list contains the revision-id, the length and a ISO-timestamp of the creation date.
responses:
'200':
description: Revisions of the note.
content:
application/json:
schema:
type: array
items:
"$ref": "#/components/schemas/NoteRevisionsMetadata"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which revisions should be shown.
content:
text/plain:
example: my-note
/notes/{note}/revisions/{revision-id}:
get:
tags:
- note
summary: Returns the revision of the note with some metadata
operationId: getSpecificRevisionOfNote
description: The revision is returned as a JSON object with the content of the note and the authorship.
responses:
'200':
description: Revision of the note for the given id.
content:
application/json:
schema:
"$ref": "#/components/schemas/NoteRevision"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the revision should be shown.
content:
text/plain:
example: my-note
- name: revision-id
in: path
required: true
description: The id of the revision to fetch.
content:
text/plain:
example: 1570921051959
/notes/{note}/content:
get:
tags:
- note
- export
summary: Returns the raw markdown content of a note
operationId: getNoteContent
responses:
'200':
description: The raw markdown content of the note.
content:
'text/markdown':
schema:
type: string
format: binary
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
parameters:
- name: note
in: path
required: true
description: The note for which the markdown should be exported.
content:
text/plain:
example: my-note
/notes/{note}/media:
get:
tags: [ note, media ]
summary: Get list of files uploaded to the note
operationId: getOwnMedia
responses:
'200':
description:
content:
application/json:
schema:
type: array
items:
"$ref": "#/components/schemas/MediaUpload"
/media:
post:
tags:
- media
summary: Uploads a media file to the backend storage
description: Uploads a file to be processed by the backend.
requestBody:
required: true
description: The binary file to upload.
content:
application/pdf:
schema:
type: string
format: binary
image/apng:
schema:
type: string
format: binary
image/bmp:
schema:
type: string
format: binary
image/gif:
schema:
type: string
format: binary
image/heif:
schema:
type: string
format: binary
image/heic:
schema:
type: string
format: binary
image/heif-sequence:
schema:
type: string
format: binary
image/heic-sequence:
schema:
type: string
format: binary
image/jpeg:
schema:
type: string
format: binary
image/png:
schema:
type: string
format: binary
image/svg+xml:
schema:
type: string
format: binary
image/tiff:
schema:
type: string
format: binary
image/webp:
schema:
type: string
format: binary
parameters:
- in: header
name: HedgeDoc-Note
schema:
type: string
required: true
description: ID or alias of the parent note
responses:
'201':
description: The file was uploaded successfully.
content:
application/json:
schema:
type: object
properties:
link:
type: string
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
/media/{filename}:
delete:
tags:
- media
summary: Delete the specified file
operationId: deleteMedia
parameters:
- name: filename
in: path
required: true
description: The name of the file to be deleted.
content:
text/plain:
example: e18d1b83e1821128615bad849ad0655a.jpg
responses:
'204':
"$ref": "#/components/responses/SuccessfullyDeleted"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
'404':
"$ref": "#/components/responses/NotFoundError"
/monitoring:
get:
tags:
- monitoring
summary: Returns the current status of the backend
operationId: getMonitoring
description: The data is returned as a JSON object containing the number of notes stored on the server, (distinct) online users and more.
responses:
'200':
description: The server info.
content:
application/json:
schema:
"$ref": "#/components/schemas/ServerStatus"
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
/monitoring/prometheus:
get:
tags:
- monitoring
summary: Returns the current status of the backend for Prometheus.
operationId: getPrometheus
description: The data is returned in Prometheus Exposition Format
responses:
'200':
description: Prometheus compatible monitoring data.
content:
text/plain: {}
'401':
"$ref": "#/components/responses/UnauthorizedError"
'403':
"$ref": "#/components/responses/ForbiddenError"
components:
schemas:
UserInfo:
type: object
properties:
userName:
type: string
displayName:
type: string
photo:
type: string
format: uri
email:
type: string
format: email
UserPasswordChange:
type: object
properties:
password:
type: string
GroupInfo:
type: object
properties:
name:
type: string
displayName:
type: string
special:
type: boolean
ImageProxyRequest:
type: object
properties:
src:
type: string
description: The url of the image that should be processed by the image proxy.
ImageProxyResponse:
type: object
properties:
src:
type: string
description: The url of the provied version of the image.
Note:
type: object
properties:
content:
type: string
description: The markdown content of the note
metadata:
$ref: "#/components/schemas/NoteMetadata"
editedByAtPosition:
type: array
description: Data which gives insights about who worked where on the note.
items:
type: integer
description: Unique user ids and additional data
NoteMetadata:
type: object
properties:
id:
type: string
format: UUIDv4
description: The id of the note.
alias:
type: string
description: The alias of the note.
title:
type: string
description: Title of the note
description:
type: string
description: Description of the note.
tags:
type: array
description: A list of tags attached to the note.
items:
type: string
description: A tag
updateTime:
type: string
description: ISO-timestamp of when the note was last changed.
updateUser:
$ref: "#/components/schemas/UserInfo"
viewCount:
type: integer
minimum: 0
description: How often the published version of the note was viewed.
createTime:
type: string
description: The ISO-timestamp when the note was created in ISO 8601 format.
editedBy:
type: array
description: List of usernames who edited the note.
items:
type: string
permissions:
$ref: "#/components/schemas/NotePermissions"
NotePermissions:
type: object
properties:
owner:
$ref: "#/components/schemas/UserInfo"
sharedToUsers:
type: array
description: Contains all users that can read the note and a boolean that denotes if they can also edit.
items:
type: object
properties:
user:
$ref: "#/components/schemas/UserInfo"
canEdit:
type: boolean
sharedToGroups:
type: array
description: Contains all groups that can read the note and a boolean that denotes if they can also edit.
items:
type: object
properties:
group:
$ref: "#/components/schemas/GroupInfo"
canEdit:
type: boolean
NotePermissionsUpdate:
type: object
description: Contains only title, description and tags of a note.
properties:
sharedToUsers:
type: array
description: Contains all usernames that can read the note and a boolean that denotes if they can also edit.
items:
type: object
properties:
username:
type: string
canEdit:
type: boolean
sharedToGroups:
type: array
description: Contains all groups that can read the note and a boolean that denotes if they can also edit.
items:
type: object
properties:
groupname:
type: string
canEdit:
type: boolean
NoteRevisionsMetadata:
type: object
properties:
id:
type: integer
description: The id of the revision
createdTime:
type: string
description: ISO-timestamp of when the revision was saved. Is also the revision-id.
length:
type: integer
description: Length of the document to the timepoint the revision was saved.
NoteRevision:
type: object
properties:
content:
type: string
description: The raw markdown content of the note revision.
authorship:
type: array
description: Data which gives insights about who worked on the note.
items:
type: integer
description: Unique user ids and additional data.
patch:
type: array
description: Data which gives insight about what changed in comparison to former revisions.
items:
type: string
GistLink:
type: object
properties:
link:
type: string
format: uri
description: A Gist link.
DropboxLink:
type: object
properties:
link:
type: string
format: uri
description: A Dropbox link.
EmailLogin:
type: object
properties:
email:
type: string
format: email
password:
type: string
format: password
LdapLogin:
type: object
properties:
username:
type: string
format: email
password:
type: string
format: password
OpenIdLogin:
type: object
properties:
openId:
type: string
ServerStatus:
type: object
properties:
serverVersion:
type: object
properties:
major:
type: integer
minor:
type: integer
patch:
type: integer
preRelease:
type: string
commit:
type: string
description: Version of the server specified according to SemVer specification
onlineNotes:
type: integer
description: How many notes are edited at the moment.
onlineUsers:
type: integer
description: How many users are online at the moment.
distinctOnlineUsers:
type: integer
description: How many distinct users (different machines) are online at the moment.
notesCount:
type: integer
description: How many notes are stored on the server.
registeredUsers:
type: integer
description: How many users are registered on the server.
onlineRegisteredUsers:
type: integer
description: How many of the online users are registered on the server.
distinctOnlineRegisteredUsers:
type: integer
description: How many of the distinct online users are registered on the server.
isConnectionBusy:
type: boolean
connectionSocketQueueLength:
type: integer
isDisconnectBusy:
type: boolean
disconnectSocketQueueLength:
type: integer
History:
type: object
properties:
metadata:
$ref: "#/components/schemas/NoteMetadata"
pinned:
type: boolean
description: Whether the user has pinned this note.
HistoryUpdate:
type: object
properties:
pinned:
type: boolean
description: Whether the user has pinned this note.
MediaUpload:
type: object
properties:
note:
type: string
description: ID of the note the file was uploaded to
user:
type: string
description: username of the user who uploaded the file
url:
type: string
description: URL of the file
createdAt:
type: string
format: date-time
description: Date when the file was upladed
examples:
markdownExample:
value: '# Some header\nSome normal text. **Some bold text**'
summary: A sample markdown content
securitySchemes:
bearerAuth:
type: http
scheme: bearer
responses:
UnauthorizedError:
description: Authorization information is missing or invalid.
ForbiddenError:
description: Access to the requested resource is not permitted.
NotFoundError:
description: The requested resource was not found.
SuccessfullyDeleted:
description: The requested resource was sucessfully deleted.

View file

@ -0,0 +1,40 @@
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`
This file contains all common definitions for chunks and plugins that are needed by the whole app.
The various entrypoints under the `entry` key define groups of files (npm packages or .css/.js files directly from this project) that need to be included together to be useful.
The `index` group for example bundles all javascript files and libraries used for the note editor.
Entrypoints are referenced in the `plugins` section.
The `HtmlWebpackPlugin` uses templates in `public/views/includes` to include the path to the generated resources in new templates under `public/views/build`. These templates are then used by the backend to serve HTML to the browser.
**TODO:** Document which entry points are used for what.
## `webpack.htmlexport.js`
Separate config for the "save as html" feature.
Packs all CSS from `public/js/htmlExport.js` to `build/html.min.css`.
This file is then downloaded by client-side JS and used to create the HTML.
See `exportToHTML()` in `public/js/extra.js`.
## `webpack.dev.js`
The development config uses both common configs, enables development mode and enables "cheap" source maps (lines only).
If you need more detailed source maps while developing, you might want to use the `source-maps` option.
See https://webpack.js.org/configuration/devtool/ for details.
## `webpack.prod.js`
The production config uses both common configs and enables production mode.
This automatically enables various optimizations (e.g. UglifyJS). See https://webpack.js.org/concepts/mode/ for details.
For the global app config, the name of the emitted chunks is changed to include the content hash.
See https://webpack.js.org/guides/caching/ on why this is a good idea.
For the HTML export config, CSS minification is enabled.