diff --git a/lib/models/revision.ts b/lib/models/revision.ts
index fcac5e7fd..76de7e0ff 100644
--- a/lib/models/revision.ts
+++ b/lib/models/revision.ts
@@ -114,7 +114,7 @@ export class Revision extends Model<Revision> {
   @BelongsTo(() => Note, { foreignKey: 'noteId', constraints: false, onDelete: 'CASCADE', hooks: true })
   note: Note;
 
-  getNoteRevisions (note: Note, callback): void {
+  static getNoteRevisions (note: Note, callback): void {
     Revision.findAll({
       where: {
         noteId: note.id
@@ -138,7 +138,7 @@ export class Revision extends Model<Revision> {
     })
   }
 
-  getPatchedNoteRevisionByTime (note: Note, time, errorCallback): void {
+  static getPatchedNoteRevisionByTime (note: Note, time, errorCallback): void {
     // find all revisions to prepare for all possible calculation
     Revision.findAll({
       where: {
diff --git a/lib/web/note/actions.ts b/lib/web/note/actions.ts
index ac52f1fac..30db0f507 100644
--- a/lib/web/note/actions.ts
+++ b/lib/web/note/actions.ts
@@ -1,87 +1,59 @@
-import {Response} from "express";
+import { Response } from 'express'
 
-const models = require('../../models')
-const logger = require('../../logger')
-const config = require('../../config')
-const errors = require('../../errors')
-const shortId = require('shortid')
-const moment = require('moment')
-const querystring = require('querystring')
+import { Note, Revision } from '../../models'
+import logger from '../../logger'
+import config from '../../config'
+import errors from '../../errors'
+import shortId from 'shortid'
+import moment from 'moment'
+import querystring from 'querystring'
 
-export module ActionController {
-
-  // TODO: Use correct type for note
-  export function getInfo(req: any, res: Response, note: any) {
-    const body = note.content
-    const extracted = models.Note.extractMeta(body)
-    const markdown = extracted.markdown
-    const meta = models.Note.parseMeta(extracted.meta)
-    const createtime = note.createdAt
-    const updatetime = note.lastchangeAt
-    const title = models.Note.decodeTitle(note.title)
-    const data = {
-      title: meta.title || title,
-      description: meta.description || (markdown ? models.Note.generateDescription(markdown) : null),
-      viewcount: note.viewcount,
-      createtime: createtime,
-      updatetime: updatetime
-    }
-    res.set({
-      'Access-Control-Allow-Origin': '*', // allow CORS as API
-      'Access-Control-Allow-Headers': 'Range',
-      'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',
-      'Cache-Control': 'private', // only cache by client
-      'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
-    })
-    res.send(data)
+export function getInfo (req: any, res: Response, note: Note): void {
+  const body = note.content
+  const extracted = Note.extractMeta(body)
+  const markdown = extracted.markdown
+  const meta = Note.parseMeta(extracted.meta)
+  const title = Note.decodeTitle(note.title)
+  const data = {
+    title: meta.title || title,
+    description: meta.description || (markdown ? Note.generateDescription(markdown) : null),
+    viewcount: note.viewcount,
+    createtime: note.createdAt,
+    updatetime: note.lastchangeAt
   }
+  res.set({
+    'Access-Control-Allow-Origin': '*', // allow CORS as API
+    'Access-Control-Allow-Headers': 'Range',
+    'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',
+    'Cache-Control': 'private', // only cache by client
+    'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
+  })
+  res.send(data)
+}
 
-  // TODO: Use correct type for note
-  export function createGist(req: any, res: Response, note: any) {
-    const data = {
-      client_id: config.github.clientID,
-      redirect_uri: config.serverURL + '/auth/github/callback/' + models.Note.encodeNoteId(note.id) + '/gist',
-      scope: 'gist',
-      state: shortId.generate()
-    }
-    const query = querystring.stringify(data)
-    res.redirect('https://github.com/login/oauth/authorize?' + query)
+export function createGist (req: any, res: Response, note: Note): void {
+  const data = {
+    client_id: config.github.clientID,
+    redirect_uri: config.serverURL + '/auth/github/callback/' + Note.encodeNoteId(note.id) + '/gist',
+    scope: 'gist',
+    state: shortId.generate()
   }
+  const query = querystring.stringify(data)
+  res.redirect('https://github.com/login/oauth/authorize?' + query)
+}
 
-  // TODO: Use correct type for note
-  export function getRevision(req: any, res: Response, note: any) {
-    const actionId = req.params.actionId
-    if (actionId) {
-      const time = moment(parseInt(actionId))
-      if (time.isValid()) {
-        models.Revision.getPatchedNoteRevisionByTime(note, time, function (err, content) {
-          if (err) {
-            logger.error(err)
-            return errors.errorInternalError(res)
-          }
-          if (!content) {
-            return errors.errorNotFound(res)
-          }
-          res.set({
-            'Access-Control-Allow-Origin': '*', // allow CORS as API
-            'Access-Control-Allow-Headers': 'Range',
-            'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',
-            'Cache-Control': 'private', // only cache by client
-            'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
-          })
-          res.send(content)
-        })
-      } else {
-        return errors.errorNotFound(res)
-      }
-    } else {
-      models.Revision.getNoteRevisions(note, function (err, data) {
+export function getRevision (req: any, res: Response, note: Note): void {
+  const actionId = req.params.actionId
+  if (actionId) {
+    const time = moment(parseInt(actionId))
+    if (time.isValid()) {
+      Revision.getPatchedNoteRevisionByTime(note, time, function (err, content) {
         if (err) {
           logger.error(err)
-          return errors.errorInternalError(res)
+          errors.errorInternalError(res)
         }
-        const out = {
-          revision: data
+        if (!content) {
+          errors.errorNotFound(res)
         }
         res.set({
           'Access-Control-Allow-Origin': '*', // allow CORS as API
@@ -90,8 +62,28 @@ export module ActionController {
           'Cache-Control': 'private', // only cache by client
           'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
         })
-        res.send(out)
+        res.send(content)
       })
+    } else {
+      errors.errorNotFound(res)
     }
+  } else {
+    Revision.getNoteRevisions(note, function (err, data) {
+      if (err) {
+        logger.error(err)
+        errors.errorInternalError(res)
+      }
+      const out = {
+        revision: data
+      }
+      res.set({
+        'Access-Control-Allow-Origin': '*', // allow CORS as API
+        'Access-Control-Allow-Headers': 'Range',
+        'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',
+        'Cache-Control': 'private', // only cache by client
+        'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
+      })
+      res.send(out)
+    })
   }
 }
diff --git a/lib/web/note/controller.ts b/lib/web/note/controller.ts
index b8184d7f5..3c29ce1ba 100644
--- a/lib/web/note/controller.ts
+++ b/lib/web/note/controller.ts
@@ -1,41 +1,40 @@
-import {NextFunction, Response} from "express";
-import {NoteUtils} from "./util";
-import { ActionController } from "./actions";
-import errors from "../../errors";
-import config from "../../config";
-import logger from "../../logger";
-import { User } from "../../models/user";
-import { Note } from "../../models/note";
+import { NextFunction, Response } from 'express'
+import { NoteUtils } from './util'
+import * as ActionController from './actions'
+import errors from '../../errors'
+import config from '../../config'
+import logger from '../../logger'
+import { User, Note } from '../../models'
 
 export module NoteController {
-  export function publishNoteActions(req: any, res: Response, next: NextFunction) {
+  export function publishNoteActions (req: any, res: Response, next: NextFunction) {
     NoteUtils.findNoteOrCreate(req, res, function (note) {
-      const action = req.params.action;
+      const action = req.params.action
       switch (action) {
         case 'download':
-          exports.downloadMarkdown(req, res, note);
-          break;
+          exports.downloadMarkdown(req, res, note)
+          break
         case 'edit':
-          res.redirect(config.serverURL + '/' + (note.alias ? note.alias : Note.encodeNoteId(note.id)) + '?both');
-          break;
+          res.redirect(config.serverURL + '/' + (note.alias ? note.alias : Note.encodeNoteId(note.id)) + '?both')
+          break
         default:
-          res.redirect(config.serverURL + '/s/' + note.shortid);
+          res.redirect(config.serverURL + '/s/' + note.shortid)
           break
       }
     })
   }
 
-  export function showPublishNote(req: any, res: Response, next: NextFunction) {
+  export function showPublishNote (req: any, res: Response, next: NextFunction) {
     const include = [{
       model: User,
       as: 'owner'
     }, {
       model: User,
       as: 'lastchangeuser'
-    }];
+    }]
     NoteUtils.findNoteOrCreate(req, res, function (note) {
       // force to use short id
-      const shortid = req.params.shortid;
+      const shortid = req.params.shortid
       if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) {
         return res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid))
       }
@@ -46,34 +45,34 @@ export module NoteController {
         NoteUtils.getPublishData(req, res, note, (data) => {
           res.set({
             'Cache-Control': 'private' // only cache by client
-          });
+          })
           return res.render('pretty.ejs', data)
         })
       }).catch(function (err) {
-        logger.error(err);
+        logger.error(err)
         return errors.errorInternalError(res)
       })
     }, include)
   }
 
-  export function showNote(req: any, res: Response, next: NextFunction) {
+  export function showNote (req: any, res: Response, next: NextFunction) {
     NoteUtils.findNoteOrCreate(req, res, function (note) {
       // force to use note id
-      const noteId = req.params.noteId;
-      const id = Note.encodeNoteId(note.id);
+      const noteId = req.params.noteId
+      const id = Note.encodeNoteId(note.id)
       if ((note.alias && noteId !== note.alias) || (!note.alias && noteId !== id)) {
         return res.redirect(config.serverURL + '/' + (note.alias || id))
       }
-      const body = note.content;
-      const extracted = Note.extractMeta(body);
-      const meta = Note.parseMeta(extracted.meta);
-      let title = Note.decodeTitle(note.title);
-      title = Note.generateWebTitle(meta.title || title);
-      const opengraph = Note.parseOpengraph(meta, title);
+      const body = note.content
+      const extracted = Note.extractMeta(body)
+      const meta = Note.parseMeta(extracted.meta)
+      let title = Note.decodeTitle(note.title)
+      title = Note.generateWebTitle(meta.title || title)
+      const opengraph = Note.parseOpengraph(meta, title)
       res.set({
         'Cache-Control': 'private', // only cache by client
         'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
-      });
+      })
       return res.render('codimd.ejs', {
         title: title,
         opengraph: opengraph
@@ -81,52 +80,52 @@ export module NoteController {
     })
   }
 
-  export function createFromPOST(req: any, res: Response, next: NextFunction) {
-    let body = '';
+  export function createFromPOST (req: any, res: Response, next: NextFunction) {
+    let body = ''
     if (req.body && req.body.length > config.documentMaxLength) {
       return errors.errorTooLong(res)
     } else if (req.body) {
       body = req.body
     }
-    body = body.replace(/[\r]/g, '');
+    body = body.replace(/[\r]/g, '')
     return NoteUtils.newNote(req, res, body)
   }
 
-  export function doAction(req: any, res: Response, next: NextFunction) {
-    const noteId = req.params.noteId;
+  export function doAction (req: any, res: Response, next: NextFunction) {
+    const noteId = req.params.noteId
     NoteUtils.findNoteOrCreate(req, res, (note) => {
-      const action = req.params.action;
+      const action = req.params.action
       // TODO: Don't switch on action, choose action in Router and use separate functions
       switch (action) {
         case 'publish':
         case 'pretty': // pretty deprecated
-          res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid));
-          break;
+          res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid))
+          break
         case 'slide':
-          res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid));
-          break;
+          res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid))
+          break
         case 'download':
-          exports.downloadMarkdown(req, res, note);
-          break;
+          exports.downloadMarkdown(req, res, note)
+          break
         case 'info':
-          ActionController.getInfo(req, res, note);
-          break;
+          ActionController.getInfo(req, res, note)
+          break
         case 'gist':
-          ActionController.createGist(req, res, note);
-          break;
+          ActionController.createGist(req, res, note)
+          break
         case 'revision':
-          ActionController.getRevision(req, res, note);
-          break;
+          ActionController.getRevision(req, res, note)
+          break
         default:
           return res.redirect(config.serverURL + '/' + noteId)
       }
     })
   }
 
-  export function downloadMarkdown(req: Request, res: Response, note: any) {
-    const body = note.content;
-    let filename = Note.decodeTitle(note.title);
-    filename = encodeURIComponent(filename);
+  export function downloadMarkdown (req: Request, res: Response, note: any) {
+    const body = note.content
+    let filename = Note.decodeTitle(note.title)
+    filename = encodeURIComponent(filename)
     res.set({
       'Access-Control-Allow-Origin': '*', // allow CORS as API
       'Access-Control-Allow-Headers': 'Range',
@@ -135,7 +134,7 @@ export module NoteController {
       'Cache-Control': 'private',
       'Content-disposition': 'attachment; filename=' + filename + '.md',
       'X-Robots-Tag': 'noindex, nofollow' // prevent crawling
-    });
+    })
     res.send(body)
   }
 }