background

It is common for individual developers to have their own personal blog site. Common frameworks, whether Hexo, Gitbook, or Docsify, do not support article views or site views. They require plugins that are currently on the market based on Busuanzi and LeanCloud. And MemFireDB Cloud aims to provide database services. If the SDK function is provided later, plug-ins corresponding to the framework can be realized for individual developers to use, and relevant articles can be provided, which can also attract many individual developers. (Because I also register an account on LeanCloud based on the need of using plug-ins.)

An overview of the

Based on the above background, try to implement a plug-in based on Memfire to count the number of visits to Gitbook articles

implementation

To build libraries built table

Login MemFireDB Cloud

Need to be inMemFireDB CloudRegister your account and create your own database

Go to the online editor

Click SQL Query to enter the online editor

Build table

CREATE TABLE counter (
  id serial NOT NULL,
  url varchar(500),
  time int,
  title varchar(200),
        PRIMARY KEY (id)
)
Copy the code

Database connection

Because MemFireDB Cloud does not provide SDK and other functions at present, so I first write a simple intermediate service to facilitate plug-in access.

package main import ( "database/sql" "fmt" "log" "net/http" "github.com/gin-gonic/gin" _ "github.com/lib/pq" ) const ( host = "<db ip>" port = <db port> user = "<your db user>" password = "<your db password>" dbname = "<your db name>" ) Func main() {r := gin.Default() r.us (Cors()) // Enable middleware to allow cross-domain requests r.git ("/counter", R.post ("/counter", AddCount) R.run () // Listen and start the service at 0.0.0.0:8080} func Cors() gin.HandlerFunc {return func(c *gin.Context) { Method := c.equest.method origin := c.equest.header. Get(" origin ") // request Header if origin! = "" { c.Writer.Header().Set("Access-Control-Allow-Origin", origin) c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session") c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") c.Header("Access-Control-Max-Age", "172800") c.Header("Access-Control-Allow-Credentials", } if method == "OPTIONS" {c.son (http.statusok, "ok!" ) } defer func() { if err := recover(); err ! = nil { log.Printf("Panic info is: %v", err) } }() c.Next() } } func GetCount(c *gin.Context) { url := c.Query("url") if url == "" { url = "#" } psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) db, err := sql.Open("postgres", psqlInfo) if err ! = nil { log.Fatal(err) } rows, err := db.Query("SELECT time FROM counter WHERE url = $1", url) if err ! = nil { log.Fatal(err) } defer rows.Close() var time int for rows.Next() { err := rows.Scan(&time) if err ! = nil { log.Fatal(err) } fmt.Printf("Row[%d]\n", time) } err = rows.Err() if err ! = nil { log.Fatal(err) } defer db.Close() c.JSON(200, gin.H{ "time":time, }) return } func AddCount(c *gin.Context) { url := c.PostForm("url") if url == "" { url = "#" } psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) db, err := sql.Open("postgres", psqlInfo) if err ! = nil { log.Fatal(err) } insert := "INSERT INTO counter(url, time) VALUES (" insert += "'" + url + "', 1)" fmt.Println("insert statement: ", insert) if _, err := db.Exec(insert); err ! = nil { log.Fatal(err) } fmt.Printf("Inserted data: %s\n", insert) defer db.Close() return } func UpdateCount(c *gin.Context) { url := c.PostForm("url") if url == "" { url = "#" }  time := c.PostForm("time") psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable",  host, port, user, password, dbname) db, err := sql.Open("postgres", psqlInfo) if err ! = nil { log.Fatal(err) } update := "UPDATE counter SET time=" + time + " Where url= '" + url + "'" if _, err := db.Exec(update); err ! = nil { log.Fatal(err) } fmt.Printf("update data: %s\n", update) defer db.Close() return }Copy the code

Build the Gitbook plug-in

Copy other plug-ins and build code repositories

Modify plugin.js under book

var gitbook = window.gitbook; / * <! -- Start of CuterCounter Code --> <a href="http://www.cutercounter.com/" target="_blank"><img src="http://www.cutercounter.com/hit.php?id=gmvufxqck&nd=1&style=116" border="0" alt="visitor counter"></a> <! -- End of CuterCounter Code --> */ var iconSVg = '<svg t="1543310294340" \ class="icon" style="" viewBox="0 0 1024 1024" Version = "1.1" \ XMLNS = "http://www.w3.org/2000/svg" p - id = "1104" XMLNS: xlink = "http://www.w3.org/1999/xlink" width = "14" height="14"><defs><style type="text/css"></style></defs>\ <path d="M512 416a96 96 0 1 0 0 192 96 96 0 0 0 0-192z M511.952 102.064c-0.016-0.448-0.064-0.864-0.096-1.296a8.16 8.16 0 0 m511.952 102.064c-0.016-0.448-0.064-0.864-0.096-1.296a8.16 8.16 0 0 0-0.08-0.656 c0-0.32-0.064-0.624-0.128-0.928-0.032-0.368-0.064-0.736-0.128-1.088-0.032-0.048-0.032-0.096-0.032-0.144 a39.4 88 39.488 0 0 0-10.704-21.536 - c - 32.672-39.616-71.536-74.88-111.04-107.072-85.088-69.392-182.432-127.424-289.856-150.8-62.112-13.504-124 576-14.064-187.008-2.64-56.784 10.384-111.504 32-162.72 58.784-80.176 41.92-153.392 99.696-217.184 164.48-11.808 11.984-23.552 24.224-34.288 37.248-14.288 17.328-14.288 37.872 0 55.216 32.672 39.616 71.52 74.848 111.04 107.056 85.12 69.392 182.448 127.408 289.888 150.784 62.096 13.504 124.608 14.096 187.008 2.656 56.768-10.4 111.488-32 162.736-58.768 80.176-41.936 153.376-99.696 217.184-164.48 11.792-12 23.536-24.224 34.288-37.248 5.712-5.872 9.456-13.44 10.704-21.568l0.032-0.128a12.592 12.592 0 0 0 0.128-1.088c0.064-0.304 0.096-0.624 0.128-0.928l0.08-0.656 ZM512 704c-106.032 0-192-85.952-192s85.952-192 192-192 zM512 704c-106.032 0-192-85.952-192s85 192 "\ fill="#CCC" p-id="1105"></path></ SVG >' require(["gitbook", "jQuery"], function (gitbook, $) { gitbook.events.bind("page.change", function() { var bookHeader = $('.book-header') var lastChild = bookHeader.children().last() var renderWrapper = $('<div  class="page-view-wrapper dropdown pull-left">\ <span class="btn toggle-dropdown">'+ iconSVg + '</span>\ <span Class = "page - view - counter" title = "reads" > - < / span > \ < / div > ') if (lastChild. Length) {renderWrapper. The insertBefore (lastChild) }else{ bookHeader.append(renderWrapper) } var Counter = function (method, url, data) { return $.ajax({ method: Method, url: ` http://127.0.0.1:8080${url} `, data: data,}); }; var url = location.href.replace(/^http:\/\/[^/]+/, "").trim(); url = decodeURI(url); var s = url.split("/").pop(); var title = s.replace(".html", ""); var time = 0; Counter('get', '/counter', { url: url }).done(function (results ) { console.log(results) if (results.time > 0) { time = results.time+1; Counter('put', `/counter`, {url: url, time: time }).done(function () { console.log(time); renderWrapper.find('.page-view-counter').html(time) }) } else { Counter('post', '/counter', { title: title, url: url, time: 1}).done(function ({ results }) { renderWrapper.find('.page-view-counter').html(1) }) } }); })});Copy the code

Warehouse Address:Github.com/TiannV/gitb…NPM publish publishes to the NPM marketplace

use

Add the plug-in

Add the plugin to the book.json file of your own Gitbook repository

Execute Gitbook Install to download the app market plug-ins into the GitBook project for gitBoolk Build compilation

Run the database connection service

go run mf.go

Start the gitbook

gitbook serve

View the interface:

Success ~

Code warehouse

TiannV/gitbook-plugin-mf-pageview