diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index ec5b910..6a1fe94 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -9,17 +9,17 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} # If your repository depends on submodule, please see: https://github.com/actions/checkout submodules: recursive - - name: Use Node.js 16.x - uses: actions/setup-node@v2 + - name: Use Node.js 20 + uses: actions/setup-node@v4 with: - node-version: '16' + node-version: '20' - name: Cache NPM dependencies - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: node_modules key: ${{ runner.OS }}-npm-cache @@ -30,7 +30,7 @@ jobs: - name: Build run: npm run build - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 with: path: ./public deploy: @@ -45,4 +45,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 \ No newline at end of file + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a8c4cc2 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Writting diff --git a/package.json b/package.json index d54baea..2afa163 100644 --- a/package.json +++ b/package.json @@ -26,4 +26,4 @@ "hexo-theme-landscape": "^1.0.0", "hexo-theme-next": "^v7.8.0" } -} +} \ No newline at end of file diff --git a/source/_posts/2024-06-go-interface.md b/source/_posts/2024-06-go-interface.md new file mode 100644 index 0000000..f36d64d --- /dev/null +++ b/source/_posts/2024-06-go-interface.md @@ -0,0 +1,765 @@ +--- +title: Go Interface 实现 +date: 2024-06-29 +tags: + - Go +permalink: /go-interface/ +--- + +这篇文章主要记录了一些我在学习 Go 语言实现原理过程中的笔记。 + +本人使用的 `go version go1.22.4 darwin/amd64`。 + +## Go interface + +interface 是 Go 语言中很有意思的一个特性,它能让你像纯动态语言一样使用`duck typing`,而且编译器还能像静态语言一样做类型检查。 + +> 如果一个东西叫起来像鸭子,走路也像鸭子,那么它就是鸭子。 + +也就是说,interface 允许你定义一组方法的集合,任何实现了这组方法的类型都可以被看作是这个 interface 的实现。 + +有了 interface,可以做很多有意思的事情。 + +1、可以通过 interface 来抽象,然后再通过组合与继承,让程序足够有表达力。 + +2、如果不用 interface,一个函数就只能接受具体的类型作为参数,而且也只能返回具体的类型作为返回值,这个函数的适用范围就比较局限。有了 interface,就能让这个函数接受和返回更抽象的类型的参数(某个 interface),相当于让这个函数的适用范围更广了。 + +3、interface 让程序可以很方便地实现各种编程模式,提升程序的抽象性和解耦度,让程序更容易维护和扩展。 + +--- + +下面我们主要关注 interface 的底层实现原理,也就是要理解这段代码的原理(直接用 AI 生成几段代码给我们): + +类型断言 + +```go +var i interface{} = 42 +n, ok := i.(int) // n == 42, ok == true +s, ok := i.(string) // s == "", ok == false +``` + +类型转化:把一种类型转化为 + +```go + +// 定义一个接口 +type Speaker interface { + Speak() string +} + +// 定义一个实现了该接口的具体类型 +type Dog struct{} + +var d Dog + +// 具体类型 转 空接口 +var a interface{} = d + +// 空接口 转 特定接口 +var s Speaker +s = a.(Speaker) // 使用类型断言 + +``` + +类型 switch:尝试把某个变量转化为其他类型,是类型断言和类型转化的组合。 + +```go +switch v := i.(type) { +case T1: + // v 是 T1 类型 +case T2: + // v 是 T2 类型 +default: + // v 是其他类型 +} +``` + +动态派发:在运行的时候确定应该调用哪个函数。 + +```go +type Speaker interface { + Speak() string +} + +type Dog struct{} + +func (d Dog) Speak() string { + return "Woof!" +} + +type Cat struct{} + +func (c Cat) Speak() string { + return "Meow!" +} + +func makeSound(s Speaker) { + fmt.Println(s.Speak()) +} + +func main() { + d := Dog{} + c := Cat{} + makeSound(d) // 输出 "Woof!" + makeSound(c) // 输出 "Meow!" +} +``` + +## Go interface 的实现原理 + +interface 在 Go 语言的实现其实就靠一个叫做 `iface` 的数据结构。 + +```go + +type iface struct { + tab *itab + data unsafe.Pointer // 数据指针 +} + +type itab struct { + inter *interfacetype + _type *_type + hash uint32 // copy of _type.hash. Used for type switches. + _ [4]byte + fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter. +} + +``` + +把所有子数据结构也展开,就是如下: + +```go +type iface struct { // `iface` + tab *struct { // `itab` + inter *struct { // `interfacetype` + typ struct { // `_type` + size uintptr + ptrdata uintptr + hash uint32 + tflag tflag + align uint8 + fieldalign uint8 + kind uint8 + alg *typeAlg + gcdata *byte + str nameOff + ptrToThis typeOff + } + pkgpath name + mhdr []struct { // `imethod` + name nameOff + ityp typeOff + } + } + _type *struct { // `_type` + size uintptr + ptrdata uintptr + hash uint32 + tflag tflag + align uint8 + fieldalign uint8 + kind uint8 + alg *typeAlg + gcdata *byte + str nameOff + ptrToThis typeOff + } + hash uint32 + _ [4]byte + fun [1]uintptr + } + data unsafe.Pointer +} +``` + +用图来表示就是这样: + +![](2024-06-go-interface/iface.png) + +理解 `iface` 的运作原理的最好方式就是直接查看其汇编代码。 + +写一段简单的代码: + +```go +package main + +type Speaker interface { + Speak() string +} + +type Dog struct { +} + +//go:noinline +func (*Dog) Speak() string { + return "Dog" +} + +type Cat struct { +} + +//go:noinline +func (*Cat) Speak() string { + return "Cat" +} + +//go:noinline +func JustSpeak(s Speaker) string { + return s.Speak() +} + +//go:noinline +func IsSpeaker(s interface{}) bool { + v, ok := s.(Speaker) + if ok { + v.Speak() + } + return ok +} + +//go:noinline +func Which(s interface{}) string { + switch s.(type) { + case Cat: + return "Cat" + case Dog: + return "Dog" + case Speaker: + return "Speaker" + default: + return "interface{}" + } +} + +//go:noinline +func DogSpeak() { + var s Speaker = &Dog{} + JustSpeak(s) +} + +func main() { +} +``` + +然后直接一个命令把代码编译为 Plan 9 汇编代码: + +`GOOS=linux GOARCH=amd64 go build -gcflags="-S" ./main.go 2> ./main.S` + +先来看 `JustSpeak` 函数的汇编代码: + +``` +main.JustSpeak STEXT size=67 args=0x10 locals=0x10 funcid=0x0 align=0x0 + 0x0000 00000 (/main.go:24) TEXT main.JustSpeak(SB), ABIInternal, $16-16 + 0x0000 00000 (/main.go:24) CMPQ SP, 16(R14) + 0x0004 00004 (/main.go:24) PCDATA $0, $-2 + 0x0004 00004 (/main.go:24) JLS 40 + 0x0006 00006 (/main.go:24) PCDATA $0, $-1 + 0x0006 00006 (/main.go:24) PUSHQ BP + 0x0007 00007 (/main.go:24) MOVQ SP, BP + 0x000a 00010 (/main.go:24) SUBQ $8, SP + 0x000e 00014 (/main.go:24) MOVQ AX, main.s+24(FP) + 0x0013 00019 (/main.go:24) MOVQ BX, main.s+32(FP) + 0x0018 00024 (/main.go:24) FUNCDATA $0, gclocals·IuErl7MOXaHVn7EZYWzfFA==(SB) + 0x0018 00024 (/main.go:24) FUNCDATA $1, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB) + 0x0018 00024 (/main.go:24) FUNCDATA $5, main.JustSpeak.arginfo1(SB) + 0x0018 00024 (/main.go:24) FUNCDATA $6, main.JustSpeak.argliveinfo(SB) + 0x0018 00024 (/main.go:24) PCDATA $3, $1 + 0x0018 00024 (/main.go:25) MOVQ 24(AX), CX + 0x001c 00028 (/main.go:25) MOVQ BX, AX + 0x001f 00031 (/main.go:25) PCDATA $1, $1 + 0x001f 00031 (/main.go:25) NOP + 0x0020 00032 (/main.go:25) CALL CX + 0x0022 00034 (/main.go:25) ADDQ $8, SP + 0x0026 00038 (/main.go:25) POPQ BP + 0x0027 00039 (/main.go:25) RET + 0x0028 00040 (/main.go:25) NOP + 0x0028 00040 (/main.go:24) PCDATA $1, $-1 + 0x0028 00040 (/main.go:24) PCDATA $0, $-2 + 0x0028 00040 (/main.go:24) MOVQ AX, 8(SP) + 0x002d 00045 (/main.go:24) MOVQ BX, 16(SP) + 0x0032 00050 (/main.go:24) CALL runtime.morestack_noctxt(SB) + 0x0037 00055 (/main.go:24) PCDATA $0, $-1 + 0x0037 00055 (/main.go:24) MOVQ 8(SP), AX + 0x003c 00060 (/main.go:24) MOVQ 16(SP), BX + 0x0041 00065 (/main.go:24) JMP 0 + 0x0000 49 3b 66 10 76 22 55 48 89 e5 48 83 ec 08 48 89 I;f.v"UH..H...H. + 0x0010 44 24 18 48 89 5c 24 20 48 8b 48 18 48 89 d8 90 D$.H.\$ H.H.H... + 0x0020 ff d1 48 83 c4 08 5d c3 48 89 44 24 08 48 89 5c ..H...].H.D$.H.\ + 0x0030 24 10 e8 00 00 00 00 48 8b 44 24 08 48 8b 5c 24 $......H.D$.H.\$ + 0x0040 10 eb bd ... + rel 2+0 t=R_USEIFACEMETHOD type:main.Speaker+96 + rel 32+0 t=R_CALLIND +0 + rel 51+4 t=R_CALL runtime.morestack_noctxt+0 +``` + +别被这一大段汇编代码吓到了,其实很好读懂。 + +最关键的是这一行: + +``` + 0x0020 00032 (/main.go:25) CALL CX +``` + +这就是动态调用的实现。 + +在调用这个函数之前,它会先构造一个 iface 来表示传入的 Speaker 类型的变量,然后它会把传入这个的参数的偏移 24 字节作为函数进行调用,实际上就是调用的 Speak() 函数。 + +那么 iface 是如何被构造出来的?继续看这段代码。 + +``` +go:itab.*main.Dog,main.Speaker SRODATA dupok size=32 + 0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 0x0010 29 fe 4c 82 00 00 00 00 00 00 00 00 00 00 00 00 ).L............. + rel 0+8 t=R_ADDR type:main.Speaker+0 + rel 8+8 t=R_ADDR type:*main.Dog+0 + rel 24+8 t=RelocType(-32767) main.(*Dog).Speak+0 +main.DogSpeak STEXT size=50 args=0x0 locals=0x18 funcid=0x0 align=0x0 + 0x0000 00000 (/main.go:56) TEXT main.DogSpeak(SB), ABIInternal, $24-0 + 0x0000 00000 (/main.go:56) CMPQ SP, 16(R14) + 0x0004 00004 (/main.go:56) PCDATA $0, $-2 + 0x0004 00004 (/main.go:56) JLS 43 + 0x0006 00006 (/main.go:56) PCDATA $0, $-1 + 0x0006 00006 (/main.go:56) PUSHQ BP + 0x0007 00007 (/main.go:56) MOVQ SP, BP + 0x000a 00010 (/main.go:56) SUBQ $16, SP + 0x000e 00014 (/main.go:56) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB) + 0x000e 00014 (/main.go:56) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB) + 0x000e 00014 (/main.go:58) LEAQ go:itab.*main.Dog,main.Speaker(SB), AX + 0x0015 00021 (/main.go:58) LEAQ runtime.zerobase(SB), BX + 0x001c 00028 (/main.go:58) PCDATA $1, $0 + 0x001c 00028 (/main.go:58) NOP + 0x0020 00032 (/main.go:58) CALL main.JustSpeak(SB) + 0x0025 00037 (/main.go:59) ADDQ $16, SP + 0x0029 00041 (/main.go:59) POPQ BP + 0x002a 00042 (/main.go:59) RET + 0x002b 00043 (/main.go:59) NOP + 0x002b 00043 (/main.go:56) PCDATA $1, $-1 + 0x002b 00043 (/main.go:56) PCDATA $0, $-2 + 0x002b 00043 (/main.go:56) CALL runtime.morestack_noctxt(SB) + 0x0030 00048 (/main.go:56) PCDATA $0, $-1 + 0x0030 00048 (/main.go:56) JMP 0 + 0x0000 49 3b 66 10 76 25 55 48 89 e5 48 83 ec 10 48 8d I;f.v%UH..H...H. + 0x0010 05 00 00 00 00 48 8d 1d 00 00 00 00 0f 1f 40 00 .....H........@. + 0x0020 e8 00 00 00 00 48 83 c4 10 5d c3 e8 00 00 00 00 .....H...]...... + 0x0030 eb ce .. + rel 2+0 t=R_USEIFACE type:*main.Dog+0 + rel 17+4 t=R_PCREL go:itab.*main.Dog,main.Speaker+0 + rel 24+4 t=R_PCREL runtime.zerobase+0 + rel 33+4 t=R_CALL main.JustSpeak+0 + rel 44+4 t=R_CALL runtime.morestack_noctxt+0 +``` + +还记得上面的 `iface` 数据结构吗? + +```go +type iface struct { + tab *itab + data unsafe.Pointer // 数据指针 +} +``` + +你不用很懂 Plan 9 Assembly 也可以看出来,这段代码的核心就是在把 `iface` 给构造出来并通过指针传递给下一个函数,而构造 `iface` 的核心步骤之一就是把 `go:itab.*main.Dog,main.Speaker` 复制到了 AX 上,而这是一个 rodata 只读数据,我也把它列出来了。 + +`go:itab.*main.Dog,main.Speaker` 看名字我们也知道,实际上就是 Dog 这个 struct 实现的 Speaker 的函数表(当然 itab 里也包含了变量类型和接口类型的相关信息)。 + +因此,我们可以大胆地做两个推测: + +- 所有的 interface 实现都有一个对应的 itab,如果 3 个 struct 分别实现了 5 个 interface,那么就会有 15 个这样的 itab rodata。 +- 每个变量在底层都有一个对应的 iface,iface 包含了该变量所需的类型信息和函数表信息,底层是通过把变量组装为 iface,然后以此作为“介质”进行更高级的类型推断或类型转化的实现的。类型转换无非就是从这个样的 iface 转换为另外一个 iface 而已,类型推断无非就是对 itab 做一些相应的判断。 + +## runtime 代码分析 + +在那个汇编文件里,我们会看到很多 runtime 函数,这些 runtime 函数在类型推断和转化的过程中扮演了关键角色。 + +- runtime.typeAssert +- runtime.interfaceSwitch + +我们直接来看函数的实现: + +当进行 type assert 时,会先把把 abi.TypeAssert 和 \_type 这俩给构造出来,然后把它们的指针放到寄存器里,然后再调用 runtime.typeAssert 函数。 + +```go + +type TypeAssert struct { + Cache *TypeAssertCache + Inter *InterfaceType + CanFail bool +} +type TypeAssertCache struct { + Mask uintptr + Entries [1]TypeAssertCacheEntry +} +type TypeAssertCacheEntry struct { + // type of source value (a *runtime._type) + Typ uintptr + // itab to use for result (a *runtime.itab) + // nil if CanFail is set and conversion would fail. + Itab uintptr +} + +type InterfaceType struct { + Type + PkgPath Name // import path + Methods []Imethod // sorted by hash +} + +type _type = abi.Type // 就是上面的 Type 类型 + +// typeAssert builds an itab for the concrete type t and the +// interface type s.Inter. If the conversion is not possible it +// panics if s.CanFail is false and returns nil if s.CanFail is true. +func typeAssert(s *abi.TypeAssert, t *_type) *itab { + var tab *itab + if t == nil { + if !s.CanFail { + panic(&TypeAssertionError{nil, nil, &s.Inter.Type, ""}) + } + } else { + tab = getitab(s.Inter, t, s.CanFail) + } + + if !abi.UseInterfaceSwitchCache(GOARCH) { + return tab + } + + // Maybe update the cache, so the next time the generated code + // doesn't need to call into the runtime. + if cheaprand()&1023 != 0 { + // Only bother updating the cache ~1 in 1000 times. + return tab + } + // Load the current cache. + oldC := (*abi.TypeAssertCache)(atomic.Loadp(unsafe.Pointer(&s.Cache))) + + if cheaprand()&uint32(oldC.Mask) != 0 { + // As cache gets larger, choose to update it less often + // so we can amortize the cost of building a new cache. + return tab + } + + // Make a new cache. + newC := buildTypeAssertCache(oldC, t, tab) + + // Update cache. Use compare-and-swap so if multiple threads + // are fighting to update the cache, at least one of their + // updates will stick. + atomic_casPointer((*unsafe.Pointer)(unsafe.Pointer(&s.Cache)), unsafe.Pointer(oldC), unsafe.Pointer(newC)) + + return tab +} + +func getitab(inter *interfacetype, typ *_type, canfail bool) *itab { + if len(inter.Methods) == 0 { + throw("internal error - misuse of itab") + } + + // easy case + if typ.TFlag&abi.TFlagUncommon == 0 { + if canfail { + return nil + } + name := toRType(&inter.Type).nameOff(inter.Methods[0].Name) + panic(&TypeAssertionError{nil, typ, &inter.Type, name.Name()}) + } + + var m *itab + + // First, look in the existing table to see if we can find the itab we need. + // This is by far the most common case, so do it without locks. + // Use atomic to ensure we see any previous writes done by the thread + // that updates the itabTable field (with atomic.Storep in itabAdd). + t := (*itabTableType)(atomic.Loadp(unsafe.Pointer(&itabTable))) + if m = t.find(inter, typ); m != nil { + goto finish + } + + // Not found. Grab the lock and try again. + lock(&itabLock) + if m = itabTable.find(inter, typ); m != nil { + unlock(&itabLock) + goto finish + } + + // Entry doesn't exist yet. Make a new entry & add it. + m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.Methods)-1)*goarch.PtrSize, 0, &memstats.other_sys)) + m.inter = inter + m._type = typ + // The hash is used in type switches. However, compiler statically generates itab's + // for all interface/type pairs used in switches (which are added to itabTable + // in itabsinit). The dynamically-generated itab's never participate in type switches, + // and thus the hash is irrelevant. + // Note: m.hash is _not_ the hash used for the runtime itabTable hash table. + m.hash = 0 + m.init() + itabAdd(m) + unlock(&itabLock) +finish: + if m.fun[0] != 0 { + return m + } + if canfail { + return nil + } + // this can only happen if the conversion + // was already done once using the , ok form + // and we have a cached negative result. + // The cached result doesn't record which + // interface function was missing, so initialize + // the itab again to get the missing function name. + panic(&TypeAssertionError{concrete: typ, asserted: &inter.Type, missingMethod: m.init()}) +} + +// init fills in the m.fun array with all the code pointers for +// the m.inter/m._type pair. If the type does not implement the interface, +// it sets m.fun[0] to 0 and returns the name of an interface function that is missing. +// It is ok to call this multiple times on the same m, even concurrently. +func (m *itab) init() string { + inter := m.inter + typ := m._type + x := typ.Uncommon() + + // both inter and typ have method sorted by name, + // and interface names are unique, + // so can iterate over both in lock step; + // the loop is O(ni+nt) not O(ni*nt). + ni := len(inter.Methods) + nt := int(x.Mcount) + xmhdr := (*[1 << 16]abi.Method)(add(unsafe.Pointer(x), uintptr(x.Moff)))[:nt:nt] + j := 0 + methods := (*[1 << 16]unsafe.Pointer)(unsafe.Pointer(&m.fun[0]))[:ni:ni] + var fun0 unsafe.Pointer +imethods: + for k := 0; k < ni; k++ { + i := &inter.Methods[k] + itype := toRType(&inter.Type).typeOff(i.Typ) + name := toRType(&inter.Type).nameOff(i.Name) + iname := name.Name() + ipkg := pkgPath(name) + if ipkg == "" { + ipkg = inter.PkgPath.Name() + } + for ; j < nt; j++ { + t := &xmhdr[j] + rtyp := toRType(typ) + tname := rtyp.nameOff(t.Name) + if rtyp.typeOff(t.Mtyp) == itype && tname.Name() == iname { + pkgPath := pkgPath(tname) + if pkgPath == "" { + pkgPath = rtyp.nameOff(x.PkgPath).Name() + } + if tname.IsExported() || pkgPath == ipkg { + ifn := rtyp.textOff(t.Ifn) + if k == 0 { + fun0 = ifn // we'll set m.fun[0] at the end + } else { + methods[k] = ifn + } + continue imethods + } + } + } + // didn't find method + m.fun[0] = 0 + return iname + } + m.fun[0] = uintptr(fun0) + return "" +} + +// interfaceSwitch compares t against the list of cases in s. +// If t matches case i, interfaceSwitch returns the case index i and +// an itab for the pair . +// If there is no match, return N,nil, where N is the number +// of cases. +func interfaceSwitch(s *abi.InterfaceSwitch, t *_type) (int, *itab) { + cases := unsafe.Slice(&s.Cases[0], s.NCases) + + // Results if we don't find a match. + case_ := len(cases) + var tab *itab + + // Look through each case in order. + for i, c := range cases { + tab = getitab(c, t, true) + if tab != nil { + case_ = i + break + } + } + + if !abi.UseInterfaceSwitchCache(GOARCH) { + return case_, tab + } + + // Maybe update the cache, so the next time the generated code + // doesn't need to call into the runtime. + if cheaprand()&1023 != 0 { + // Only bother updating the cache ~1 in 1000 times. + // This ensures we don't waste memory on switches, or + // switch arguments, that only happen a few times. + return case_, tab + } + // Load the current cache. + oldC := (*abi.InterfaceSwitchCache)(atomic.Loadp(unsafe.Pointer(&s.Cache))) + + if cheaprand()&uint32(oldC.Mask) != 0 { + // As cache gets larger, choose to update it less often + // so we can amortize the cost of building a new cache + // (that cost is linear in oldc.Mask). + return case_, tab + } + + // Make a new cache. + newC := buildInterfaceSwitchCache(oldC, t, case_, tab) + + // Update cache. Use compare-and-swap so if multiple threads + // are fighting to update the cache, at least one of their + // updates will stick. + atomic_casPointer((*unsafe.Pointer)(unsafe.Pointer(&s.Cache)), unsafe.Pointer(oldC), unsafe.Pointer(newC)) + + return case_, tab +} +``` + +源代码虽然有点长,但是稍微耐心点是很容看懂的。 + +最关键的是要理解 `func getitab(inter *interfacetype, typ *_type, canfail bool) *itab` 这个函数在做什么。 + +它尝试从 interface type 和 struct type 里构造出一个 itab,如果能构造成功,那么就意味着这个 struct 实现了该 interface。 + +而且你可以看到,它还用了缓存机制,第一次构造成功之后就会缓存起来,后续再进行这样的构造时就直接从缓存里拿了,空间换时间,提高性能。 + +最终核心的函数是`func (m *itab) init() string`。它会尝试从可执行文件里寻找所有 interface/struct pair(主要是 rodata 和 text 段的数据),也就是看这个 struct 是否都实现了 interface 所规定的所有函数。 + +type switch 呢?一样的,最终都会落到 `func getitab(inter *interfacetype, typ *_type, canfail bool) *itab` 这个函数上。 + +自此,我们基本上理解了 interface 在 Go 中是如何实现的了,当然其中还有很多细节,但是对于我们理解整体的实现原理并无影响。 + +## 变量实现和指针实现接口有什么不同? + +稍微要涉及一点汇编代码的细节了。 + +TODO + +## 总结一下 + +- 查看汇编代码可以很直观地理解 go 语言运行的过程。 +- 程序的底层是以 iface/eface/interfacetype/\_type 等各种 abi 数据结构为“介质”来进行交互的。如果说调用一个函数的参数是某种 interface 类型,那么从汇编程序中就可以看出,程序现在堆栈上构造出 iface/eface,然后再调用函数,之后就可以实现 interface 的各种功能了。 +- go 会为每一种 `type x interface` 记录一条 `itab`,这个非常重要。比如说有三种 interface,而且分别有三个具体类型都实现这三个接口,那么汇编代码里就有 9 个 itab 的 rodata。有了这些,就可以实现 interface 那些神奇的功能了。 +- 很多 interface 最终都是调用了 go 写的函数而不是汇编级代码,比如说类型 switch 就对应了 runtime.interfaceSwitch,类型推断对应了 runtime.typeAssert,等等。 +- 编译器和 runtime 之间需要有一个规约(abi),才能相互无缝地相互配合,让程序运行起来。 +- 真正理解了 itab iface eface 等数据结构,那么 interface 的各种特性的实现则是不言自明的。 + +## 反射的实现 + +聊完 interface 的实现后再来聊 reflection 就顺理成章了。 + +具体实现是怎么样的呢? + +interface 实现源码中的  eface 和  iface  会和反射实现源码中的 emptyInterface 和 nonEmptyInterface 是一样的数据结构,它们保持同步。 + +反射中提供了两个核心的数据结构,Type 和 Value,在此基础上实现了各种方法,这两个都叫做反射对象。 + +Type 和 Value 提供了非常多的方法:例如获取对象的属性列表、获取和修改某个属性的值、对象所属结构体的名字、对象的底层类型(underlying type)等等。 + +Go 中的反射,在使用中最核心的就两个函数: + +- `reflect.TypeOf(x)` +- `reflect.ValueOf(x)` + +这两个函数可以分别将给定的数据对象转化为以上的 Type 和 Value,这两个都叫做反射对象。 + +这两个函数的实现源码如下: + +```go +// TypeOf returns the reflection Type that represents the dynamic type of i. +// If i is a nil interface value, TypeOf returns nil. +func TypeOf(i interface{}) Type { + eface := *(*emptyInterface)(unsafe.Pointer(&i)) + return toType(eface.typ) +} + +// toType converts from a *rtype to a Type that can be returned +// to the client of package reflect. In gc, the only concern is that +// a nil *rtype must be replaced by a nil Type, but in gccgo this +// function takes care of ensuring that multiple *rtype for the same +// type are coalesced into a single Type. +func toType(t *abi.Type) Type { + if t == nil { + return nil + } + return toRType(t) +} + +func toRType(t *abi.Type) *rtype { + return (*rtype)(unsafe.Pointer(t)) +} +``` + +```go +// ValueOf returns a new Value initialized to the concrete value +// stored in the interface i. ValueOf(nil) returns the zero Value. +func ValueOf(i any) Value { + if i == nil { + return Value{} + } + return unpackEface(i) +} + +// unpackEface converts the empty interface i to a Value. +func unpackEface(i any) Value { + e := (*emptyInterface)(unsafe.Pointer(&i)) + // NOTE: don't read e.word until we know whether it is really a pointer or not. + t := e.typ + if t == nil { + return Value{} + } + f := flag(t.Kind()) + if ifaceIndir(t) { + f |= flagIndir + } + return Value{t, e.word, f} +} +``` + +实际上也是一个 pack 和 unpack 出 emptyInterface/nonEmptyInterface 的过程。 + +--- + +在 Go 中,反射是在类型系统的基础上包装了一套更高级的类型系统的用法。上面说那些类型推断、类型转换只不过是这套类型系统的一个应用而已,而且这个应用直接集成到了代码语法上。 + +反射无非就是把 itab 这样的静态数据的构造从编译阶段放到了运行阶段。或者从另外一个角度来说,就是把静态类型检查从编译阶段放到了运行阶段。 + +Go 中反射机制的本质是,Go 会把函数和类型的元数据(尤其是 itab,比如:go.itab.\*"".MyStruct,"".MyInterface SRODATA dupok size=48)存储在 rodata 里,在运行时,通过读取这些元数据,来动态构造出 iface,然后在此基础上进行一些数据修改或函数的调用。 + +## 反射三定律 + +根据 Go 官方关于反射的博客,反射有三大定律: + +- Reflection goes from interface value to reflection object. +- Reflection goes from reflection object to interface value. +- To modify a reflection object, the value must be settable. + +关于第三条,记住一句话:如果想要操作原变量,反射变量 Value 必须要 hold 住原变量的地址才行。 + +## 反射的优劣 + +使用反射的优势: + +- 程序抽象性提升 +- 程序表达力提升 + +适用反射的坏处: + +- 程序维护性降低 +- 程序性能降低 +- 程序安全性降低 + +## 参考资料 + +- [go internals Chapter II: Interfaces](https://github.com/teh-cmc/go-internals/blob/master/chapter2_interfaces/README.md) +- [Go Data Structures: Interfaces](https://research.swtch.com/interfaces) +- [Finding unreachable functions with deadcode](https://go.dev/blog/deadcode) +- [A Quick Guide to Go's Assembler](https://go.dev/doc/asm) +- [Introduction to the Go compiler](https://go.dev/src/cmd/compile/README) +- [Go 语言设计与实现 4.2 接口](https://draveness.me/Go/docs/part2-foundation/ch04-basic/Go-interface) diff --git a/source/_posts/2024-06-go-interface/iface.png b/source/_posts/2024-06-go-interface/iface.png new file mode 100644 index 0000000..8d8f735 Binary files /dev/null and b/source/_posts/2024-06-go-interface/iface.png differ diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 4cb3b62..0000000 --- a/yarn.lock +++ /dev/null @@ -1,1592 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@adobe/css-tools@~4.3.1": - "integrity" "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==" - "resolved" "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz" - "version" "4.3.3" - -"@tootallnate/once@2": - "integrity" "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - "resolved" "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" - "version" "2.0.0" - -"a-sync-waterfall@^1.0.0": - "integrity" "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" - "resolved" "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz" - "version" "1.0.1" - -"abab@^2.0.6": - "integrity" "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" - "resolved" "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" - "version" "2.0.6" - -"abbrev@^2.0.0": - "integrity" "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" - "resolved" "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz" - "version" "2.0.0" - -"accepts@~1.3.5": - "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" - "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" - "version" "1.3.8" - dependencies: - "mime-types" "~2.1.34" - "negotiator" "0.6.3" - -"acorn-globals@^7.0.0": - "integrity" "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==" - "resolved" "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz" - "version" "7.0.1" - dependencies: - "acorn" "^8.1.0" - "acorn-walk" "^8.0.2" - -"acorn-walk@^8.0.2": - "integrity" "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==" - "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz" - "version" "8.3.2" - -"acorn@^8.1.0", "acorn@^8.8.1": - "integrity" "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" - "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" - "version" "8.11.3" - -"agent-base@6": - "integrity" "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==" - "resolved" "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" - "version" "6.0.2" - dependencies: - "debug" "4" - -"ansi-regex@^5.0.1": - "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - "version" "5.0.1" - -"ansi-styles@^4.1.0": - "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" - "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - "version" "4.3.0" - dependencies: - "color-convert" "^2.0.1" - -"anymatch@~3.1.2": - "integrity" "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==" - "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" - "version" "3.1.3" - dependencies: - "normalize-path" "^3.0.0" - "picomatch" "^2.0.4" - -"archy@^1.0.0": - "integrity" "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" - "resolved" "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" - "version" "1.0.0" - -"argparse@^2.0.1": - "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - "version" "2.0.1" - -"asap@^2.0.3": - "integrity" "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - "resolved" "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" - "version" "2.0.6" - -"async@^3.2.3": - "integrity" "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - "resolved" "https://registry.npmjs.org/async/-/async-3.2.5.tgz" - "version" "3.2.5" - -"asynckit@^0.4.0": - "integrity" "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - "resolved" "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - "version" "0.4.0" - -"balanced-match@^1.0.0": - "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - "version" "1.0.2" - -"basic-auth@~2.0.1": - "integrity" "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==" - "resolved" "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "safe-buffer" "5.1.2" - -"binary-extensions@^2.0.0": - "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" - "version" "2.2.0" - -"bluebird@^3.5.2", "bluebird@^3.5.5", "bluebird@^3.7.2": - "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" - "version" "3.7.2" - -"brace-expansion@^1.1.7": - "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - "version" "1.1.11" - dependencies: - "balanced-match" "^1.0.0" - "concat-map" "0.0.1" - -"brace-expansion@^2.0.1": - "integrity" "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==" - "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "balanced-match" "^1.0.0" - -"braces@^3.0.2", "braces@~3.0.2": - "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" - "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "fill-range" "^7.0.1" - -"bytes@3.0.0": - "integrity" "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" - "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" - "version" "3.0.0" - -"camel-case@^4.0.0", "camel-case@^4.1.2": - "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" - "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "pascal-case" "^3.1.2" - "tslib" "^2.0.3" - -"chalk@^4.0.2": - "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "ansi-styles" "^4.1.0" - "supports-color" "^7.1.0" - -"chokidar@^3.3.0", "chokidar@^3.5.3": - "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" - "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - "version" "3.5.3" - dependencies: - "anymatch" "~3.1.2" - "braces" "~3.0.2" - "glob-parent" "~5.1.2" - "is-binary-path" "~2.1.0" - "is-glob" "~4.0.1" - "normalize-path" "~3.0.0" - "readdirp" "~3.6.0" - optionalDependencies: - "fsevents" "~2.3.2" - -"color-convert@^2.0.1": - "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" - "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "color-name" "~1.1.4" - -"color-name@~1.1.4": - "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - "version" "1.1.4" - -"combined-stream@^1.0.8": - "integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==" - "resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" - "version" "1.0.8" - dependencies: - "delayed-stream" "~1.0.0" - -"command-exists@^1.2.9": - "integrity" "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - "resolved" "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" - "version" "1.2.9" - -"commander@^5.1.0": - "integrity" "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - "resolved" "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz" - "version" "5.1.0" - -"compressible@~2.0.16": - "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" - "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" - "version" "2.0.18" - dependencies: - "mime-db" ">= 1.43.0 < 2" - -"compression@^1.7.4": - "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" - "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" - "version" "1.7.4" - dependencies: - "accepts" "~1.3.5" - "bytes" "3.0.0" - "compressible" "~2.0.16" - "debug" "2.6.9" - "on-headers" "~1.0.2" - "safe-buffer" "5.1.2" - "vary" "~1.1.2" - -"concat-map@0.0.1": - "integrity" "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - "version" "0.0.1" - -"connect@^3.7.0": - "integrity" "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==" - "resolved" "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz" - "version" "3.7.0" - dependencies: - "debug" "2.6.9" - "finalhandler" "1.1.2" - "parseurl" "~1.3.3" - "utils-merge" "1.0.1" - -"cross-spawn@^7.0.0", "cross-spawn@^7.0.3": - "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" - "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" - "version" "7.0.3" - dependencies: - "path-key" "^3.1.0" - "shebang-command" "^2.0.0" - "which" "^2.0.1" - -"cssom@^0.5.0": - "integrity" "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==" - "resolved" "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz" - "version" "0.5.0" - -"cssom@~0.3.6": - "integrity" "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - "resolved" "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" - "version" "0.3.8" - -"cssstyle@^2.3.0": - "integrity" "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==" - "resolved" "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" - "version" "2.3.0" - dependencies: - "cssom" "~0.3.6" - -"cuid@^2.1.8": - "integrity" "sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg==" - "resolved" "https://registry.npmjs.org/cuid/-/cuid-2.1.8.tgz" - "version" "2.1.8" - -"data-urls@^3.0.2": - "integrity" "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==" - "resolved" "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "abab" "^2.0.6" - "whatwg-mimetype" "^3.0.0" - "whatwg-url" "^11.0.0" - -"debug@^4.3.2": - "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" - "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - "version" "4.3.4" - dependencies: - "ms" "2.1.2" - -"debug@2.6.9": - "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - "version" "2.6.9" - dependencies: - "ms" "2.0.0" - -"debug@4": - "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" - "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - "version" "4.3.4" - dependencies: - "ms" "2.1.2" - -"decimal.js@^10.4.2": - "integrity" "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" - "resolved" "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" - "version" "10.4.3" - -"deepmerge@^4.2.2": - "integrity" "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" - "version" "4.3.1" - -"define-lazy-prop@^2.0.0": - "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" - "version" "2.0.0" - -"delayed-stream@~1.0.0": - "integrity" "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - "resolved" "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - "version" "1.0.0" - -"depd@~2.0.0", "depd@2.0.0": - "integrity" "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - "resolved" "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" - "version" "2.0.0" - -"destroy@1.2.0": - "integrity" "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" - "version" "1.2.0" - -"dom-serializer@^1.0.1": - "integrity" "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz" - "version" "1.4.1" - dependencies: - "domelementtype" "^2.0.1" - "domhandler" "^4.2.0" - "entities" "^2.0.0" - -"dom-serializer@^2.0.0": - "integrity" "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==" - "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "domelementtype" "^2.3.0" - "domhandler" "^5.0.2" - "entities" "^4.2.0" - -"domelementtype@^2.0.1", "domelementtype@^2.2.0", "domelementtype@^2.3.0": - "integrity" "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" - "version" "2.3.0" - -"domexception@^4.0.0": - "integrity" "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==" - "resolved" "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "webidl-conversions" "^7.0.0" - -"domhandler@^4.2.0", "domhandler@^4.2.2": - "integrity" "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==" - "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz" - "version" "4.3.1" - dependencies: - "domelementtype" "^2.2.0" - -"domhandler@^5.0.2", "domhandler@^5.0.3": - "integrity" "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==" - "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" - "version" "5.0.3" - dependencies: - "domelementtype" "^2.3.0" - -"dompurify@^3.0.3": - "integrity" "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==" - "resolved" "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz" - "version" "3.0.8" - -"domutils@^2.8.0": - "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" - "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" - "version" "2.8.0" - dependencies: - "dom-serializer" "^1.0.1" - "domelementtype" "^2.2.0" - "domhandler" "^4.2.0" - -"domutils@^3.1.0": - "integrity" "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==" - "resolved" "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "dom-serializer" "^2.0.0" - "domelementtype" "^2.3.0" - "domhandler" "^5.0.3" - -"ee-first@1.1.1": - "integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - "version" "1.1.1" - -"ejs@^3.1.6": - "integrity" "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==" - "resolved" "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz" - "version" "3.1.9" - dependencies: - "jake" "^10.8.5" - -"encodeurl@~1.0.2": - "integrity" "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" - "version" "1.0.2" - -"entities@^2.0.0": - "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" - "version" "2.2.0" - -"entities@^3.0.1": - "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" - "resolved" "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz" - "version" "3.0.1" - -"entities@^4.2.0", "entities@^4.4.0", "entities@^4.5.0": - "integrity" "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - "resolved" "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" - "version" "4.5.0" - -"escape-html@~1.0.3": - "integrity" "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - "version" "1.0.3" - -"escodegen@^2.0.0": - "integrity" "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==" - "resolved" "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "esprima" "^4.0.1" - "estraverse" "^5.2.0" - "esutils" "^2.0.2" - optionalDependencies: - "source-map" "~0.6.1" - -"esprima@^4.0.1": - "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" - "version" "4.0.1" - -"estraverse@^5.2.0": - "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" - "version" "5.3.0" - -"esutils@^2.0.2": - "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" - "version" "2.0.3" - -"etag@~1.8.1": - "integrity" "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" - "version" "1.8.1" - -"fast-equals@^3.0.1": - "integrity" "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==" - "resolved" "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz" - "version" "3.0.3" - -"filelist@^1.0.4": - "integrity" "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==" - "resolved" "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz" - "version" "1.0.4" - dependencies: - "minimatch" "^5.0.1" - -"fill-range@^7.0.1": - "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" - "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - "version" "7.0.1" - dependencies: - "to-regex-range" "^5.0.1" - -"finalhandler@1.1.2": - "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" - "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" - "version" "1.1.2" - dependencies: - "debug" "2.6.9" - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "on-finished" "~2.3.0" - "parseurl" "~1.3.3" - "statuses" "~1.5.0" - "unpipe" "~1.0.0" - -"form-data@^4.0.0": - "integrity" "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==" - "resolved" "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "asynckit" "^0.4.0" - "combined-stream" "^1.0.8" - "mime-types" "^2.1.12" - -"fresh@0.5.2": - "integrity" "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" - "version" "0.5.2" - -"fs.realpath@^1.0.0": - "integrity" "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - "version" "1.0.0" - -"fsevents@~2.3.2": - "integrity" "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" - "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - "version" "2.3.3" - -"function-bind@^1.1.2": - "integrity" "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" - "version" "1.1.2" - -"glob-parent@~5.1.2": - "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" - "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - "version" "5.1.2" - dependencies: - "is-glob" "^4.0.1" - -"glob@^7.1.6": - "integrity" "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==" - "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" - "version" "7.2.3" - dependencies: - "fs.realpath" "^1.0.0" - "inflight" "^1.0.4" - "inherits" "2" - "minimatch" "^3.1.1" - "once" "^1.3.0" - "path-is-absolute" "^1.0.0" - -"graceful-fs@^4.2.10": - "integrity" "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" - "version" "4.2.11" - -"has-flag@^4.0.0": - "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - "version" "4.0.0" - -"hasown@^2.0.0": - "integrity" "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==" - "resolved" "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "function-bind" "^1.1.2" - -"hexo-cli@^4.3.0": - "integrity" "sha512-nYe7yJhXT7MwlDEpIAjneMfz0wnWTdIhRv+cVW2OPTw8JtG2X+8Y/sYhPDvQz/ZqjFRZ4qgiKFXN5orFJ/u1vg==" - "resolved" "https://registry.npmjs.org/hexo-cli/-/hexo-cli-4.3.1.tgz" - "version" "4.3.1" - dependencies: - "abbrev" "^2.0.0" - "bluebird" "^3.7.2" - "command-exists" "^1.2.9" - "hexo-fs" "^4.1.1" - "hexo-log" "^4.0.1" - "hexo-util" "^2.5.0" - "minimist" "^1.2.5" - "picocolors" "^1.0.0" - "resolve" "^1.20.0" - "tildify" "^2.0.0" - -"hexo-front-matter@^4.2.1": - "integrity" "sha512-sJJI0GNmejYiwBvgnGRKn5V3sbODB4dNPr8jyw2Qp0PRHr4Uuyv8iyxw6WfK3+T7yvzYvJOh+tZ7jnwr2BYARA==" - "resolved" "https://registry.npmjs.org/hexo-front-matter/-/hexo-front-matter-4.2.1.tgz" - "version" "4.2.1" - dependencies: - "js-yaml" "^4.1.0" - -"hexo-fs@^4.1.1": - "integrity" "sha512-aDysNTyv8ElcerbFVbPLRXnYt+QDY6gAOZZ5DLbCxudY0Ywppqd+uZ03gZ2BDypIBvmNB27WYWYz76M+Yv/YXw==" - "resolved" "https://registry.npmjs.org/hexo-fs/-/hexo-fs-4.1.1.tgz" - "version" "4.1.1" - dependencies: - "bluebird" "^3.7.2" - "chokidar" "^3.5.3" - "graceful-fs" "^4.2.10" - "hexo-util" "^2.7.0" - -"hexo-generator-archive@^2.0.0": - "integrity" "sha512-KikJk7dGFbtNHOgqtLFGf5T/S8n1paGp+Gy0KfVDz+HKYhGbXOouyiZkmc3O9KrYt6ja14rmkMhq7KKGtvfehw==" - "resolved" "https://registry.npmjs.org/hexo-generator-archive/-/hexo-generator-archive-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "hexo-pagination" "3.0.0" - -"hexo-generator-category@^2.0.0": - "integrity" "sha512-9OduRBf3WeRDa4BR0kAfRjOVHur7v3fm0NKAwbjUiqULigAdNZVZPO3cHKW2MlBbl/lI5PuWdhQ9zZ99CCCAgQ==" - "resolved" "https://registry.npmjs.org/hexo-generator-category/-/hexo-generator-category-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "hexo-pagination" "3.0.0" - -"hexo-generator-feed@^3.0.0": - "integrity" "sha512-Jo35VSRSNeMitS2JmjCq3OHAXXYU4+JIODujHtubdG/NRj2++b3Tgyz9pwTmROx6Yxr2php/hC8og5AGZHh8UQ==" - "resolved" "https://registry.npmjs.org/hexo-generator-feed/-/hexo-generator-feed-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "hexo-util" "^2.1.0" - "nunjucks" "^3.0.0" - -"hexo-generator-index@^3.0.0": - "integrity" "sha512-83AuNN4cWdLVi//3ugR8E3kR6rrOwhXZt+hOCm1IjtIGj353/GlrtpMHpqZHU5kqipzj4miy9dweVdukXglVWw==" - "resolved" "https://registry.npmjs.org/hexo-generator-index/-/hexo-generator-index-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "hexo-pagination" "3.0.0" - -"hexo-generator-tag@^2.0.0": - "integrity" "sha512-1px/hF3veEohWDN8jjzchQhaiz+uOStUvvMaBJC9vWOlALh30UFcapL8IrvAwwJZjFRVA+WqGgDRqoQ8+yaaFw==" - "resolved" "https://registry.npmjs.org/hexo-generator-tag/-/hexo-generator-tag-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "hexo-pagination" "3.0.0" - -"hexo-i18n@^2.0.0": - "integrity" "sha512-dkUXecEtChaQMdTHN4WR13c8GwKqjbSOZPJS9qDqV6Ebnb77Wa/nQzWFckhP0dCps3a9lUQBd8hYGOMbOosiQQ==" - "resolved" "https://registry.npmjs.org/hexo-i18n/-/hexo-i18n-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "sprintf-js" "^1.1.2" - -"hexo-image-link@^0.0.5": - "integrity" "sha512-IakmAA0lPATF6iUfHAzYSuZPA6DYLlMj4LTGnT4LeEtmIHjPWsTDgGssPbMJakA47M1vNv5WwiNS3GCtdH2FQw==" - "resolved" "https://registry.npmjs.org/hexo-image-link/-/hexo-image-link-0.0.5.tgz" - "version" "0.0.5" - -"hexo-log@^4.0.1": - "integrity" "sha512-i2Sgxk8Cgx5viSjq5qW5N/rBFfwoCKQcH8qnnW1fawCapcdEAhIsq+Y3vbrs9bssyDlyU6Vqm4oQmosREaNI7Q==" - "resolved" "https://registry.npmjs.org/hexo-log/-/hexo-log-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "picocolors" "^1.0.0" - -"hexo-pagination@3.0.0": - "integrity" "sha512-8oo1iozloZo7TojPVYg4IxL3SJKCBdSJ908fTlIxIK7TWJIKdYnQlW31+12DBJ0NhVZA/lZisPObGF08wT8fKw==" - "resolved" "https://registry.npmjs.org/hexo-pagination/-/hexo-pagination-3.0.0.tgz" - "version" "3.0.0" - -"hexo-renderer-ejs@^2.0.0": - "integrity" "sha512-qCjE1IdwgDgv65qyb0KMVCwCdSVAkH0vwAe9XihjvaKWkmb9dtt8DgErOdqCXn0HReSyWiEVP2BrLRj3gyHwOQ==" - "resolved" "https://registry.npmjs.org/hexo-renderer-ejs/-/hexo-renderer-ejs-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "ejs" "^3.1.6" - -"hexo-renderer-marked@^6.0.0": - "integrity" "sha512-/TwgQCAmqYIyxONzrgqokw0n8rU6W/lCtgbjhWcMoZxhwTaQCYpzaO0+sdu+PKXf9BL4910pg+xAbeFaqqIIrA==" - "resolved" "https://registry.npmjs.org/hexo-renderer-marked/-/hexo-renderer-marked-6.2.0.tgz" - "version" "6.2.0" - dependencies: - "dompurify" "^3.0.3" - "hexo-util" "^3.1.0" - "jsdom" "^20.0.1" - "marked" "^4.3.0" - -"hexo-renderer-stylus@^3.0.0": - "integrity" "sha512-cFm8ZwShBBeFcQwOXc8EK7lIZnSYVD6OJykdL4GBw99hxc4eD5Hlsi32nRzE8sgKv00jhX1s9Da3GVVFMPAVQg==" - "resolved" "https://registry.npmjs.org/hexo-renderer-stylus/-/hexo-renderer-stylus-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "nib" "^1.2.0" - "stylus" "^0.62.0" - -"hexo-server@^3.0.0": - "integrity" "sha512-u4s0ty9Aew6jV+a9oMrXBwhrRpUQ0U8PWM/88a5aHgDru58VY81mVrxOFxs788NAsWQ8OvsJtF5m7mnXoRnSIA==" - "resolved" "https://registry.npmjs.org/hexo-server/-/hexo-server-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "bluebird" "^3.5.5" - "compression" "^1.7.4" - "connect" "^3.7.0" - "mime" "^3.0.0" - "morgan" "^1.9.1" - "open" "^8.0.9" - "picocolors" "^1.0.0" - "serve-static" "^1.14.1" - -"hexo-theme-landscape@^1.0.0": - "integrity" "sha512-bWQJWMqQI78wWiJPQZq5pJBH20TM442ShCaHGRetuEgMraxH0OKxB3NTupJzNEkzEk8DV2yrdizkXdKN6i501A==" - "resolved" "https://registry.npmjs.org/hexo-theme-landscape/-/hexo-theme-landscape-1.0.0.tgz" - "version" "1.0.0" - -"hexo-theme-next@^v7.8.0": - "integrity" "sha512-XecKX/8hkipAGfrm+SWnTmd++21w/JpJkidUfGutFD1sW4b9y/z/f7Fr8sPbtJdK/1WJzSV7Pz8bdQqHNPEPSA==" - "resolved" "https://registry.npmjs.org/hexo-theme-next/-/hexo-theme-next-7.8.0.tgz" - "version" "7.8.0" - -"hexo-util@^2.1.0", "hexo-util@^2.5.0", "hexo-util@^2.7.0": - "integrity" "sha512-hQM3h34nhDg0bSe/Tg1lnpODvNkz7h2u0+lZGzlKL0Oufp+5KCAEUX9wal7/xC7ax3/cwEn8IuoU75kNpZLpJQ==" - "resolved" "https://registry.npmjs.org/hexo-util/-/hexo-util-2.7.0.tgz" - "version" "2.7.0" - dependencies: - "bluebird" "^3.5.2" - "camel-case" "^4.0.0" - "cross-spawn" "^7.0.0" - "deepmerge" "^4.2.2" - "highlight.js" "^11.0.1" - "htmlparser2" "^7.0.0" - "prismjs" "^1.17.1" - "strip-indent" "^3.0.0" - -"hexo-util@^3.0.1": - "integrity" "sha512-iM2eS8P88IUpcgiU2szx584bwhXzjzLLqED6WwDk55wYQZrQh/sni/UJwmoW4pxpgubbISIUPXr4LjwPyJuYzA==" - "resolved" "https://registry.npmjs.org/hexo-util/-/hexo-util-3.2.0.tgz" - "version" "3.2.0" - dependencies: - "camel-case" "^4.1.2" - "cross-spawn" "^7.0.3" - "deepmerge" "^4.2.2" - "highlight.js" "^11.6.0" - "htmlparser2" "^9.0.0" - "prismjs" "^1.29.0" - "strip-indent" "^3.0.0" - -"hexo-util@^3.1.0": - "integrity" "sha512-iM2eS8P88IUpcgiU2szx584bwhXzjzLLqED6WwDk55wYQZrQh/sni/UJwmoW4pxpgubbISIUPXr4LjwPyJuYzA==" - "resolved" "https://registry.npmjs.org/hexo-util/-/hexo-util-3.2.0.tgz" - "version" "3.2.0" - dependencies: - "camel-case" "^4.1.2" - "cross-spawn" "^7.0.3" - "deepmerge" "^4.2.2" - "highlight.js" "^11.6.0" - "htmlparser2" "^9.0.0" - "prismjs" "^1.29.0" - "strip-indent" "^3.0.0" - -"hexo@^7.0.0": - "integrity" "sha512-u6aJXG1npYkZJLl7QEOeTdm9hOwxfsLmFp4qAQVF0OAuNaikrKORjgNsjPmrWwI/tIObwjVJnEUJnV7S+NnUlw==" - "resolved" "https://registry.npmjs.org/hexo/-/hexo-7.1.1.tgz" - "version" "7.1.1" - dependencies: - "abbrev" "^2.0.0" - "archy" "^1.0.0" - "bluebird" "^3.7.2" - "hexo-cli" "^4.3.0" - "hexo-front-matter" "^4.2.1" - "hexo-fs" "^4.1.1" - "hexo-i18n" "^2.0.0" - "hexo-log" "^4.0.1" - "hexo-util" "^3.0.1" - "js-yaml" "^4.1.0" - "js-yaml-js-types" "^1.0.0" - "micromatch" "^4.0.4" - "moize" "^6.1.6" - "moment" "^2.29.1" - "moment-timezone" "^0.5.34" - "nunjucks" "^3.2.3" - "picocolors" "^1.0.0" - "pretty-hrtime" "^1.0.3" - "resolve" "^1.22.0" - "strip-ansi" "^6.0.0" - "text-table" "^0.2.0" - "tildify" "^2.0.0" - "titlecase" "^1.1.3" - "warehouse" "^5.0.0" - -"highlight.js@^11.0.1", "highlight.js@^11.6.0": - "integrity" "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==" - "resolved" "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz" - "version" "11.9.0" - -"html-encoding-sniffer@^3.0.0": - "integrity" "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==" - "resolved" "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "whatwg-encoding" "^2.0.0" - -"htmlparser2@^7.0.0": - "integrity" "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==" - "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz" - "version" "7.2.0" - dependencies: - "domelementtype" "^2.0.1" - "domhandler" "^4.2.2" - "domutils" "^2.8.0" - "entities" "^3.0.1" - -"htmlparser2@^9.0.0": - "integrity" "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==" - "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz" - "version" "9.1.0" - dependencies: - "domelementtype" "^2.3.0" - "domhandler" "^5.0.3" - "domutils" "^3.1.0" - "entities" "^4.5.0" - -"http-errors@2.0.0": - "integrity" "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==" - "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "depd" "2.0.0" - "inherits" "2.0.4" - "setprototypeof" "1.2.0" - "statuses" "2.0.1" - "toidentifier" "1.0.1" - -"http-proxy-agent@^5.0.0": - "integrity" "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==" - "resolved" "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "@tootallnate/once" "2" - "agent-base" "6" - "debug" "4" - -"https-proxy-agent@^5.0.1": - "integrity" "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==" - "resolved" "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "agent-base" "6" - "debug" "4" - -"iconv-lite@0.6.3": - "integrity" "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==" - "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" - "version" "0.6.3" - dependencies: - "safer-buffer" ">= 2.1.2 < 3.0.0" - -"inflight@^1.0.4": - "integrity" "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" - "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - "version" "1.0.6" - dependencies: - "once" "^1.3.0" - "wrappy" "1" - -"inherits@^2.0.3", "inherits@2", "inherits@2.0.4": - "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - "version" "2.0.4" - -"is-binary-path@~2.1.0": - "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" - "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "binary-extensions" "^2.0.0" - -"is-core-module@^2.13.0": - "integrity" "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==" - "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" - "version" "2.13.1" - dependencies: - "hasown" "^2.0.0" - -"is-docker@^2.0.0", "is-docker@^2.1.1": - "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" - "version" "2.2.1" - -"is-extglob@^2.1.1": - "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - "version" "2.1.1" - -"is-glob@^4.0.1", "is-glob@~4.0.1": - "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" - "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "is-extglob" "^2.1.1" - -"is-number@^7.0.0": - "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - "version" "7.0.0" - -"is-plain-object@^5.0.0": - "integrity" "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz" - "version" "5.0.0" - -"is-potential-custom-element-name@^1.0.1": - "integrity" "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" - "resolved" "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" - "version" "1.0.1" - -"is-wsl@^2.2.0": - "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" - "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" - "version" "2.2.0" - dependencies: - "is-docker" "^2.0.0" - -"isexe@^2.0.0": - "integrity" "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - "version" "2.0.0" - -"jake@^10.8.5": - "integrity" "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==" - "resolved" "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz" - "version" "10.8.7" - dependencies: - "async" "^3.2.3" - "chalk" "^4.0.2" - "filelist" "^1.0.4" - "minimatch" "^3.1.2" - -"js-yaml-js-types@^1.0.0": - "integrity" "sha512-5tpfyORs8OQ43alNERbWfYRCtWgykvzYgY46fUhrQi2+kS7N0NuuFYLZ/IrfmVm5muLTndeMublgraXiFRjEPw==" - "resolved" "https://registry.npmjs.org/js-yaml-js-types/-/js-yaml-js-types-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "esprima" "^4.0.1" - -"js-yaml@^4.1.0", "js-yaml@4.x": - "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" - "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "argparse" "^2.0.1" - -"jsdom@^20.0.1": - "integrity" "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==" - "resolved" "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz" - "version" "20.0.3" - dependencies: - "abab" "^2.0.6" - "acorn" "^8.8.1" - "acorn-globals" "^7.0.0" - "cssom" "^0.5.0" - "cssstyle" "^2.3.0" - "data-urls" "^3.0.2" - "decimal.js" "^10.4.2" - "domexception" "^4.0.0" - "escodegen" "^2.0.0" - "form-data" "^4.0.0" - "html-encoding-sniffer" "^3.0.0" - "http-proxy-agent" "^5.0.0" - "https-proxy-agent" "^5.0.1" - "is-potential-custom-element-name" "^1.0.1" - "nwsapi" "^2.2.2" - "parse5" "^7.1.1" - "saxes" "^6.0.0" - "symbol-tree" "^3.2.4" - "tough-cookie" "^4.1.2" - "w3c-xmlserializer" "^4.0.0" - "webidl-conversions" "^7.0.0" - "whatwg-encoding" "^2.0.0" - "whatwg-mimetype" "^3.0.0" - "whatwg-url" "^11.0.0" - "ws" "^8.11.0" - "xml-name-validator" "^4.0.0" - -"jsonparse@^1.3.1": - "integrity" "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==" - "resolved" "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz" - "version" "1.3.1" - -"lower-case@^2.0.2": - "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" - "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "tslib" "^2.0.3" - -"marked@^4.3.0": - "integrity" "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==" - "resolved" "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz" - "version" "4.3.0" - -"micro-memoize@^4.1.2": - "integrity" "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==" - "resolved" "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz" - "version" "4.1.2" - -"micromatch@^4.0.4": - "integrity" "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==" - "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - "version" "4.0.5" - dependencies: - "braces" "^3.0.2" - "picomatch" "^2.3.1" - -"mime-db@>= 1.43.0 < 2", "mime-db@1.52.0": - "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" - "version" "1.52.0" - -"mime-types@^2.1.12", "mime-types@~2.1.34": - "integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==" - "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" - "version" "2.1.35" - dependencies: - "mime-db" "1.52.0" - -"mime@^3.0.0": - "integrity" "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" - "resolved" "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz" - "version" "3.0.0" - -"mime@1.6.0": - "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" - "version" "1.6.0" - -"min-indent@^1.0.0": - "integrity" "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" - "resolved" "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" - "version" "1.0.1" - -"minimatch@^3.1.1", "minimatch@^3.1.2": - "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - "version" "3.1.2" - dependencies: - "brace-expansion" "^1.1.7" - -"minimatch@^5.0.1": - "integrity" "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" - "version" "5.1.6" - dependencies: - "brace-expansion" "^2.0.1" - -"minimist@^1.2.5": - "integrity" "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - "resolved" "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" - "version" "1.2.8" - -"moize@^6.1.6": - "integrity" "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==" - "resolved" "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz" - "version" "6.1.6" - dependencies: - "fast-equals" "^3.0.1" - "micro-memoize" "^4.1.2" - -"moment-timezone@^0.5.34": - "integrity" "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==" - "resolved" "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz" - "version" "0.5.44" - dependencies: - "moment" "^2.29.4" - -"moment@^2.29.1", "moment@^2.29.4": - "integrity" "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" - "resolved" "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz" - "version" "2.30.1" - -"morgan@^1.9.1": - "integrity" "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==" - "resolved" "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz" - "version" "1.10.0" - dependencies: - "basic-auth" "~2.0.1" - "debug" "2.6.9" - "depd" "~2.0.0" - "on-finished" "~2.3.0" - "on-headers" "~1.0.2" - -"ms@2.0.0": - "integrity" "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - "version" "2.0.0" - -"ms@2.1.2": - "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - "version" "2.1.2" - -"ms@2.1.3": - "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - "version" "2.1.3" - -"negotiator@0.6.3": - "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" - "version" "0.6.3" - -"nib@^1.2.0": - "integrity" "sha512-7HgrnMl/3yOmWykueO8/D0q+0iWwe7Z+CK2Eaq/xQV8w1hK80WN1oReRQkfkrztbAAnp/nTHkUSl5EcVkor6JQ==" - "resolved" "https://registry.npmjs.org/nib/-/nib-1.2.0.tgz" - "version" "1.2.0" - -"no-case@^3.0.4": - "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" - "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" - "version" "3.0.4" - dependencies: - "lower-case" "^2.0.2" - "tslib" "^2.0.3" - -"normalize-path@^3.0.0", "normalize-path@~3.0.0": - "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - "version" "3.0.0" - -"nunjucks@^3.0.0", "nunjucks@^3.2.3": - "integrity" "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==" - "resolved" "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz" - "version" "3.2.4" - dependencies: - "a-sync-waterfall" "^1.0.0" - "asap" "^2.0.3" - "commander" "^5.1.0" - -"nwsapi@^2.2.2": - "integrity" "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==" - "resolved" "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz" - "version" "2.2.7" - -"on-finished@~2.3.0": - "integrity" "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==" - "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - "version" "2.3.0" - dependencies: - "ee-first" "1.1.1" - -"on-finished@2.4.1": - "integrity" "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==" - "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" - "version" "2.4.1" - dependencies: - "ee-first" "1.1.1" - -"on-headers@~1.0.2": - "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" - "version" "1.0.2" - -"once@^1.3.0": - "integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" - "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - "version" "1.4.0" - dependencies: - "wrappy" "1" - -"open@^8.0.9": - "integrity" "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==" - "resolved" "https://registry.npmjs.org/open/-/open-8.4.2.tgz" - "version" "8.4.2" - dependencies: - "define-lazy-prop" "^2.0.0" - "is-docker" "^2.1.1" - "is-wsl" "^2.2.0" - -"parse5@^7.1.1": - "integrity" "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==" - "resolved" "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz" - "version" "7.1.2" - dependencies: - "entities" "^4.4.0" - -"parseurl@~1.3.3": - "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" - "version" "1.3.3" - -"pascal-case@^3.1.2": - "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" - "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" - "version" "3.1.2" - dependencies: - "no-case" "^3.0.4" - "tslib" "^2.0.3" - -"path-is-absolute@^1.0.0": - "integrity" "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - "version" "1.0.1" - -"path-key@^3.1.0": - "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" - "version" "3.1.1" - -"path-parse@^1.0.7": - "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" - "version" "1.0.7" - -"picocolors@^1.0.0": - "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - "version" "1.0.0" - -"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.3.1": - "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - "version" "2.3.1" - -"pretty-hrtime@^1.0.3": - "integrity" "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==" - "resolved" "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz" - "version" "1.0.3" - -"prismjs@^1.17.1", "prismjs@^1.29.0": - "integrity" "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" - "resolved" "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz" - "version" "1.29.0" - -"psl@^1.1.33": - "integrity" "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - "resolved" "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz" - "version" "1.9.0" - -"punycode@^2.1.1": - "integrity" "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" - "version" "2.3.1" - -"querystringify@^2.1.1": - "integrity" "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - "resolved" "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" - "version" "2.2.0" - -"range-parser@~1.2.1": - "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" - "version" "1.2.1" - -"readable-stream@3": - "integrity" "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==" - "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" - "version" "3.6.2" - dependencies: - "inherits" "^2.0.3" - "string_decoder" "^1.1.1" - "util-deprecate" "^1.0.1" - -"readdirp@~3.6.0": - "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" - "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - "version" "3.6.0" - dependencies: - "picomatch" "^2.2.1" - -"requires-port@^1.0.0": - "integrity" "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - "version" "1.0.0" - -"resolve@^1.20.0", "resolve@^1.22.0": - "integrity" "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==" - "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" - "version" "1.22.8" - dependencies: - "is-core-module" "^2.13.0" - "path-parse" "^1.0.7" - "supports-preserve-symlinks-flag" "^1.0.0" - -"rfdc@^1.3.0": - "integrity" "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" - "resolved" "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz" - "version" "1.3.1" - -"safe-buffer@~5.2.0": - "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - "version" "5.2.1" - -"safe-buffer@5.1.2": - "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - "version" "5.1.2" - -"safer-buffer@>= 2.1.2 < 3.0.0": - "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" - "version" "2.1.2" - -"sax@~1.3.0": - "integrity" "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" - "resolved" "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz" - "version" "1.3.0" - -"saxes@^6.0.0": - "integrity" "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==" - "resolved" "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "xmlchars" "^2.2.0" - -"send@0.18.0": - "integrity" "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==" - "resolved" "https://registry.npmjs.org/send/-/send-0.18.0.tgz" - "version" "0.18.0" - dependencies: - "debug" "2.6.9" - "depd" "2.0.0" - "destroy" "1.2.0" - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "etag" "~1.8.1" - "fresh" "0.5.2" - "http-errors" "2.0.0" - "mime" "1.6.0" - "ms" "2.1.3" - "on-finished" "2.4.1" - "range-parser" "~1.2.1" - "statuses" "2.0.1" - -"serve-static@^1.14.1": - "integrity" "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==" - "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" - "version" "1.15.0" - dependencies: - "encodeurl" "~1.0.2" - "escape-html" "~1.0.3" - "parseurl" "~1.3.3" - "send" "0.18.0" - -"setprototypeof@1.2.0": - "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" - "version" "1.2.0" - -"shebang-command@^2.0.0": - "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" - "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "shebang-regex" "^3.0.0" - -"shebang-regex@^3.0.0": - "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" - "version" "3.0.0" - -"source-map@^0.7.3": - "integrity" "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" - "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" - "version" "0.7.4" - -"source-map@~0.6.1": - "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - "version" "0.6.1" - -"sprintf-js@^1.1.2": - "integrity" "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" - "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz" - "version" "1.1.3" - -"statuses@~1.5.0": - "integrity" "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" - "version" "1.5.0" - -"statuses@2.0.1": - "integrity" "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - "resolved" "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" - "version" "2.0.1" - -"string_decoder@^1.1.1": - "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" - "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - "version" "1.3.0" - dependencies: - "safe-buffer" "~5.2.0" - -"strip-ansi@^6.0.0": - "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - "version" "6.0.1" - dependencies: - "ansi-regex" "^5.0.1" - -"strip-indent@^3.0.0": - "integrity" "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==" - "resolved" "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "min-indent" "^1.0.0" - -"stylus@*", "stylus@^0.62.0": - "integrity" "sha512-v3YCf31atbwJQIMtPNX8hcQ+okD4NQaTuKGUWfII8eaqn+3otrbttGL1zSMZAAtiPsBztQnujVBugg/cXFUpyg==" - "resolved" "https://registry.npmjs.org/stylus/-/stylus-0.62.0.tgz" - "version" "0.62.0" - dependencies: - "@adobe/css-tools" "~4.3.1" - "debug" "^4.3.2" - "glob" "^7.1.6" - "sax" "~1.3.0" - "source-map" "^0.7.3" - -"supports-color@^7.1.0": - "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - "version" "7.2.0" - dependencies: - "has-flag" "^4.0.0" - -"supports-preserve-symlinks-flag@^1.0.0": - "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" - "version" "1.0.0" - -"symbol-tree@^3.2.4": - "integrity" "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" - "resolved" "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" - "version" "3.2.4" - -"text-table@^0.2.0": - "integrity" "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - "version" "0.2.0" - -"through2@^4.0.2": - "integrity" "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==" - "resolved" "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz" - "version" "4.0.2" - dependencies: - "readable-stream" "3" - -"tildify@^2.0.0": - "integrity" "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==" - "resolved" "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz" - "version" "2.0.0" - -"titlecase@^1.1.3": - "integrity" "sha512-pQX4oiemzjBEELPqgK4WE+q0yhAqjp/yzusGtlSJsOuiDys0RQxggepYmo0BuegIDppYS3b3cpdegRwkpyN3hw==" - "resolved" "https://registry.npmjs.org/titlecase/-/titlecase-1.1.3.tgz" - "version" "1.1.3" - -"to-regex-range@^5.0.1": - "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" - "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "is-number" "^7.0.0" - -"toidentifier@1.0.1": - "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" - "version" "1.0.1" - -"tough-cookie@^4.1.2": - "integrity" "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==" - "resolved" "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz" - "version" "4.1.3" - dependencies: - "psl" "^1.1.33" - "punycode" "^2.1.1" - "universalify" "^0.2.0" - "url-parse" "^1.5.3" - -"tr46@^3.0.0": - "integrity" "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==" - "resolved" "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "punycode" "^2.1.1" - -"tslib@^2.0.3": - "integrity" "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" - "version" "2.6.2" - -"universalify@^0.2.0": - "integrity" "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" - "resolved" "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" - "version" "0.2.0" - -"unpipe@~1.0.0": - "integrity" "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - "version" "1.0.0" - -"url-parse@^1.5.3": - "integrity" "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==" - "resolved" "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" - "version" "1.5.10" - dependencies: - "querystringify" "^2.1.1" - "requires-port" "^1.0.0" - -"util-deprecate@^1.0.1": - "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - "version" "1.0.2" - -"utils-merge@1.0.1": - "integrity" "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" - "version" "1.0.1" - -"vary@~1.1.2": - "integrity" "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - "version" "1.1.2" - -"w3c-xmlserializer@^4.0.0": - "integrity" "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==" - "resolved" "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "xml-name-validator" "^4.0.0" - -"warehouse@^5.0.0": - "integrity" "sha512-5BQEQP56bPY+cqocTho4syazuGgSoyKd0y3PsS2j8tGN10HH+CEfJSIY+KUw9D0k4jaVEFMXLz0KqCiUzTYb8A==" - "resolved" "https://registry.npmjs.org/warehouse/-/warehouse-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "bluebird" "^3.7.2" - "cuid" "^2.1.8" - "graceful-fs" "^4.2.10" - "hexo-log" "^4.0.1" - "is-plain-object" "^5.0.0" - "jsonparse" "^1.3.1" - "rfdc" "^1.3.0" - "through2" "^4.0.2" - -"webidl-conversions@^7.0.0": - "integrity" "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" - "version" "7.0.0" - -"whatwg-encoding@^2.0.0": - "integrity" "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==" - "resolved" "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "iconv-lite" "0.6.3" - -"whatwg-mimetype@^3.0.0": - "integrity" "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" - "resolved" "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz" - "version" "3.0.0" - -"whatwg-url@^11.0.0": - "integrity" "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==" - "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" - "version" "11.0.0" - dependencies: - "tr46" "^3.0.0" - "webidl-conversions" "^7.0.0" - -"which@^2.0.1": - "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" - "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "isexe" "^2.0.0" - -"wrappy@1": - "integrity" "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - "version" "1.0.2" - -"ws@^8.11.0": - "integrity" "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==" - "resolved" "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz" - "version" "8.16.0" - -"xml-name-validator@^4.0.0": - "integrity" "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" - "resolved" "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz" - "version" "4.0.0" - -"xmlchars@^2.2.0": - "integrity" "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" - "resolved" "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" - "version" "2.2.0"