Little H title

this is subtitle


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 公益404

JSON_Web_Token实现URL认证访问

发表于 2018-03-07 | 分类于 newbie项目

JSON_Web_Token实现URL认证访问

koa的一些middleware

发表于 2018-03-07 | 分类于 newbie项目

koa的一些常用的middleware

直接去github中的koa的wiki中搜

Frameworks

Frameworks, boilerplates and other starter kits using Koa.

Middleware

Known middleware for Koa, you may want to search npm with “koa” to find more.

Security

Body Parsing

Parameter Validation

Rate Limiting

Vhost

Routing and Mounting

Documentation

File Serving

koa-static

静态文件服务中间件,是koa-send的包装

安装

1
npm install koa-static

API

1
2
3
4
5
API
const Koa = require('koa');
const app = new Koa();
//有点不同哦,还是看下面例子好了
app.use(require('koa-static')(root, opts));
  • root 根目录 String
  • opts options object.

Options

  • maxage 浏览cache的最大时间ms 默认 0
  • hidden 允不允许改变隐藏文件. 默认 false
  • index 默认文件名, 默认 ‘index.html’
  • defer 如果为true, 在 return next()之后, 服务器允许任何一个downstream middleware 首先回应.
  • gzip 当用户支持gzip格式, 并且.gz这种文件存在就行. 默认 true.
  • br 同上 .br 格式存在时 (但要注意这个只用在https中). 默认 true.
  • setHeaders Function to set custom headers on response.
  • extensions 当在URL中没有匹配到扩展名时,那么会试着去从传过来的数组中匹配. 默认 false

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const serve = require('koa-static');
const Koa = require('koa');
const app = new Koa();

// $ GET /package.json
app.use(serve('.'));

// $ GET /hello.txt
app.use(serve('test/fixtures'));

// or use absolute paths
app.use(serve(__dirname + '/test/fixtures'));

app.listen(3000);

console.log('listening on port 3000');

SPDY

HTTP2

JSON and JSONP Responses

Compression

Caching

Authentication

Sessions

Templating

Services

CSS Preprocessor

Livereload

Error reporting

koa-onerror

就是一个抓错误的处理器 for koa, hack ctx.onerror.
就是handle all errors, steams’ and events’ errors

比koa-error使用简单,且抓的错误多

安装

1
npm install koa-onerror

使用

1
2
3
4
5
6
7
8
9
10
11
12
const fs = require('fs');
const koa = require('koa');
const onerror = require('koa-onerror');

const app = new koa();
//这里就是使用咯
onerror(app);

app.use(ctx => {
// foo();
ctx.body = fs.createReadStream('not exist');
});

Options

1
onerror(app, options);
  • all: if options.all exist, ignore negotiation
  • text: text error handler
  • json: json error handler
  • html: html error handler
  • redirect: if accepct html, can redirect to another error page

check out default handler to write your own handler.

Status and Headers

koa-onerror will automatic set err.status as response status code, and err.headers as response headers.

Logging

koa-logger

Development style logger middleware for koa.

注意: koa-logger@2 支持 koa@2; 如果你想在 koa@1中使用, 请使用 koa-logger@1.

1
2
3
4
5
6
7
8
<-- GET /
--> GET / 200 835ms 746b
<-- GET /
--> GET / 200 960ms 1.9kb
<-- GET /users
--> GET /users 200 357ms 922b
<-- GET /users?page=2
--> GET /users?page=2 200 466ms 4.66kb

安装

1
npm install koa-logger

使用

1
2
3
4
5
const logger = require('koa-logger')
const Koa = require('koa')

const app = new Koa()
app.use(logger())

Notes

Recommended that you .use() this middleware near the top to “wrap” all subsequent middleware.
就是在顺序上放最上面来app.use(logger())

Metrics

Analytics

i18n or L10n

Response Transformation

Utilities

koa-convert

就是将只能在koa1中使用的middleware转换成koa2中能用的,当然也能反之咯.但注意有些不能转换 比如koa-router

安装

1
npm install koa-convert

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Koa = require('koa') // koa v2.x
const convert = require('koa-convert')
const app = new Koa()
//这是正常是用koa2的middleware
app.use(modernMiddleware)
//这是使用koa2之前的版本,加上convert
app.use(convert(legacyMiddleware))
//这是一起用,混合
app.use(convert.compose(legacyMiddleware, modernMiddleware))

function * legacyMiddleware (next) {
// before
yield next
// after
}

function modernMiddleware (ctx, next) {
// before
return next().then(() => {
// after
})
}

关于区分 legacy and modern middleware

就一个意思,通过 fn.constructor.name == 'GeneratorFunction'来判断版本.

API

就3个,实现不管新版本还是旧版本都能使用middleware
一个将老的middleware转成新的,
一个混合老的和新的middleware都转成新的,
一个将新的middleware转成老的

  • convert()
1
modernMiddleware = convert(legacyMiddleware)
  • convert.compose()
1
2
3
composedModernMiddleware = convert.compose(legacyMiddleware, modernMiddleware)
// or
composedModernMiddleware = convert.compose([legacyMiddleware, modernMiddleware])
  • convert.back()
1
legacyMiddleware = convert.back(modernMiddleware)

strip-ansi是将转义码转换为原码

发表于 2018-03-07 | 分类于 newbie项目

strip-ansi就是将转义后的符号复原

Install

1
npm install strip-ansi

Usage

1
2
3
4
const stripAnsi = require('strip-ansi');

stripAnsi('\u001B[4mUnicorn\u001B[0m');
//=> 'Unicorn'

Related

  • strip-ansi-cli - CLI for this module
  • has-ansi - Check if a string has ANSI escape codes
  • ansi-regex - Regular expression for matching ANSI escape codes
  • chalk - Terminal string styling done right

require-dir增强require的使用

发表于 2018-03-07 | 分类于 newbie项目

require-dir Helper to require() diretories

本来require()只能读一个文件,现在用了这个后就能读取一个目录,当做一个对象就可以使用了

例子

一个目录结构

1
2
3
4
5
dir
+ a.js
+ b.json
+ c.coffee
+ d.txt

在使用requireDir('./dir') 后将会返回:看不懂这个requireDir见下面使用

1
2
3
4
//也可以看到这个只是名字,而不是扩展名也有,所以有options duplicate
{ a: require('./dir/a.js')
, b: require('./dir/b.json')
}

安装

1
2
//注意这个package不是requireDir
npm install require-dir

使用

基本使用

1
2
var requireDir = require('require-dir')
var dir = requireDir('./path/to/dir')

自定义使用,增加参数options

1
var dir = requireDir('./path/to/dir', {recurse: true});

Options

  • recurse: 是否在子文件夹中递归 require() . (node_modules 中的会被忽略.) 默认 false.
  • duplicates: 默认预设的,如果多个文件有相同的名字(注意这个只看名字,不看扩展名),只有最高优先权的 require()‘d 会返回. (优先权通过require.extensions keys的顺序决定,如果 recurse is true那么文件夹的优先权大于文件.) Specifying this option require()‘s all files and returns full filename keys in addition to basename keys. 默认 false.

例如.在上面那个例子中, 如果多了一个叫 a.json的, 那么结果还是一样, 但如果改了 duplicates: true 结果如下:

1
2
3
4
5
6
{ a: require('./dir/a.js')
, 'a.js': require('./dir/a.js')
, 'a.json': require('./dir/a.json') //多了这个
, b: require('./dir/b.json')
, 'b.json': require('./dir/b.json')
}
  • filter: 就是过滤器,在使用require前过滤夏文件名. 例如在生成环境中忽略dev开头的文件:
1
2
3
4
5
requireDir('./dir', {
filter: function (fullPath) {
return process.env.NODE_ENV !== 'production' && !fullPath.match(/$dev/);
}
})
  • mapKey: 在require-ing后对 module base name进行转换. 例如将 any module names 都大写:
1
2
3
4
5
requireDir('./dir', {
mapKey: function (value, baseName) {
return baseName.toUpperCase();
}
})
  • mapValue: 这个是对value. For example, uppercasing any text exported:
1
2
3
4
5
requireDir('./dir', {
mapValue: function (value, baseName) {
return typeof value === 'string' ? value.toUpperCase() : value;
}
})

Tips

如果你想在多个文件中使用同一个文件夹下的 require() , 你就单独建一个 index.js 文件 然后如下:

1
module.exports = require('require-dir')();   // defaults to '.'

And don’t worry, the calling file is always ignored to prevent infinite loops.

lru_cache最近最少使用缓存处理

发表于 2018-03-07 | 分类于 newbie项目

LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”。

LRU缓存的处理方式如其命名,在固定的缓存空间下,把最近最少使用的数据移除,让给最新读取的数据。算法假设最常读取的数据一般也是访问次数最多的,尽力保留这部分数据可以提高cache的命中。

lru-cache

例子

在保持几个从MongoDB中取出来的数据

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var LRU = require("lru-cache")
//默认接受max,下面的参数都是可选的
otherCache = LRU(50) // sets just the max size

options = {
max: 500,
length: function (n, key) {
return n * 2 + key.length
},
dispose: function (key, n) {
n.close()
},
maxAge: 1000 * 60 * 60
}
cache = LRU(options)

cache.set("key", "value")
cache.get("key") // "value"

// non-string keys ARE fully supported
var someObject = {}
cache.set(someObject, 'a value')
cache.set('[object Object]', 'a different value')
assert.equal(cache.get(someObject), 'a value')

cache.reset() // empty the cache

当然要注意数据不能放太多,不然溢出

Options

  • max cache的最大长度,使用length函数来对所有值检查合法性.必须设置,不然默认无穷大.
  • maxAge 以ms为单位的最大逗留时间.
  • length 这是一个Function用来计算 the length of stored items.

    你在存储 strings or buffers时, 你可能想要做如下 function(n, key){return n.length}. The default is function(){return 1}, 表示你存储大小规模是 max 那设置就没事. The item is passed as the first argument, and the key is passed as the second argumnet.

  • dispose 这个Function 是用来将items从cache中drop的. 当你关闭文件或做其他清除cache工作时,不需要用到这些items时可以使用. Called with key, value. 实际上是先call再把这个item是从内部cache中remove,如果你想立即put it back in, you’ll have to do that in a nextTick or setTimeout callback or it won’t do anything.
  • stale By default, if you set a maxAge, 只有当你使用get(key) 他才会真正把 stale items 拉出cache . (也就是说在做setTimeout or anything前并不能做其他事.)
    1. 如果你设置stale:true, 在你删除这个stale value前,他会返回给你.
    2. 如果你没有设置这个值, 那么当你试图get a stale entry, 他会返回undefined , 因为他已经被删除了
  • noDisposeOnSet By default, 如果你设置了 dispose() 方法,当你使用 set() 操作来重写一个已经存在的key时,他会被调用 If you set this option, dispose() will only be called when a key falls out of the cache, not when it is overwritten.

API

  • set(key, value, maxAge)

  • get(key) => value

Both of these will update the “recently used”-ness of the key. They do what you think. maxAge is optional and overrides the cache maxAge option if provided.

If the key is not found, get() will return undefined.

The key and val can be any value.

  • peek(key)

Returns the key value (or undefined if not found) without updating the “recently used”-ness of the key.

(If you find yourself using this a lot, you might be using the wrong sort of data structure, but there are some use cases where it’s handy.)

  • del(key)

Deletes a key out of the cache.

  • reset()

Clear the cache entirely, throwing away all values.

  • has(key)

Check if a key is in the cache, without updating the recent-ness or deleting it for being stale.

  • forEach(function(value,key,cache), [thisp])

Just like Array.prototype.forEach. Iterates over all the keys in the cache, in order of recent-ness. (Ie, more recently used items are iterated over first.)

  • rforEach(function(value,key,cache), [thisp])

The same as cache.forEach(...) but items are iterated over in reverse order. (ie, less recently used items are iterated over first.)

  • keys()

Return an array of the keys in the cache.

  • values()

Return an array of the values in the cache.

  • length

Return total length of objects in cache taking into account length options function.

  • itemCount

Return total quantity of objects currently in cache. Note, that stale (see options) items are returned as part of this item count.

  • dump()

Return an array of the cache entries ready for serialization and usage with ‘destinationCache.load(arr)`.

  • load(cacheEntriesArray)

Loads another cache entries array, obtained with sourceCache.dump(), into the cache. The destination cache is reset before loading new entries

  • prune()

Manually iterates over the entire cache proactively pruning old entries

mongoose操作MongoDB数据库的模块

发表于 2018-03-07 | 分类于 newbie项目

mongoose让你用js的方式来操纵mongodb数据库

入门

官网Quick Start

首先理下思路

  1. 有个数据库叫mongodb
  2. nodejs中有个模块叫mongoose
  3. nodejs不通过shell命令行而是通过使用mongoose的API来控制mongodb

quick start

安装mongoose

1
npm install mongoose

例子

例子就是我们想在mongodb中创建一个叫test的数据库,然后再数据库中增加一个collection,这个collection中存入fuzzy kittens

这其实就对应着3块,Schemas,Models,Documents

使用开始

要在nodejs中使用mongoose,先得连接mongodb数据库.指的是在shell中

1
mongod --dbpath d:/db

不懂得话先看mongodb教程熟悉一下.然后

1
2
3
// getting-started.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');

当然这个test同mongodb那样,要存入数据口才能show dbs看到

接下来看看有没有连接成功

1
2
3
4
5
6
7
8
9
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useMongoClient: true });

var db = mongoose.connection;
//这里就是说连接成功的话会打印出coneect success,失败的话会打印出失败的信息
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('connect success')
});

然后启动

1
node app.js

接着连接成功,那么如何往MongoDB中存入数据呢,这个看例子,注意理清Schema,Model,Documents关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Schema,相当于规定好数据的属性
var kittySchema = mongoose.Schema({
name: String
});

//这边还可以插入方法,但只能放这里哦

//Model 依照上面那个大纲,实例化一个collection,Kitten在mongodb中会加上s
var Kitten = mongoose.model('Kitten', kittySchema);

//Documents,这里就是填入具体数据了
var silence = new Kitten({ name: 'Silence' });

//将数据保存到数据库里面去,没有这一步,数据库是不会被建立的,下面有详细展开这个save参数
silence.save();

接着上面,除了规定属性外,当然还有方法咯(注意顺序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//给猫加个猫猫叫
// NOTE: methods must be added to the schema before compiling it with mongoose.model()
kittySchema.methods.speak = function () {
var greeting = this.name
? "Meow name is " + this.name
: "I don't have a name";
console.log(greeting);
}

//这是和上面一样的model
var Kitten = mongoose.model('Kitten', kittySchema);
//这也是上面一样的,注意方法调用也很方便
var fluffy = new Kitten({ name: 'fluffy' });
fluffy.speak(); // "Meow name is fluffy"

接下来就是保存到MongoDB数据库中了

1
2
3
4
5
//将Documents存入MongoDB中去,第一个参数是error的callback
fluffy.save(function (err, fluffy) {
if (err) return console.error(err);
fluffy.speak();
});

当然存入后还能查找所有kittens中的(find咯),和save一样的格式

1
2
3
4
Kitten.find(function (err, kittens) {
if (err) return console.error(err);
console.log(kittens);
})

过滤下查找结果,条件查找,查找所有name叫fluff的,然后通过callback返回一组array

1
Kitten.find({ name: /^fluff/ }, callback);

配置

moment一款管理date格式的轻量级js库

发表于 2018-03-07 | 分类于 newbie项目

Moment.js是一款解析,验证,控制和格式化时间的轻量级javascript库

可以使用在browser和Node.js中

安装

Node.js

1
2
3
4
npm install moment

var moment = require('moment');
moment().format();

Browser

1
2
3
4
5
6
//就是使用CDN  在cdnjs.com或jsDelivr上都有
<script src="moment.js"></script>

<script>
moment().format();
</script>

官方推荐用Require.js(但我不会)

先通过bower或node_modules安装依赖,然后通过packages config

Browserify

1
2
3
4
npm install moment

var moment = require('moment');
moment().format();

Note: There is a bug that prevents moment.locale from being loaded.

1
2
3
var moment = require('moment');
moment.locale('cs');
console.log(moment.locale()); // en

Use the workaround below

1
2
3
var moment = require('moment');
require('moment/locale/cs');
console.log(moment.locale()); // cs

In order to include all the locales

1
2
3
4
var moment = require('moment');
require("moment/min/locales.min");
moment.locale('cs');
console.log(moment.locale()); // cs

Typescript 2.13.0+

这个要moment版本大于2.13.0才能用

1
2
3
4
5
6
//install via NPM
npm install moment
//Import and use in your Typescript file
import * as moment from 'moment';

let now = moment().format('LLLL');

Note: If you have trouble importing moment, try adding "allowSyntheticDefaultImports": true in compilerOptions in yourtsconfig.json file and then use the syntax

1
import moment from 'moment';

Locale Import(就是设置时区)

To use moment.locale you first need to import the language you are targeting.

1
2
3
4
5
6
7
8
9
import * as moment from 'moment';
//就是这个
import 'moment/locale/pt-br';

console.log(moment.locale()); // en
moment.locale('fr');
console.log(moment.locale()); // en
moment.locale('pt-BR');
console.log(moment.locale()); // pt-BR

解析

为了修改原生的 Date.prototype, Moment.js 创建了一个 wrapper for the Date object. 获取这个wrapper object, 只需要简单的调用 moment() 输入支持的类型即可.

The Moment prototype is exposed through moment.fn.如果你想增加你自定义的函数,可以通过这个

为了简单使用,所有在 Moment.prototype中的方法 都会指到 moment#method. So Moment.prototype.format == moment.fn.format == moment#format.

Now

1
2
3
4
moment();
// From 2.14.0 onward, also supported
moment([]);
moment({});

获得当前时间只需要调用 moment() 不需要参数.

1
var now = moment();

本质上就是和调用 moment(new Date())一样.

Note: From version 2.14.0, moment([]) and moment({}) also return now. They used to default to start-of-today before 2.14.0, but that was arbitrary so it was changed.

String

要用到时查下

md5使用MD5来hash

发表于 2018-03-07 | 分类于 newbie项目

使用MD5来哈希消息的一个js函数

版本

version 2.0.0 前有2个package谁叫md5 on npm,一个小写,一个大写(你看到的这个就是). version 2.0.0之后,所有的版本就都是小写的md5 on npm. 如果你想在versions >= 2.0.0正确使用这个module,那么你就得改一下 require(‘MD5’) 为 require(‘md5’) .

淘宝地址md5

安装

1
npm install md5

API

1
md5(message)
  • message: String or Buffer
  • 返回 String

使用

1
2
var md5 = require('md5');
console.log(md5('message'));

结果

1
78e731027d8fd50ed642340b7c9a63b3

如果支持buffer

1
2
3
4
5
6
var fs = require('fs'); //这个fs不是通过npm安装,而是node自带的
var md5 = require('md5');

fs.readFile('example.txt', function(err, buf) {
console.log(md5(buf));
});

simplemde一款markdown编辑器

发表于 2018-03-06 | 分类于 newbie项目

SimpleMDE is a simple, embeddable, and beautiful JS markdown editor

simplemde marked highlight.js区别
第一个是编辑器,第二个是解析器,第三个是语法高亮

安装

通过npm

1
npm install simplemde --sava

通过 jsDelivr.但这个更新会有延迟

1
2
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>

快速开始

1
2
3
4
5
6
7
8
9
10
11
12
13
//这个会自动加载到页面上第一个textarea上,不建议这么做
<script>
var simplemde = new SimpleMDE();
</script>

// 应该用一个特殊的加了id的
<textarea id="MyID"> </textarea>

<script>
var simplemde = new SimpleMDE({
element: document.getElementById("MyID")
});
</script>

获取/设置内容

1
2
3
4
5
//get
simplemde.value();
//set
simplemde.value("This text will appear in the editor");
//这里当然是用来解析markdown后显示html,有个markdown函数,我们不用,用marked

配置参数

  • autoDownloadFontAwesome: 默认是undefined,可选true/false 是否自动下载字体,图标.建议false,因为速度会变慢.我们npm下载就好了
  • autofocus: 默认false, true/false, 自动聚焦到编辑器.
  • autosave: 自动保存
    • enabled: 默认false
    • delay: 默认延迟 10000 (10s). 延迟10s自动保存
    • uniqueId: 设置自动保存就一定要设置一个id
  • blockStyles: 自定义bold code italic怎么标记
    • bold ** or __. Defaults to **.
    • code ``` or ~~~. Defaults to ```.
    • italic * or _. Defaults to *.
  • element: DOM元素挂载点 默认就是页面中第一个textarea标签.建议修改掉,用id=””指定
  • forceSync: 前置同步. 默认false.
  • hideIcons: 要隐藏图标的一个数组
  • indentWithTabs: 缩进用tab 默认 true. 否则就是space
  • initialValue: 自定义一个初始值,不是placeholder
  • insertTexts: 自定义插入文本的行为,是一个有2个元素的数组. 第1个元素时鼠标或高亮前插入,第2个之后插入, For example, this is the default link value: [““, ““].
    • horizontalRule
    • image
    • link
    • table
  • lineWrapping: 自动换行. 默认 true.
  • parsingConfig: 在编辑的时候对解析markdown的设置进行调整(不是预先写入)
    • allowAtxHeaderWithoutSpace: 如果是true就在对标题渲染的时候在#后面不会带一个空格. 默认 false.
    • strikethrough: false的话不处理 GFM strikethrough 语法. 默认 true.
    • underscoresBreakWords: true的话下划线当做分隔符,默认 false
  • placeholder: 自定义placeholder显示
  • previewRender: 自定义解析markdown到html的函数. 当用户预览的时候会加载
  • promptURLs: true的话, 会有2个js弹窗出现要求link或img的url.默认false.
  • renderingConfig: 在预览的时候解析markdown的设置进行调整.(不是在编辑时)

    • singleLineBreaks: false的话, 不会解析GFM single line breaks. 默认 true.
    • codeSyntaxHighlighting: true的话 将会对使用 highlight.js的进行高亮. 默认 false. 使用这个功能的话你必须在你的页面上加载 highlight.js . For example, include the script and the CSS files like:
      1
      2
      <script src="https://cdn.jsdelivr.net/highlight.js/latest/highlight.min.js"></script>
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/latest/styles/github.min.css">
  • shortcuts: 快捷键 默认有一张表.

  • showIcons: 一组显示图标名字
  • spellChecker: 拼写检查. 默认true.
  • status: 默认 true 显示状态栏
    • 当然这个也可以你定义
  • styleSelectedText: false的话, 从选择的行中移除CodeMirror-selectedtext class . 默认 true.
  • tabSize: 自定义tab大小. 默认 2.
  • toolbar: false的话, 隐藏工具栏. 默认是展示
  • toolbarTips: false的话, 关闭工具栏按钮提示. 默认true.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Most options demonstrate the non-default behavior
var simplemde = new SimpleMDE({
autofocus: true,
autosave: {
enabled: true,
uniqueId: "MyUniqueID",
delay: 1000,
},
blockStyles: {
bold: "__",
italic: "_"
},
element: document.getElementById("MyID"),
forceSync: true,
hideIcons: ["guide", "heading"],
indentWithTabs: false,
initialValue: "Hello world!",
insertTexts: {
horizontalRule: ["", "\n\n-----\n\n"],
image: ["![](http://", ")"],
link: ["[", "](http://)"],
table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n"],
},
lineWrapping: false,
parsingConfig: {
allowAtxHeaderWithoutSpace: true,
strikethrough: false,
underscoresBreakWords: true,
},
placeholder: "Type here...",
previewRender: function(plainText) {
return customMarkdownParser(plainText); // Returns HTML from a custom parser
},
previewRender: function(plainText, preview) { // Async method
setTimeout(function(){
preview.innerHTML = customMarkdownParser(plainText);
}, 250);

return "Loading...";
},
promptURLs: true,
renderingConfig: {
singleLineBreaks: false,
codeSyntaxHighlighting: true,
},
shortcuts: {
drawTable: "Cmd-Alt-T"
},
showIcons: ["code", "table"],
spellChecker: false,
status: false,
status: ["autosave", "lines", "words", "cursor"], // Optional usage
status: ["autosave", "lines", "words", "cursor", {
className: "keystrokes",
defaultValue: function(el) {
this.keystrokes = 0;
el.innerHTML = "0 Keystrokes";
},
onUpdate: function(el) {
el.innerHTML = ++this.keystrokes + " Keystrokes";
}
}], // Another optional usage, with a custom status bar item that counts keystrokes
styleSelectedText: false,
tabSize: 4,
toolbar: false,
toolbarTips: false,
});

高度(2种都可以,在html中或css中)

To change the minimum height (before it starts auto-growing):

1
2
3
4
5
6
7
8
.CodeMirror, .CodeMirror-scroll {
min-height: 200px;
}
Or, you can keep the height static:

.CodeMirror {
height: 300px;
}

事件绑定

You can catch the following list of events:

1
2
3
4
var simplemde = new SimpleMDE();
simplemde.codemirror.on("change", function(){
console.log(simplemde.value());
});

从textarea中移除simplemde

通过调用 toTextArea 方法. 注意这个也会清除自动保存,就是textarea内容重置了.

1
2
3
4
var simplemde = new SimpleMDE();
...
simplemde.toTextArea();
simplemde = null;

一些常用方法

1
2
3
4
5
var simplemde = new SimpleMDE();
simplemde.isPreviewActive(); // returns boolean
simplemde.isSideBySideActive(); // returns boolean
simplemde.isFullscreenActive(); // returns boolean
simplemde.clearAutosavedValue(); // no returned value

How it works

SimpleMDE began as an improvement of lepture’s Editor project, but has now taken on an identity of its own. It is bundled with CodeMirror and depends on Font Awesome.

CodeMirror is the backbone of the project and parses much of the Markdown syntax as it’s being written. This allows us to add styles to the Markdown that’s being written. Additionally, a toolbar and status bar have been added to the top and bottom, respectively. Previews are rendered by Marked using GFM.

marked一个简易markdown功能实现模块

发表于 2018-03-06 | 分类于 newbie项目

marked模块-简易markdown功能实现

Markdown不是HTML,目前还不能被浏览器解析,所以我们需要Markdown的解析器(不是编辑器,编辑器另选simplemde),把Markdown翻译成浏览器认识的HTML文档展示出来。Marked就是一个基于Nodejs的Markdown解析引擎!

markdown.js简易手册

安装

使用

1
2
3
npm isntall marked --sava

或者用cdn

使用

使用就很简单了,直接用div或者textarea都行,id指明后用innerHTML插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Marked in the browser</title>
<script src="/path/to/marked.min.js"></script>
</head>
<body>
<div id="content"></div>
<script>
document.getElementById('content').innerHTML =
marked('# Marked in browser\n\nRendered by **marked**.');
</script>
</body>
</html>

详细说明marked()方法

1
marked(markdownString [,options] [,callback])

markdownString是你渲染的内容,必须是字符串。
options是你渲染的设置——它是一个对象。当然,你用marked.setOptions也是不错的。
callback是回调函数。如果 options 参数没有定义,它就是第二个参数。

关于Options(详细解说,毕竟配合highlight.js一起用)

1
2
3
4
5
6
7
8
9
10
11
var rendererMD = new marked.Renderer();
marked.setOptions({
renderer: rendererMD,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false
});//基本设置

当然首先highlight.js要引入

1
2
3
<link href="http://cdn.bootcss.com/highlight.js/8.0/styles/monokai_sublime.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/highlight.js/8.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

因为highlight.js不能渲染接口返回的代码,所以需要node中的marked配合options

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var rendererMD = new marked.Renderer();
marked.setOptions({
renderer: rendererMD, //当然可以renderer: new marked.Renderer()
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false
});
//要显示的markdown内容
var markdownString = '```js\n console.log("hello"); \n```';
//这是设置highlight.js的,当然也可以拿到前面的setOptions中
marked.setOptions({
highlight: function (code) { //这个code后还有2个参数lang,callback
return hljs.highlightAuto(code).value;
}
});
//这是在HTML中使用
document.getElementById('content').innerHTML = marked(markdownString);

所以以上有两点参数说明

highlight中 高亮的参数

完整的highlight方法包含三个参数:code,lang和callback

code——代码内容——是一个字符串。
lang——编程语言的种类——也是字符串。

这个需要在highlight.registerLanguage中设置

callback就是回调函数。

renderer(渲染)

render存放的是一个对象,不声明时默认为new Renderer()。

自定义渲染方式(这个略过吧)
渲染选项允许你以自定义的方式渲染内容,并把之前的规则设置覆盖掉。——这是比较底层的方法了。

比如,我想渲染# heading+,但是默认的规则是:<h1></h1>,我想改为更为复杂的结构——

1
2
3
4
5
6
7
8
9
10
11
12
13
var rendererMD = new marked.Renderer();
rendererMD.heading = function (text, level) {
var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
return '<h' + level + '><a name="' +
escapedText +
'" class="anchor" href="#' +
escapedText +
'"><span class="header-link"></span></a>' +
text + '</h' + level + '>';
}
//显示
console.log(marked('# heading+', { renderer: rendererMD }));
document.getElementById('content').innerHTML = marked('# heading+', { renderer: rendererMD });

渲染结果

1
2
3
4
5
6
<h1>
<a name="heading-" class="anchor" href="#heading-">
<span class="header-link"></span>
</a>
heading+
</h1>

以上就用了heading的渲染。

块级支持以下渲染

  • code(string code, string language)
  • blockquote(string quote)
  • html(string html)
  • heading(string text, number level)
  • hr()
  • list(string body, boolean ordered)
  • listitem(string text)
  • paragraph(string text)
  • table(string header, string body)
  • tablerow(string content)
  • tablecell(string content, object flags)

flags 拥有以下属性:

1
2
3
4
{
header: true || false,
align: 'center' || 'left' || 'right'
}

行级支持以下渲染:

  • strong(string text)
  • em(string text)
  • codespan(string code)
  • br()
  • del(string text)
  • link(string href, string title, string text)
  • image(string href, string title, string text)

其它渲染参数(都是boolean)

gfm
它是一个布尔值,默认为true。
允许 GitHub标准的markdown.

tables
它是一个布尔值,默认为true。
支持支持github表格语法。该选项要求 gfm 为true。

breaks
它是一个布尔值,默认为false。
支持github回车换行。该选项要求 gfm 为true。

pedantic
它是一个布尔值,默认为false。
尽可能地兼容 markdown.pl的晦涩部分。不纠正原始模型任何的不良行为和错误。

sanitize
它是一个布尔值,默认为false。
对输出进行过滤(清理),将忽略任何已经输入的html代码(标签)

smartLists
它是一个布尔值,默认为false。
使用比原生markdown更时髦的列表。 旧的列表将可能被作为pedantic的处理内容过滤掉.

smartypants
它是一个布尔值,默认为false。
使用更为时髦的标点,比如在引用语法中加入破折号。

使用lexer和parser

如果你想,还可以使用词法分析器。通过它可以追加规则:

1
2
3
4
5
6
7
var tokens = marked.lexer('text');//把text解析为一个marked.js的内部对象
console.log(marked.parser(tokens));//又把这个对象转化为html字符串。(<p>text</p>)

var lexer = new marked.Lexer({sanitize: true});//放option信息
var tokens = lexer.lex('<h1>hello</h1>');//<p>&lt;h1&gt;hello&lt;/h1&gt;</p>
console.log(marked.parser(tokens));
console.log(lexer.rules);//打出正则信息
1…101112…14
Henry x

Henry x

this is description

133 日志
25 分类
135 标签
GitHub E-Mail
Links
  • weibo
© 2019 Henry x